"use client"; import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; import { Skeleton } from "@/components/ui/skeleton"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; type MetricEntry = { ts: string; tps: number; ramUsedMB: number; ramTotalMB: number; cpuPercent: number; playersOnline: number; }; function Sparkline({ data, color, max, height = 80, label, unit, currentValue, }: { data: number[]; color: string; max?: number; height?: number; label: string; unit: string; currentValue: string; }) { if (data.length < 2) { return (

{label}

{currentValue} {unit}

Collecting data...

); } const dataMax = max || Math.max(...data, 1); const w = 300; const points = data.map((v, i) => { const x = (i / (data.length - 1)) * w; const y = height - (v / dataMax) * (height - 10) - 5; return `${x},${y}`; }); const pathD = `M${points.join(" L")}`; const areaD = `${pathD} L${w},${height} L0,${height} Z`; return (

{label}

{currentValue} {unit}

); } export function Analytics() { const [hours, setHours] = useState(6); const { data: metrics = [] } = useQuery({ queryKey: ["analytics", hours], queryFn: () => fetch(`/api/analytics?hours=${hours}`).then((r) => r.json()), refetchInterval: 60_000, }); const latest = metrics.length > 0 ? metrics[metrics.length - 1] : null; const ranges = [ { label: "1h", value: 1 }, { label: "6h", value: 6 }, { label: "24h", value: 24 }, ]; return (
Server Analytics {metrics.length} data points
{ranges.map((r) => ( ))}
m.tps)} color="#4ade80" max={22} label="TPS" unit="" currentValue={latest ? latest.tps.toFixed(1) : "-"} /> m.ramUsedMB)} color="#60a5fa" label="RAM" unit="MB" currentValue={ latest ? `${(latest.ramUsedMB / 1024).toFixed(1)} GB` : "-" } /> m.cpuPercent)} color="#f59e0b" max={100} label="CPU" unit="%" currentValue={latest ? latest.cpuPercent.toFixed(0) : "-"} /> m.playersOnline)} color="#a78bfa" label="Players" unit="" currentValue={latest ? latest.playersOnline.toString() : "0"} />
); }