import { useEffect, useState } from 'react' import { getAnalytics } from '../api/client.js' import ByDayChart from '../components/charts/ByDayChart.jsx' import ByRouteChart from '../components/charts/ByRouteChart.jsx' import ByTypeChart from '../components/charts/ByTypeChart.jsx' import Spinner from '../components/common/Spinner.jsx' function Kpi({ n, l, color = 'var(--blue)' }) { return (
{n} {l}
) } export default function AnalyticsPage() { const [a, setA] = useState(null) const [err, setErr] = useState('') useEffect(() => { getAnalytics().then(setA).catch((e) => setErr(e.message)) }, []) if (err) return
Failed to load analytics: {err}
if (!a) return
loading analytics…
const confirmed = (a.by_route?.auto_confirmed || 0) + (a.by_route?.vlm_confirmed || 0) const reduction = a.total ? Math.round((100 * confirmed) / a.total) : 0 const plateRate = a.plates_read ? Math.round((100 * (a.plates_valid || 0)) / a.plates_read) : 0 return ( <>
🤖 Human-review reduction: {reduction}% — that share of violations was resolved automatically (auto- or AI-confirmed), with no human needed.
Plate OCR: {a.plate_ocr_enabled ? 'on' : 'off'} · {a.plates_read || 0} read,{' '} {a.plates_valid || 0} valid format ({plateRate}%).
) }