import { useEffect, useState } from 'react'; import { getJSON } from '../lib/api'; interface HealthStatus { status: string; redis: boolean; timestamp: string; } interface FileStats { count: number; totalSize: number; } interface Stats { records: number; redisKeys: number; redisMemory: string; identities: number; files: FileStats | null; udlUsers: number | null; sweptAt: number; sweeping: boolean; } interface WatcherStatus { id: string; path: string; intervalMs: number; enabled: boolean; active: boolean; lastScan: number; fileCount: number; isScanning: boolean; } interface WatchersResponse { watchers: WatcherStatus[]; count: number; } const cardStyle: React.CSSProperties = { background: '#16213e', borderRadius: '8px', padding: '1.5rem', marginBottom: '1rem', }; const gridStyle: React.CSSProperties = { display: 'grid', // 200px, not 220: five tiles must fit one row inside the 1200px container // (1136 content - 4x16 gap = 1072 / 5 = 214 each) before wrapping. gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1rem', marginBottom: '1rem', }; const statStyle: React.CSSProperties = { fontSize: '2rem', fontWeight: 'bold', color: '#4ade80', lineHeight: 1.2, }; const labelStyle: React.CSSProperties = { marginBottom: '0.75rem', color: '#888', fontSize: '0.85rem', textTransform: 'uppercase', letterSpacing: '0.04em', }; const noteStyle: React.CSSProperties = { color: '#6b7a99', fontSize: '0.8rem', marginTop: '0.4rem', }; const numberFmt = new Intl.NumberFormat(); function formatCount(n: number | null | undefined): string { return n === null || n === undefined ? '—' : numberFmt.format(n); } // Binary units: this counts bytes on disk, and every other tool the operator // compares against (du, docker, the mount page) reports GiB. function formatBytes(bytes: number | null | undefined): string { if (bytes === null || bytes === undefined) return '—'; const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']; let value = bytes; let unit = 0; while (value >= 1024 && unit < units.length - 1) { value /= 1024; unit++; } return `${value.toFixed(value >= 100 || unit === 0 ? 0 : 1)} ${units[unit]}`; } function Tile({ label, value, note, pending, }: { label: string; value: string; note?: string; pending?: boolean; }) { return (
Metadata store: {health.redis ? 'Open' : 'Unavailable'}
> ) : (Loading…
)}active watchers
Status: {isScanning ? 'Scanning…' : 'Idle'}
{lastScan > 0 && (Last scan: {new Date(lastScan).toLocaleString()}
)} > ) : (Loading…
)}