From ac626a9c2edc2e528eb0b39002c836a747b2fc16 Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Mon, 16 Mar 2026 14:13:26 +0100 Subject: feat: enhance geolocation handling with loading state and improve button click behavior --- src/frontend/app/components/PlannerOverlay.tsx | 8 +++++--- src/frontend/app/components/shared/AppMap.tsx | 9 +++++---- src/frontend/app/contexts/MapContext.tsx | 2 +- src/frontend/app/hooks/useGeolocation.ts | 17 ++++++++++++----- 4 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src/frontend') diff --git a/src/frontend/app/components/PlannerOverlay.tsx b/src/frontend/app/components/PlannerOverlay.tsx index d953c2e..d42bd94 100644 --- a/src/frontend/app/components/PlannerOverlay.tsx +++ b/src/frontend/app/components/PlannerOverlay.tsx @@ -534,7 +534,7 @@ export const PlannerOverlay: React.FC = ({ diff --git a/src/frontend/app/components/shared/AppMap.tsx b/src/frontend/app/components/shared/AppMap.tsx index f4c8658..8d0aa64 100644 --- a/src/frontend/app/components/shared/AppMap.tsx +++ b/src/frontend/app/components/shared/AppMap.tsx @@ -8,6 +8,7 @@ import { useRef, useState, } from "react"; +import { useTranslation } from "react-i18next"; import Map, { GeolocateControl, NavigationControl, @@ -15,7 +16,6 @@ import Map, { type MapRef, type StyleSpecification, } from "react-map-gl/maplibre"; -import { useTranslation } from "react-i18next"; import { useLocation } from "react-router"; import { useApp } from "~/AppContext"; import { APP_CONSTANTS } from "~/config/constants"; @@ -82,7 +82,6 @@ export const AppMap = forwardRef( mapState, updateMapState, setUserLocation, - setLocationPermission, showTraffic: settingsShowTraffic, showCameras: settingsShowCameras, mapPositionMode, @@ -213,11 +212,13 @@ export const AppMap = forwardRef( {showGeolocate && ( { const { latitude, longitude } = e.coords; setUserLocation([latitude, longitude]); - setLocationPermission(true); }} /> )} diff --git a/src/frontend/app/contexts/MapContext.tsx b/src/frontend/app/contexts/MapContext.tsx index d93fefc..2c199be 100644 --- a/src/frontend/app/contexts/MapContext.tsx +++ b/src/frontend/app/contexts/MapContext.tsx @@ -72,6 +72,7 @@ export const MapProvider = ({ children }: { children: ReactNode }) => { const setLocationPermission = useCallback( (hasLocationPermission: boolean) => { setMapState((prev) => { + if (prev.hasLocationPermission === hasLocationPermission) return prev; const newState = { ...prev, hasLocationPermission }; localStorage.setItem("mapState", JSON.stringify(newState)); return newState; @@ -103,7 +104,6 @@ export const MapProvider = ({ children }: { children: ReactNode }) => { (position) => { const { latitude, longitude } = position.coords; setUserLocation([latitude, longitude]); - setLocationPermission(true); }, (error) => { if (error.code === GeolocationPositionError.PERMISSION_DENIED) { diff --git a/src/frontend/app/hooks/useGeolocation.ts b/src/frontend/app/hooks/useGeolocation.ts index 878420b..78e9096 100644 --- a/src/frontend/app/hooks/useGeolocation.ts +++ b/src/frontend/app/hooks/useGeolocation.ts @@ -1,16 +1,18 @@ -import { useCallback } from "react"; -import { useMap } from "../contexts/MapContext"; import type { LngLatLike } from "maplibre-gl"; +import { useCallback, useState } from "react"; +import { useMap } from "../contexts/MapContext"; export interface UseGeolocationResult { userLocation: { latitude: number; longitude: number } | null; hasLocationPermission: boolean; + isLoading: boolean; requestLocation: () => void; } -function lngLatToCoords( - loc: LngLatLike -): { latitude: number; longitude: number } { +function lngLatToCoords(loc: LngLatLike): { + latitude: number; + longitude: number; +} { if (Array.isArray(loc)) { // This codebase stores location as [latitude, longitude] (not the standard // MapLibre [lng, lat] GeoJSON order). See MapContext.tsx where arrays are @@ -36,16 +38,20 @@ function lngLatToCoords( */ export function useGeolocation(): UseGeolocationResult { const { mapState, setUserLocation, setLocationPermission } = useMap(); + const [isLoading, setIsLoading] = useState(false); const requestLocation = useCallback(() => { if (typeof window === "undefined" || !("geolocation" in navigator)) return; + setIsLoading(true); navigator.geolocation.getCurrentPosition( (pos) => { setUserLocation([pos.coords.latitude, pos.coords.longitude]); setLocationPermission(true); + setIsLoading(false); }, () => { setLocationPermission(false); + setIsLoading(false); }, { enableHighAccuracy: false, maximumAge: 60000, timeout: 10000 } ); @@ -57,6 +63,7 @@ export function useGeolocation(): UseGeolocationResult { return { userLocation, hasLocationPermission: mapState.hasLocationPermission, + isLoading, requestLocation, }; } -- cgit v1.3