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 ) => void; stopJourney: () => void; markNotified: () => void; } const JourneyContext = createContext(null); export function JourneyProvider({ children }: { children: ReactNode }) { const [activeJourney, setActiveJourney] = useState( null ); const notificationRef = useRef(null); const startJourney = useCallback( (journey: Omit) => { // 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 ( {children} ); } export function useJourney() { const ctx = useContext(JourneyContext); if (!ctx) { throw new Error("useJourney must be used within a JourneyProvider"); } return ctx; }