"use client"; import { useEffect, useRef, useState } from "react"; import { clientApi } from "@/lib/client-api"; import { cx, formatCompact, formatDuration, formatInt } from "@/lib/format"; import type { Stats } from "@/lib/types"; function Counter({ value, format }: { value: number; format: (n: number) => string }) { const [display, setDisplay] = useState(value); const from = useRef(value); useEffect(() => { const start = from.current; const delta = value - start; if (!delta) return; const t0 = performance.now(); let raf = 0; const step = (t: number) => { const k = Math.min(1, (t - t0) / 600); setDisplay(start + delta * (1 - (1 - k) ** 3)); if (k < 1) raf = requestAnimationFrame(step); else from.current = value; }; raf = requestAnimationFrame(step); return () => cancelAnimationFrame(raf); }, [value]); return {format(display)}; } /** Homepage telemetry — every number comes from GET /v1/stats (refreshed every 5 s). */ export function TelemetryStrip({ initial, className }: { initial: Stats; className?: string }) { const [s, setS] = useState(initial); useEffect(() => { let alive = true; const t = setInterval(() => clientApi("/v1/stats").then((x) => alive && setS(x)).catch(() => {}), 5000); return () => { alive = false; clearInterval(t); }; }, []); const items: Array<{ label: string; value: number; format: (n: number) => string; sub?: string }> = [ { label: "Instruments", value: s.instruments_total, format: formatInt, sub: `${formatInt(s.instruments_quoted)} quoted · ${formatInt(s.instruments_live)} live` }, { label: "Exchanges", value: s.exchanges_total, format: formatInt, sub: `${s.exchanges_open} open now` }, { label: "Active connectors", value: s.connectors_healthy, format: formatInt, sub: `${s.connectors_total} connectors · ${s.sources_total} sources` }, { label: "Observations today", value: s.observations_today, format: (n) => formatCompact(n, 2), sub: `${s.observations_per_sec.toFixed(1)} / sec` }, { label: "Events · 24h", value: s.events_24h, format: formatInt, sub: `${s.filings_24h} filings` }, { label: "Median freshness", value: s.median_freshness_ms ?? 0, format: (n) => (s.median_freshness_ms == null ? "—" : formatDuration(n)), sub: "real-time quotes" }, ]; return (
{items.map((it) => (
{it.label}
{it.sub &&
{it.sub}
}
))}
); }