"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}
}
))}
);
}