diff options
Diffstat (limited to 'src/frontend/app/contexts/JourneyContext.tsx')
| -rw-r--r-- | src/frontend/app/contexts/JourneyContext.tsx | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/frontend/app/contexts/JourneyContext.tsx b/src/frontend/app/contexts/JourneyContext.tsx new file mode 100644 index 0000000..f513aa8 --- /dev/null +++ b/src/frontend/app/contexts/JourneyContext.tsx @@ -0,0 +1,84 @@ +import { + createContext, + useCallback, + useContext, + useRef, + useState, + type ReactNode, +} from "react"; + +export interface ActiveJourney { + tripId: string; + stopId: string; + stopName: string; + routeShortName: string; + routeColour: string; + routeTextColour: string; + headsignDestination: string | null; + /** Minutes remaining when tracking was started (for display context) */ + initialMinutes: number; + /** Send notification when this many minutes remain (default: 2) */ + notifyAtMinutes: number; + /** Whether the "approaching" notification has already been sent */ + hasNotified: boolean; +} + +interface JourneyContextValue { + activeJourney: ActiveJourney | null; + startJourney: ( + journey: Omit<ActiveJourney, "hasNotified"> + ) => void; + stopJourney: () => void; + markNotified: () => void; +} + +const JourneyContext = createContext<JourneyContextValue | null>(null); + +export function JourneyProvider({ children }: { children: ReactNode }) { + const [activeJourney, setActiveJourney] = useState<ActiveJourney | null>( + null + ); + const notificationRef = useRef<Notification | null>(null); + + const startJourney = useCallback( + (journey: Omit<ActiveJourney, "hasNotified">) => { + // Close any existing notification + if (notificationRef.current) { + notificationRef.current.close(); + notificationRef.current = null; + } + setActiveJourney({ ...journey, hasNotified: false }); + }, + [] + ); + + const stopJourney = useCallback(() => { + if (notificationRef.current) { + notificationRef.current.close(); + notificationRef.current = null; + } + setActiveJourney(null); + }, []); + + const markNotified = useCallback(() => { + setActiveJourney((prev) => + prev ? { ...prev, hasNotified: true } : null + ); + }, []); + + return ( + <JourneyContext.Provider + value={{ activeJourney, startJourney, stopJourney, markNotified }} + > + {children} + </JourneyContext.Provider> + ); +} + +export function useJourney() { + const ctx = useContext(JourneyContext); + if (!ctx) { + throw new Error("useJourney must be used within a JourneyProvider"); + } + return ctx; +} |
