Initial web

This commit is contained in:
Caesar2011
2026-05-17 19:55:53 +02:00
parent 6e3499812e
commit 20ed6ee9fb
58 changed files with 8541 additions and 0 deletions

83
web/lib/context.tsx Normal file
View File

@@ -0,0 +1,83 @@
'use client';
import React, {
createContext,
useCallback,
useContext,
useEffect,
useState,
} from 'react';
import type { TimeRange, TimeMode, TriggeredAlert } from './types';
import { TIME_RANGE_MS } from './types';
import { checkAlerts } from './api';
import { buildReverseMap } from './localization';
import type { LocaleMap, ReverseMap } from './localization';
interface AppContextValue {
timeRange: TimeRange;
setTimeRange: (r: TimeRange) => void;
timeMode: TimeMode;
setTimeMode: (m: TimeMode) => void;
triggeredAlerts: TriggeredAlert[];
refreshAlerts: () => Promise<void>;
getFromTo: () => { from: string; to: string };
localeMap: LocaleMap;
reverseMap: ReverseMap;
}
const AppContext = createContext<AppContextValue | null>(null);
export function AppProvider({
token: _token,
localeMap,
children,
}: {
token: string;
localeMap: LocaleMap;
children: React.ReactNode;
}) {
const [timeRange, setTimeRange] = useState<TimeRange>('6h');
const [timeMode, setTimeMode] = useState<TimeMode>('real');
const [triggeredAlerts, setTriggeredAlerts] = useState<TriggeredAlert[]>([]);
const reverseMap = buildReverseMap(localeMap);
const getFromTo = useCallback(() => {
const to = new Date();
const from = new Date(to.getTime() - TIME_RANGE_MS[timeRange]);
return { from: from.toISOString(), to: to.toISOString() };
}, [timeRange]);
const refreshAlerts = useCallback(async () => {
setTriggeredAlerts(await checkAlerts());
}, []);
useEffect(() => {
let cancelled = false;
const poll = () => checkAlerts().then(a => { if (!cancelled) setTriggeredAlerts(a); });
poll();
const id = setInterval(poll, 30_000);
return () => { cancelled = true; clearInterval(id); };
}, []);
return (
<AppContext.Provider
value={{
timeRange, setTimeRange,
timeMode, setTimeMode,
triggeredAlerts, refreshAlerts,
getFromTo,
localeMap, reverseMap,
}}
>
{children}
</AppContext.Provider>
);
}
/** Must be used within {@link AppProvider}. */
export function useApp() {
const ctx = useContext(AppContext);
if (!ctx) throw new Error('useApp must be used within AppProvider');
return ctx;
}