"use client"; import { motion } from "framer-motion"; import { useEffect, useState } from "react"; import { Donut } from "@/components/dashboard/donut"; import { Gauge } from "@/components/dashboard/gauge"; import { Sparkline } from "@/components/dashboard/sparkline"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { AnimatedNumber } from "@/components/ui/motion-primitives"; import { type DashboardData, gaugeColor, safeDur, serviceIndicator, } from "@/lib/dashboard/types"; const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.06, delayChildren: 0.08, }, }, }; const cardVariants = { hidden: { opacity: 0, y: 16, scale: 0.98 }, visible: { opacity: 1, y: 0, scale: 1, transition: { duration: 0.4, ease: [0.25, 0.1, 0, 1] as const }, }, }; export default function Dashboard() { const [data, setData] = useState(null); useEffect(() => { const fetchData = async () => { try { const res = await fetch("/api/dashboard"); if (res.ok) { setData(await res.json()); } } catch { /* ignore */ } }; fetchData(); const id = setInterval(fetchData, 15000); return () => clearInterval(id); }, []); const running = data?.services.filter((s) => s.state === "running").length ?? 0; const degraded = (data?.services.length ?? 0) - running; const hasNode = data?.node.cpu !== null || data?.node.ram !== null; const hasTraffik = (data?.rps?.length ?? 0) > 0 || (data?.latency?.length ?? 0) > 0; const node = data?.node; return (
{/* Services */} Services {data?.services.length ?? 0} {data?.services.length ? (
{data.services.map((s, i) => ( {s.name} ))}
) : (

No services detected

)}
{/* Overview */} Overview
{/* Health */} Health {/* Links */} Links
{data?.links.map((l) => ( {l.label} ))}
{/* System Resources */} {hasNode && ( System Resources {node?.load1?.toFixed(2)} {node?.load5?.toFixed(2)}{" "} {node?.load15?.toFixed(2)}
)} {/* Request Rate */} {hasTraffik && ( Request Rate {data?.rps?.length ? `${data.rps[data.rps.length - 1].toFixed(1)}/s` : "-"} )} {/* Latency */} {hasTraffik && ( Latency {data?.latency?.length ? `${data.latency[data.latency.length - 1].toFixed(0)}ms` : "-"} )} {/* Error Rate */} {hasTraffik && ( Error Rate {data?.errors?.length ? `${data.errors[data.errors.length - 1].toFixed(1)}/s` : "-"} )} {/* Trace Volume */} Trace Volume {data?.traces.length ?? 0} traces {/* Recent Traces */} Recent Traces {data?.traces.length ?? 0} {data?.traces.length ? (
    {data.traces.map((t, i) => (
    {t.service}
    {t.operation}
    {safeDur(t.duration)} {t.spans} {t.hasError && ( err )}
    ))}
) : (

No traces — data appears once services send OTel telemetry

)}
); } function StatBox({ value, label, color, }: { value: number | string | undefined; label: string; color: string; }) { return (
{typeof value === "number" ? ( ) : ( (value ?? "-") )}

{label}

); }