aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/AppContext.tsx
diff options
context:
space:
mode:
authorCopilot <198982749+Copilot@users.noreply.github.com>2025-06-26 23:44:25 +0200
committerGitHub <noreply@github.com>2025-06-26 23:44:25 +0200
commit7b8594debceb93a1fa400d48fe1dcff943bd5af6 (patch)
tree73e68c7238a91d8931d669364d395ce2994164f4 /src/frontend/app/AppContext.tsx
parent3dac17a9fb54c977c97280ed4c482e9d4266b7de (diff)
Implement stop sheet modal for map stop interactions (#27)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: arielcostas <94913521+arielcostas@users.noreply.github.com> Co-authored-by: Ariel Costas Guerrero <ariel@costas.dev>
Diffstat (limited to 'src/frontend/app/AppContext.tsx')
-rw-r--r--src/frontend/app/AppContext.tsx122
1 files changed, 68 insertions, 54 deletions
diff --git a/src/frontend/app/AppContext.tsx b/src/frontend/app/AppContext.tsx
index d8db66d..e6d8971 100644
--- a/src/frontend/app/AppContext.tsx
+++ b/src/frontend/app/AppContext.tsx
@@ -1,10 +1,16 @@
/* eslint-disable react-refresh/only-export-components */
-import { createContext, useContext, useEffect, useState, type ReactNode } from 'react';
-import { type LngLatLike } from 'maplibre-gl';
+import {
+ createContext,
+ useContext,
+ useEffect,
+ useState,
+ type ReactNode,
+} from "react";
+import { type LngLatLike } from "maplibre-gl";
-type Theme = 'light' | 'dark';
-type TableStyle = 'regular'|'grouped';
-type MapPositionMode = 'gps' | 'last';
+type Theme = "light" | "dark";
+type TableStyle = "regular" | "grouped";
+type MapPositionMode = "gps" | "last";
interface MapState {
center: LngLatLike;
@@ -42,56 +48,62 @@ const AppContext = createContext<AppContextProps | undefined>(undefined);
export const AppProvider = ({ children }: { children: ReactNode }) => {
//#region Theme
const [theme, setTheme] = useState<Theme>(() => {
- const savedTheme = localStorage.getItem('theme');
+ const savedTheme = localStorage.getItem("theme");
if (savedTheme) {
return savedTheme as Theme;
}
- const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
- return prefersDark ? 'dark' : 'light';
+ const prefersDark =
+ window.matchMedia &&
+ window.matchMedia("(prefers-color-scheme: dark)").matches;
+ return prefersDark ? "dark" : "light";
});
const toggleTheme = () => {
- setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
+ setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
useEffect(() => {
- document.documentElement.setAttribute('data-theme', theme);
- localStorage.setItem('theme', theme);
+ document.documentElement.setAttribute("data-theme", theme);
+ localStorage.setItem("theme", theme);
}, [theme]);
//#endregion
//#region Table Style
const [tableStyle, setTableStyle] = useState<TableStyle>(() => {
- const savedTableStyle = localStorage.getItem('tableStyle');
+ const savedTableStyle = localStorage.getItem("tableStyle");
if (savedTableStyle) {
return savedTableStyle as TableStyle;
}
- return 'regular';
+ return "regular";
});
const toggleTableStyle = () => {
- setTableStyle((prevTableStyle) => (prevTableStyle === 'regular' ? 'grouped' : 'regular'));
- }
+ setTableStyle((prevTableStyle) =>
+ prevTableStyle === "regular" ? "grouped" : "regular",
+ );
+ };
useEffect(() => {
- localStorage.setItem('tableStyle', tableStyle);
+ localStorage.setItem("tableStyle", tableStyle);
}, [tableStyle]);
//#endregion
//#region Map Position Mode
- const [mapPositionMode, setMapPositionMode] = useState<MapPositionMode>(() => {
- const saved = localStorage.getItem('mapPositionMode');
- return saved === 'last' ? 'last' : 'gps';
- });
+ const [mapPositionMode, setMapPositionMode] = useState<MapPositionMode>(
+ () => {
+ const saved = localStorage.getItem("mapPositionMode");
+ return saved === "last" ? "last" : "gps";
+ },
+ );
useEffect(() => {
- localStorage.setItem('mapPositionMode', mapPositionMode);
+ localStorage.setItem("mapPositionMode", mapPositionMode);
}, [mapPositionMode]);
//#endregion
//#region Map State
const [mapState, setMapState] = useState<MapState>(() => {
- const savedMapState = localStorage.getItem('mapState');
+ const savedMapState = localStorage.getItem("mapState");
if (savedMapState) {
try {
const parsed = JSON.parse(savedMapState);
@@ -99,56 +111,56 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
center: parsed.center || DEFAULT_CENTER,
zoom: parsed.zoom || DEFAULT_ZOOM,
userLocation: parsed.userLocation || null,
- hasLocationPermission: parsed.hasLocationPermission || false
+ hasLocationPermission: parsed.hasLocationPermission || false,
};
} catch (e) {
- console.error('Error parsing saved map state', e);
+ console.error("Error parsing saved map state", e);
}
}
return {
center: DEFAULT_CENTER,
zoom: DEFAULT_ZOOM,
userLocation: null,
- hasLocationPermission: false
+ hasLocationPermission: false,
};
});
const setMapCenter = (center: LngLatLike) => {
- setMapState(prev => {
+ setMapState((prev) => {
const newState = { ...prev, center };
- localStorage.setItem('mapState', JSON.stringify(newState));
+ localStorage.setItem("mapState", JSON.stringify(newState));
return newState;
});
};
const setMapZoom = (zoom: number) => {
- setMapState(prev => {
+ setMapState((prev) => {
const newState = { ...prev, zoom };
- localStorage.setItem('mapState', JSON.stringify(newState));
+ localStorage.setItem("mapState", JSON.stringify(newState));
return newState;
});
};
const setUserLocation = (userLocation: LngLatLike | null) => {
- setMapState(prev => {
+ setMapState((prev) => {
const newState = { ...prev, userLocation };
- localStorage.setItem('mapState', JSON.stringify(newState));
+ localStorage.setItem("mapState", JSON.stringify(newState));
return newState;
});
};
const setLocationPermission = (hasLocationPermission: boolean) => {
- setMapState(prev => {
+ setMapState((prev) => {
const newState = { ...prev, hasLocationPermission };
- localStorage.setItem('mapState', JSON.stringify(newState));
+ localStorage.setItem("mapState", JSON.stringify(newState));
return newState;
});
};
const updateMapState = (center: LngLatLike, zoom: number) => {
- setMapState(prev => {
+ setMapState((prev) => {
const newState = { ...prev, center, zoom };
- localStorage.setItem('mapState', JSON.stringify(newState));
+ localStorage.setItem("mapState", JSON.stringify(newState));
return newState;
});
};
@@ -164,31 +176,33 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
setUserLocation([latitude, longitude]);
},
(error) => {
- console.error('Error getting location:', error);
+ console.error("Error getting location:", error);
setLocationPermission(false);
- }
+ },
);
}
}
}, [mapState.hasLocationPermission, mapState.userLocation]);
return (
- <AppContext.Provider value={{
- theme,
- setTheme,
- toggleTheme,
- tableStyle,
- setTableStyle,
- toggleTableStyle,
- mapState,
- setMapCenter,
- setMapZoom,
- setUserLocation,
- setLocationPermission,
- updateMapState,
- mapPositionMode,
- setMapPositionMode
- }}>
+ <AppContext.Provider
+ value={{
+ theme,
+ setTheme,
+ toggleTheme,
+ tableStyle,
+ setTableStyle,
+ toggleTableStyle,
+ mapState,
+ setMapCenter,
+ setMapZoom,
+ setUserLocation,
+ setLocationPermission,
+ updateMapState,
+ mapPositionMode,
+ setMapPositionMode,
+ }}
+ >
{children}
</AppContext.Provider>
);
@@ -197,7 +211,7 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
export const useApp = () => {
const context = useContext(AppContext);
if (!context) {
- throw new Error('useApp must be used within a AppProvider');
+ throw new Error("useApp must be used within a AppProvider");
}
return context;
};