import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { api } from '../api/client'; import type { OverviewStats, RemoteStatRow, FileStatRow, BandwidthStatRow, HealthStatus } from '../api/types'; import { StatsCard } from '../components/StatsCard'; import { Badge } from '../components/Badge'; import { DataTable } from '../components/DataTable'; import { formatBytes, formatNumber } from '../components/format'; import './Dashboard.css'; export function Dashboard() { const [stats, setStats] = useState(null); const [topRemotes, setTopRemotes] = useState([]); const [topFilesByHits, setTopFilesByHits] = useState([]); const [topFilesByBW, setTopFilesByBW] = useState([]); const [health, setHealth] = useState(null); const [error, setError] = useState(null); useEffect(() => { Promise.all([ api.stats(), api.topRemotes(), api.topFilesByHits(), api.topFilesByBandwidth(), api.health(), ]) .then(([s, tr, tfh, tfb, h]) => { setStats(s); setTopRemotes(tr || []); setTopFilesByHits(tfh || []); setTopFilesByBW(tfb || []); setHealth(h); }) .catch(e => setError(e.message)); }, []); if (error) return
{error}
; if (!stats) return
Loading...
; return (

Dashboard

{health && (
Services postgres: {health.postgres} redis: {health.redis} s3: {health.s3}
)}

Top Remotes by Size

{r.name}, }, { key: 'objects', header: 'Objects', render: (r: RemoteStatRow) => formatNumber(r.object_count), width: '120px', }, { key: 'size', header: 'Size', render: (r: RemoteStatRow) => formatBytes(r.total_bytes), width: '120px', }, { key: 'requests', header: 'Requests (30d)', render: (r: RemoteStatRow) => formatNumber(r.requests_30d), width: '140px', }, ]} data={topRemotes} emptyMessage="No remotes configured yet" />

Top Files by Hits

( {r.remote_name} {r.path} ), }, { key: 'hits', header: 'Hits', render: (r: FileStatRow) => formatNumber(r.access_count), width: '90px', }, { key: 'size', header: 'Size', render: (r: FileStatRow) => formatBytes(r.size_bytes), width: '100px', }, ]} data={topFilesByHits} emptyMessage="No cached files yet" />

Top Files by Bandwidth (30d)

( {r.remote_name} {r.path} ), }, { key: 'bandwidth', header: 'Bandwidth', render: (r: BandwidthStatRow) => formatBytes(r.bandwidth), width: '110px', }, { key: 'requests', header: 'Requests', render: (r: BandwidthStatRow) => formatNumber(r.requests), width: '100px', }, ]} data={topFilesByBW} emptyMessage="No access data yet" />
); }