import { useQuery } from '@tanstack/react-query'; import { Database, HardDrive, Layers, AlertCircle, Activity, Cpu } from 'lucide-react'; import { api } from '../../lib/api-client'; import { AppShell, PageHeader, PageBody } from '../../layout/AppShell'; import { Badge, Card } from '../../components/ui/primitives'; interface Health { pool: { total: number; idle: number; waiting: number }; db: { products: string; offers: string; active_feeds: string; db_size: string; subscribers: string; }; queue: { pending: number; running: number; completed: number; failed: number; cancelled: number; total: number }; errors_24h: Array<{ severity: string; count: string }>; largest_tables: Array<{ table_name: string; size: string; size_bytes: number }>; uptime_seconds: number; memory_mb: number; node_version: string; } function formatUptime(secs: number): string { const d = Math.floor(secs / 86400); const h = Math.floor((secs % 86400) / 3600); const m = Math.floor((secs % 3600) / 60); if (d > 0) return `${d}d ${h}h`; if (h > 0) return `${h}h ${m}m`; return `${m}m`; } export function SystemHealth() { const { data } = useQuery({ queryKey: ['health'], queryFn: () => api.get('/health'), refetchInterval: 10000, }); if (!data) { return (
Laden...
); } const errors24 = data.errors_24h.reduce((sum, e) => sum + parseInt(e.count, 10), 0); const allOk = errors24 === 0 && data.queue.failed === 0 && data.pool.waiting === 0; return ( {allOk ? 'Alles gezond' : 'Controleer onderdelen'} } />
} label="Uptime" value={formatUptime(data.uptime_seconds)} hint={data.node_version} /> } label="Memory" value={`${data.memory_mb} MB`} hint="heap used" /> } label="DB size" value={data.db.db_size} hint={`${Number(data.db.products).toLocaleString('nl-NL')} producten`} /> } label="Errors (24u)" value={String(errors24)} hint={errors24 === 0 ? 'Geen fouten' : 'Zie error log'} danger={errors24 > 0} />

Connection pool

{data.pool.total} {data.pool.idle} {data.pool.total - data.pool.idle} 0}> {data.pool.waiting}

Job queue

{data.queue.pending} {data.queue.running} {data.queue.completed} 0}> {data.queue.failed}

Top 10 grootste tabellen

{data.largest_tables.map((t) => { const pct = Math.max(2, Math.round((t.size_bytes / data.largest_tables[0].size_bytes) * 100)); return (
{t.table_name}
{t.size}
); })}
); } function StatBlock({ icon, label, value, hint, danger, }: { icon: React.ReactNode; label: string; value: string; hint: string; danger?: boolean; }) { return (

{label}

{value}

{hint}

{icon}
); } function Row({ label, children, danger }: { label: string; children: React.ReactNode; danger?: boolean }) { return (
{label} {children}
); }