From b96273b54a9b47c79e0afe40a918f751e82097ae Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 18:02:36 +0100 Subject: Link previous trip shapes for GPS positioning on circular routes (#111) Co-authored-by: Ariel Costas Guerrero Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: arielcostas <94913521+arielcostas@users.noreply.github.com> --- src/frontend/app/components/layout/AppShell.css | 10 --- src/frontend/app/components/layout/AppShell.tsx | 4 +- .../app/components/layout/NavBar.module.css | 46 ++++++++++ src/frontend/app/components/layout/NavBar.tsx | 99 ++++++++++++++++++++++ 4 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 src/frontend/app/components/layout/NavBar.module.css create mode 100644 src/frontend/app/components/layout/NavBar.tsx (limited to 'src/frontend/app/components/layout') diff --git a/src/frontend/app/components/layout/AppShell.css b/src/frontend/app/components/layout/AppShell.css index 89a4d1f..eee678c 100644 --- a/src/frontend/app/components/layout/AppShell.css +++ b/src/frontend/app/components/layout/AppShell.css @@ -50,14 +50,4 @@ .app-shell__bottom-nav { display: none; } - - /* Override NavBar styles for sidebar */ - .app-shell__sidebar .navigation-bar { - flex-direction: column; - height: 100%; - justify-content: flex-start; - padding-top: 1rem; - gap: 1rem; - border-top: none; - } } diff --git a/src/frontend/app/components/layout/AppShell.tsx b/src/frontend/app/components/layout/AppShell.tsx index e0559ac..91f6c0d 100644 --- a/src/frontend/app/components/layout/AppShell.tsx +++ b/src/frontend/app/components/layout/AppShell.tsx @@ -1,11 +1,11 @@ import React, { useState } from "react"; import { Outlet } from "react-router"; import { PageTitleProvider, usePageTitleContext } from "~/contexts/PageTitleContext"; -import NavBar from "../NavBar"; import { ThemeColorManager } from "../ThemeColorManager"; import "./AppShell.css"; import { Drawer } from "./Drawer"; import { Header } from "./Header"; +import NavBar from "./NavBar"; const AppShellContent: React.FC = () => { const { title } = usePageTitleContext(); @@ -22,7 +22,7 @@ const AppShellContent: React.FC = () => { setIsDrawerOpen(false)} />
diff --git a/src/frontend/app/components/layout/NavBar.module.css b/src/frontend/app/components/layout/NavBar.module.css new file mode 100644 index 0000000..504b93b --- /dev/null +++ b/src/frontend/app/components/layout/NavBar.module.css @@ -0,0 +1,46 @@ +.navBar { + display: flex; + justify-content: space-around; + align-items: center; + padding: 0.5rem 0; + + background-color: var(--background-color); + border-top: 1px solid var(--border-color); +} + +.vertical { + flex-direction: column; + height: 100%; + justify-content: flex-start; + padding-top: 1rem; + gap: 1rem; + border-top: none; +} + +.link { + flex: 1 0; + display: flex; + flex-direction: column; + align-items: center; + text-decoration: none; + color: var(--text-color); + padding: 0.25rem 0; + border-radius: 0.5rem; +} + +.link svg { + width: 1.375rem; + height: 1.375rem; + fill: none; + stroke-width: 2; +} + +.link span { + font-size: 13px; + line-height: 1; + font-family: system-ui; +} + +.active { + color: var(--button-background-color); +} diff --git a/src/frontend/app/components/layout/NavBar.tsx b/src/frontend/app/components/layout/NavBar.tsx new file mode 100644 index 0000000..91c8810 --- /dev/null +++ b/src/frontend/app/components/layout/NavBar.tsx @@ -0,0 +1,99 @@ +import { Map, MapPin, Settings } from "lucide-react"; +import type { LngLatLike } from "maplibre-gl"; +import { useTranslation } from "react-i18next"; +import { Link, useLocation } from "react-router"; +import { useApp } from "../../AppContext"; +import styles from "./NavBar.module.css"; + +// Helper: check if coordinates are within Vigo bounds +function isWithinVigo(lngLat: LngLatLike): boolean { + let lng: number, lat: number; + if (Array.isArray(lngLat)) { + [lng, lat] = lngLat; + } else if ("lng" in lngLat && "lat" in lngLat) { + lng = lngLat.lng; + lat = lngLat.lat; + } else { + return false; + } + // Rough bounding box for Vigo + return lat >= 42.18 && lat <= 42.3 && lng >= -8.78 && lng <= -8.65; +} + +interface NavBarProps { + orientation?: "horizontal" | "vertical"; +} + +export default function NavBar({ orientation = "horizontal" }: NavBarProps) { + const { t } = useTranslation(); + const { mapState, updateMapState, mapPositionMode } = useApp(); + const location = useLocation(); + + const navItems = [ + { + name: t("navbar.stops", "Paradas"), + icon: MapPin, + path: "/", + exact: true, + }, + { + name: t("navbar.map", "Mapa"), + icon: Map, + path: "/map", + callback: () => { + if (mapPositionMode !== "gps") { + return; + } + + if (!("geolocation" in navigator)) { + return; + } + + navigator.geolocation.getCurrentPosition( + (position) => { + const { latitude, longitude } = position.coords; + const coords: LngLatLike = [latitude, longitude]; + if (isWithinVigo(coords)) { + updateMapState(coords, 16); + } + }, + () => {} + ); + }, + }, + { + name: t("navbar.settings", "Ajustes"), + icon: Settings, + path: "/settings", + }, + ]; + + return ( + + ); +} -- cgit v1.3