import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect, useState } from 'react'; import { api, fmtBytes, fmtAge } from '../lib/api'; import { NodeCard } from '../components/NodeCard'; import { ProjectsPanel } from '../components/ProjectsPanel'; // FleetHealth landing — human-oriented single-pane-of-glass. // Polls the aggregator's /api/v2/fleet every 10 s. export function CommandCenter() { const [fleet, setFleet] = useState(null); const [err, setErr] = useState(null); const [tick, setTick] = useState(0); useEffect(() => { api .fleet() .then((f) => { setFleet(f); setErr(null); }) .catch((e) => setErr(String(e))); }, [tick]); useEffect(() => { const id = setInterval(() => setTick((t) => t + 1), 10_000); return () => clearInterval(id); }, []); const totals = fleet ? fleet.nodes.reduce((a, n) => ({ diskUsed: a.diskUsed + (n.filesystem?.used_bytes ?? 0), diskTotal: a.diskTotal + (n.filesystem?.total_bytes ?? 0), hotUsed: a.hotUsed + (n.hot?.used_bytes ?? 0), hotMax: a.hotMax + (n.hot?.max_bytes ?? 0), online: a.online + (n.online ? 1 : 0), mounted: a.mounted + (n.mount?.active ? 1 : 0), }), { diskUsed: 0, diskTotal: 0, hotUsed: 0, hotMax: 0, online: 0, mounted: 0 }) : null; return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold text-slate-100", children: "Fleet health" }), _jsx("div", { className: "text-sm text-slate-500 mt-1", children: fleet && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-emerald-300", children: totals?.online }), "/", fleet.nodes.length, " nodes online", ' · ', totals?.mounted, "/", fleet.nodes.length, " mounted", ' · ', "updated ", _jsx("span", { className: "font-mono", children: fmtAge(fleet.fetched_at_unix) }), ' · ', "hosted by ", _jsx("span", { className: "font-mono text-slate-300", children: fleet.aggregator_name })] })) })] }), err && (_jsx("div", { className: "rounded border border-red-800 bg-red-950/40 p-3 text-red-300 text-sm", children: err })), totals && totals.diskTotal > 0 && (_jsxs("div", { className: "rounded-lg border border-slate-800 bg-slate-900/60 p-4 flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs uppercase tracking-wider text-slate-500", children: "Fleet-wide storage" }), _jsxs("div", { className: "text-2xl font-semibold font-mono mt-1", children: [fmtBytes(totals.diskUsed), ' ', _jsxs("span", { className: "text-slate-500 text-lg", children: ["/ ", fmtBytes(totals.diskTotal)] })] })] }), _jsxs("div", { className: "text-right text-slate-400 text-sm", children: [_jsxs("div", { children: [Math.round((totals.diskUsed / totals.diskTotal) * 100), "% used"] }), _jsxs("div", { className: "text-xs text-slate-500 mt-1", children: ["hot tier: ", fmtBytes(totals.hotUsed), " / ", fmtBytes(totals.hotMax)] })] })] })), _jsxs("section", { children: [_jsx("h2", { className: "text-lg font-semibold text-slate-100 mb-3", children: "Nodes" }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [fleet?.nodes.map((n) => (_jsx(NodeCard, { node: n }, n.node_name))), !fleet && [1, 2, 3].map((i) => (_jsx("div", { className: "rounded-lg border border-slate-800 bg-slate-900/40 p-5 h-64 animate-pulse" }, i)))] })] }), _jsx(ProjectsPanel, {})] })); }