/** * TimezoneProvider. * * Fetches the IANA timezone configured during the BanGUI setup wizard and * makes it available throughout the component tree via React Context. * * The timezone is fetched once at mount. On error or before the initial * fetch resolves, the value defaults to ``"UTC"`` so date-formatting callers * always receive a safe fallback. */ import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react"; import { fetchTimezone } from "../api/setup"; // --------------------------------------------------------------------------- // Context definition // --------------------------------------------------------------------------- interface TimezoneContextValue { /** IANA timezone string, e.g. ``"Europe/Berlin"`` or ``"UTC"``. */ timezone: string; } const TimezoneContext = createContext({ timezone: "UTC" }); // --------------------------------------------------------------------------- // Provider // --------------------------------------------------------------------------- export interface TimezoneProviderProps { children: React.ReactNode; } /** * Wrap the application (or authenticated shell) with this provider to make the * configured timezone available via {@link useTimezone}. * * @example * ```tsx * * * * ``` */ export function TimezoneProvider({ children, }: TimezoneProviderProps): React.JSX.Element { const [timezone, setTimezone] = useState("UTC"); const load = useCallback((): void => { fetchTimezone() .then((resp) => { setTimezone(resp.timezone); }) .catch(() => { // Silently fall back to UTC; the backend may not be reachable yet. }); }, []); useEffect(() => { load(); }, [load]); const value = useMemo(() => ({ timezone }), [timezone]); return ( {children} ); } // --------------------------------------------------------------------------- // Hook // --------------------------------------------------------------------------- /** * Return the IANA timezone string configured during setup. * * Must be used inside a {@link TimezoneProvider}. * * @returns The configured timezone, e.g. ``"Europe/Berlin"``. * * @example * ```tsx * const { timezone } = useTimezone(); * const label = formatDate(item.created_at, timezone); * ``` */ export function useTimezone(): string { return useContext(TimezoneContext).timezone; }