From e4a737f43e45f02e80c06346cea73756f83854f3 Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero <94913521+arielcostas@users.noreply.github.com> Date: Mon, 3 Mar 2025 21:13:28 +0100 Subject: Implement map page --- src/Layout.css | 5 ++- src/pages/Estimates.tsx | 16 +++---- src/pages/Map.tsx | 103 +++++++++++++++--------------------------- src/styles/Pages.css | 116 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/Layout.css b/src/Layout.css index ab4eecd..7af97b8 100644 --- a/src/Layout.css +++ b/src/Layout.css @@ -9,8 +9,7 @@ .main-content { flex: 1; overflow: auto; - padding: 16px; - padding-bottom: 70px; /* Extra padding to ensure content isn't hidden behind navbar */ + padding-bottom: 60px; /* Extra padding to ensure content isn't hidden behind navbar */ } .nav-bar { @@ -18,6 +17,8 @@ bottom: 0; left: 0; right: 0; + z-index: 5; + background-color: var(--background-color); display: flex; justify-content: space-around; diff --git a/src/pages/Estimates.tsx b/src/pages/Estimates.tsx index d3b4ced..3f002be 100644 --- a/src/pages/Estimates.tsx +++ b/src/pages/Estimates.tsx @@ -23,13 +23,17 @@ interface StopDetails { export function Estimates(): JSX.Element { const sdp = new StopDataProvider(); const [data, setData] = useState(null); + const [dataDate, setDataDate] = useState(null); const [favourited, setFavourited] = useState(false); const params = useParams(); const loadData = () => { fetch(`/api/GetStopEstimates?id=${params.stopId}`) .then(r => r.json()) - .then((body: StopDetails) => setData(body)); + .then((body: StopDetails) => { + setData(body); + setDataDate(new Date()); + }); }; useEffect(() => { @@ -80,17 +84,9 @@ export function Estimates(): JSX.Element { -
- - 🔙 Volver al listado de paradas - - - -
-
- + diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index dbf5b9f..4d89ae0 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -1,76 +1,47 @@ -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate } from "react-router"; -import { Stop, StopDataProvider } from "../data/StopDataProvider"; -import LineIcon from "../components/LineIcon"; +import { StopDataProvider, Stop } from "../data/StopDataProvider"; + +import 'leaflet/dist/leaflet.css' +import 'react-leaflet-markercluster/styles' + +import { useEffect, useState } from 'react'; +import LineIcon from '../components/LineIcon'; +import { Link } from 'react-router'; +import { MapContainer } from "react-leaflet/MapContainer"; +import { TileLayer } from "react-leaflet/TileLayer"; +import { Marker } from "react-leaflet/Marker"; +import { Popup } from "react-leaflet/Popup"; +import MarkerClusterGroup from "react-leaflet-markercluster"; const sdp = new StopDataProvider(); export function StopMap() { - const [data, setData] = useState(null) - const navigate = useNavigate(); + const [stops, setStops] = useState([]); + const position = [42.229188855975046, -8.72246955783102] useEffect(() => { - sdp.getStops().then((stops: Stop[]) => setData(stops)) + sdp.getStops().then((stops) => { setStops(stops); }); }, []); - const handleStopSearch = async (event: React.FormEvent) => { - event.preventDefault() - - const stopId = (event.target as HTMLFormElement).stopId.value - const searchNumber = parseInt(stopId) - if (data?.find(stop => stop.stopId === searchNumber)) { - navigate(`/estimates/${searchNumber}`) - } else { - alert("Parada no encontrada") - } - } - - if (data === null) return

Loading...

- return ( -
-

Map View

- -
- {/* Map placeholder - in a real implementation, this would be a map component */} -
-

Map will be displayed here

-
-
- -
-
- - -
- - - - -
-

Nearby Stops

-
    - {data?.slice(0, 5).map((stop: Stop) => ( -
  • - - ({stop.stopId}) {stop.name} -
    - {stop.lines?.map(line => )} -
    - -
  • - ))} -
-
-
- ) + + + + {stops.map((stop) => ( + + + {stop.name} +
+ {stop.lines.map((line) => ( + + ))} +
+
+ ))} +
+ +
+ ); } diff --git a/src/styles/Pages.css b/src/styles/Pages.css index 9bae8a3..a8ff842 100644 --- a/src/styles/Pages.css +++ b/src/styles/Pages.css @@ -130,6 +130,11 @@ body { color: var(--text-color); } +.distance-info { + font-size: 0.9rem; + color: var(--subtitle-color); +} + /* Message styles */ .message { padding: 1rem; @@ -160,6 +165,117 @@ body { height: calc(100vh - 140px); margin: -16px; margin-bottom: 1rem; + position: relative; +} + +#map { + position: absolute; + top: 0; + bottom: 60px; /* Adjust this value based on your navbar height */ + left: 0; + right: 0; + height: calc(100vh - 60px); /* Adjust this value based on your navbar height */ + overflow: hidden; + z-index: 0; +} + +.main-content { + position: relative; + height: calc(100vh - 60px); /* Adjust this value based on your navbar height */ + overflow: hidden; +} + +.nav-bar { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 60px; /* Adjust this value based on your navbar height */ + display: flex; + justify-content: space-around; + align-items: center; + background-color: #fff; + border-top: 1px solid #ccc; + z-index: 1; +} + +/* Fullscreen map styles */ +.fullscreen-container { + position: absolute; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + padding: 0; + margin: 0; + max-width: none; + overflow: hidden; +} + +.fullscreen-map { + width: 100%; + height: 100%; +} + +.fullscreen-loading { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + width: 100vw; + font-size: 1.8rem; + font-weight: 600; + color: var(--text-color); +} + +/* Map marker and popup styles */ +.stop-marker { + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); + transition: all 0.2s ease-in-out; +} + +.stop-marker:hover { + transform: scale(1.2); +} + +.maplibregl-popup { + max-width: 250px; +} + +.maplibregl-popup-content { + padding: 12px; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.popup-line-icons { + display: flex; + flex-wrap: wrap; + margin: 6px 0; + gap: 5px; +} + +.popup-line { + display: inline-block; + background-color: var(--button-background-color); + color: white; + padding: 2px 6px; + margin-right: 4px; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 500; +} + +.popup-link { + display: block; + margin-top: 8px; + color: var(--button-background-color); + text-decoration: none; + font-weight: 500; +} + +.popup-link:hover { + text-decoration: underline; } /* Estimates page specific styles */ -- cgit v1.3
Estimaciones de llegadasEstimaciones de llegadas a las {dataDate?.toLocaleTimeString()}