import { useEffect, useState } from 'react'; import { api, FleetSnapshot, 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 (

Fleet health

{fleet && ( <> {totals?.online} /{fleet.nodes.length} nodes online {' · '} {totals?.mounted}/{fleet.nodes.length} mounted {' · '} updated {fmtAge(fleet.fetched_at_unix)} {' · '} hosted by {fleet.aggregator_name} )}
{err && (
{err}
)} {totals && totals.diskTotal > 0 && (
Fleet-wide storage
{fmtBytes(totals.diskUsed)}{' '} / {fmtBytes(totals.diskTotal)}
{Math.round((totals.diskUsed / totals.diskTotal) * 100)}% used
hot tier: {fmtBytes(totals.hotUsed)} / {fmtBytes(totals.hotMax)}
)}

Nodes

{fleet?.nodes.map((n) => ( ))} {!fleet && [1, 2, 3].map((i) => (
))}
); }