aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/hooks/useGeolocation.ts
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2026-03-13 17:12:12 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2026-03-13 17:12:12 +0100
commitece17875d4e454423f55f0623a456c0433ecd502 (patch)
tree732c0432cbf32757344c51b8c01bb18e83e9c0c0 /src/frontend/app/hooks/useGeolocation.ts
parent5c670f1b4a237b7a5197dfcf94de92095da95463 (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.ts62
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,
+ };
+}