From 2b6e41184c3826de6e17b80d82e495bb47ba0db4 Mon Sep 17 00:00:00 2001
From: Ariel Costas Guerrero <ariel@costas.dev>
Date: Sun, 13 Apr 2025 11:25:50 +0000
Subject: feat: Add map state management and enhanced location control

---
 src/AppContext.tsx | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 116 insertions(+), 1 deletion(-)

(limited to 'src/AppContext.tsx')

diff --git a/src/AppContext.tsx b/src/AppContext.tsx
index 74fb00c..4ff391b 100644
--- a/src/AppContext.tsx
+++ b/src/AppContext.tsx
@@ -1,9 +1,17 @@
 /* eslint-disable react-refresh/only-export-components */
 import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
+import { LatLngTuple } from 'leaflet';
 
 type Theme = 'light' | 'dark';
 type TableStyle = 'regular'|'grouped';
 
+interface MapState {
+  center: LatLngTuple;
+  zoom: number;
+  userLocation: LatLngTuple | null;
+  hasLocationPermission: boolean;
+}
+
 interface AppContextProps {
   theme: Theme;
   setTheme: React.Dispatch<React.SetStateAction<Theme>>;
@@ -12,8 +20,19 @@ interface AppContextProps {
   tableStyle: TableStyle;
   setTableStyle: React.Dispatch<React.SetStateAction<TableStyle>>;
   toggleTableStyle: () => void;
+
+  mapState: MapState;
+  setMapCenter: (center: LatLngTuple) => void;
+  setMapZoom: (zoom: number) => void;
+  setUserLocation: (location: LatLngTuple | null) => void;
+  setLocationPermission: (hasPermission: boolean) => void;
+  updateMapState: (center: LatLngTuple, zoom: number) => void;
 }
 
+// Coordenadas por defecto centradas en Vigo
+const DEFAULT_CENTER: LatLngTuple = [42.229188855975046, -8.72246955783102];
+const DEFAULT_ZOOM = 14;
+
 const AppContext = createContext<AppContextProps | undefined>(undefined);
 
 export const AppProvider = ({ children }: { children: ReactNode }) => {
@@ -55,8 +74,104 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
   }, [tableStyle]);
   //#endregion
 
+  //#region Map State
+  const [mapState, setMapState] = useState<MapState>(() => {
+    const savedMapState = localStorage.getItem('mapState');
+    if (savedMapState) {
+      try {
+        const parsed = JSON.parse(savedMapState);
+        return {
+          center: parsed.center || DEFAULT_CENTER,
+          zoom: parsed.zoom || DEFAULT_ZOOM,
+          userLocation: parsed.userLocation || null,
+          hasLocationPermission: parsed.hasLocationPermission || false
+        };
+      } catch (e) {
+        console.error('Error parsing saved map state', e);
+      }
+    }
+    return {
+      center: DEFAULT_CENTER,
+      zoom: DEFAULT_ZOOM,
+      userLocation: null,
+      hasLocationPermission: false
+    };
+  });
+
+  const setMapCenter = (center: LatLngTuple) => {
+    setMapState(prev => {
+      const newState = { ...prev, center };
+      localStorage.setItem('mapState', JSON.stringify(newState));
+      return newState;
+    });
+  };
+
+  const setMapZoom = (zoom: number) => {
+    setMapState(prev => {
+      const newState = { ...prev, zoom };
+      localStorage.setItem('mapState', JSON.stringify(newState));
+      return newState;
+    });
+  };
+
+  const setUserLocation = (userLocation: LatLngTuple | null) => {
+    setMapState(prev => {
+      const newState = { ...prev, userLocation };
+      localStorage.setItem('mapState', JSON.stringify(newState));
+      return newState;
+    });
+  };
+
+  const setLocationPermission = (hasLocationPermission: boolean) => {
+    setMapState(prev => {
+      const newState = { ...prev, hasLocationPermission };
+      localStorage.setItem('mapState', JSON.stringify(newState));
+      return newState;
+    });
+  };
+
+  const updateMapState = (center: LatLngTuple, zoom: number) => {
+    setMapState(prev => {
+      const newState = { ...prev, center, zoom };
+      localStorage.setItem('mapState', JSON.stringify(newState));
+      return newState;
+    });
+  };
+  //#endregion
+
+  // Tratar de obtener la ubicación del usuario cuando se carga la aplicación si ya se había concedido permiso antes
+  useEffect(() => {
+    if (mapState.hasLocationPermission && !mapState.userLocation) {
+      if (navigator.geolocation) {
+        navigator.geolocation.getCurrentPosition(
+          (position) => {
+            const { latitude, longitude } = position.coords;
+            setUserLocation([latitude, longitude]);
+          },
+          (error) => {
+            console.error('Error getting location:', error);
+            setLocationPermission(false);
+          }
+        );
+      }
+    }
+  }, []);
+
   return (
-    <AppContext.Provider value={{ theme, setTheme, toggleTheme, tableStyle, setTableStyle, toggleTableStyle }}>
+    <AppContext.Provider value={{ 
+      theme, 
+      setTheme, 
+      toggleTheme, 
+      tableStyle, 
+      setTableStyle, 
+      toggleTableStyle,
+      mapState,
+      setMapCenter,
+      setMapZoom,
+      setUserLocation,
+      setLocationPermission,
+      updateMapState
+    }}>
       {children}
     </AppContext.Provider>
   );
-- 
cgit v1.3

