diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-13 17:12:12 +0100 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2026-03-13 17:12:12 +0100 |
| commit | ece17875d4e454423f55f0623a456c0433ecd502 (patch) | |
| tree | 732c0432cbf32757344c51b8c01bb18e83e9c0c0 /src/frontend/app/hooks/useGeolocation.ts | |
| parent | 5c670f1b4a237b7a5197dfcf94de92095da95463 (diff) | |
feat: integrate geolocation functionality and enhance map interactions
- Added useGeolocation hook to manage user location and permissions.
- Updated PlannerOverlay to utilize geolocation for setting origin.
- Enhanced NavBar with a new planner route.
- Introduced context menu for map interactions to set routes from current location.
- Improved search functionality in the map with a dedicated search bar.
- Updated localization files with new strings for routing and search features.
Diffstat (limited to 'src/frontend/app/hooks/useGeolocation.ts')
| -rw-r--r-- | src/frontend/app/hooks/useGeolocation.ts | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/frontend/app/hooks/useGeolocation.ts b/src/frontend/app/hooks/useGeolocation.ts new file mode 100644 index 0000000..878420b --- /dev/null +++ b/src/frontend/app/hooks/useGeolocation.ts @@ -0,0 +1,62 @@ +import { useCallback } from "react"; +import { useMap } from "../contexts/MapContext"; +import type { LngLatLike } from "maplibre-gl"; + +export interface UseGeolocationResult { + userLocation: { latitude: number; longitude: number } | null; + hasLocationPermission: boolean; + requestLocation: () => void; +} + +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 + // set as [position.coords.latitude, position.coords.longitude], and AppMap.tsx + // where getLatitude(center) returns center[0]. + return { latitude: loc[0], longitude: loc[1] }; + } + if ("lat" in loc) { + return { + latitude: loc.lat, + longitude: "lng" in loc ? (loc as any).lng : (loc as any).lon, + }; + } + return { latitude: 0, longitude: 0 }; +} + +/** + * Provides the current user location from the global MapContext. + * Location updates are driven by the MapContext's watchPosition subscription + * (started automatically when geolocation permission is granted). + * + * Call `requestLocation()` to prompt the user for permission and start tracking. + */ +export function useGeolocation(): UseGeolocationResult { + const { mapState, setUserLocation, setLocationPermission } = useMap(); + + const requestLocation = useCallback(() => { + if (typeof window === "undefined" || !("geolocation" in navigator)) return; + navigator.geolocation.getCurrentPosition( + (pos) => { + setUserLocation([pos.coords.latitude, pos.coords.longitude]); + setLocationPermission(true); + }, + () => { + setLocationPermission(false); + }, + { enableHighAccuracy: false, maximumAge: 60000, timeout: 10000 } + ); + }, [setUserLocation, setLocationPermission]); + + const rawLoc = mapState.userLocation; + const userLocation = rawLoc ? lngLatToCoords(rawLoc) : null; + + return { + userLocation, + hasLocationPermission: mapState.hasLocationPermission, + requestLocation, + }; +} |
