'use client'; import 'uplot/dist/uPlot.min.css'; import { useState, useEffect } from 'react'; import uPlot from 'uplot'; import { CardShell } from './CardShell'; import { makeYScale, makeAnnotationHooks, makeSignalsSeries, makeSignalsAxes, CURSOR_NO_DRAG, } from './plotHelpers'; import { buildSeriesData } from './seriesData'; import { usePlot } from './usePlot'; import type { ColorMap } from '@/lib/colors'; import type { AlertConfig, ChartConfig, SessionBoundary, SignalRow, TimeMode } from '@/lib/types'; import { getColorMap } from '@/lib/colors'; import { useApp } from '@/lib/context'; import { resolveName } from '@/lib/localization'; interface Props { config: ChartConfig; rows: SignalRow[]; sessions: SessionBoundary[]; alerts: AlertConfig[]; timeMode: TimeMode; onEdit: () => void; onDelete: () => void; } export default function SignalsChart({ config, rows, sessions, alerts, timeMode, onEdit, onDelete, }: Props) { const { localeMap } = useApp(); const locale = typeof navigator !== 'undefined' ? navigator.language : 'de-DE'; const [colorMap, setColorMap] = useState(new Map()); useEffect(() => { getColorMap().then(setColorMap); }, []); const { containerRef, legendRef } = usePlot( (el, w, h, lRef) => { const data = buildSeriesData(rows, config.signal_type, timeMode); if (!data) return null; const { keys, allXs, data: seriesData } = data; const sessionXs = sessions.map((s) => timeMode === 'tick' ? s.game_tick : new Date(s.real_time).getTime() / 1000, ); const alertThresholds = alerts .filter((a) => config.signal_type === 'both' || config.signal_type === a.signal_type) .map((a) => a.threshold); return new uPlot( { width: w, height: h, cursor: CURSOR_NO_DRAG, legend: { mount: (_u, legendEl) => { if (lRef.current) lRef.current.appendChild(legendEl); }, }, series: makeSignalsSeries(keys, timeMode, (key) => resolveName(key, localeMap), colorMap), axes: makeSignalsAxes(timeMode, locale), scales: { x: { time: false }, y: makeYScale(config.y_min ?? null, config.y_max ?? null, config.y_scale), }, hooks: makeAnnotationHooks(sessionXs, alertThresholds), }, [allXs, ...seriesData], el, ); }, [ rows, sessions, alerts, config.signal_type, config.y_min, config.y_max, config.y_scale, timeMode, localeMap, ], ); return (
} className="w-full h-full" /> ); }