import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { Stats, DeduplicationStats, ReferencedArtifact } from '../types'; import { getStats, getDeduplicationStats } from '../api'; import { DataTable } from '../components/DataTable'; import './Dashboard.css'; function formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`; } function formatNumber(num: number): string { return num.toLocaleString(); } function truncateHash(hash: string, length: number = 12): string { if (hash.length <= length) return hash; return `${hash.slice(0, length)}...`; } interface StatCardProps { label: string; value: string; subvalue?: string; icon: React.ReactNode; variant?: 'default' | 'success' | 'accent'; trend?: 'up' | 'down' | 'neutral'; } function StatCard({ label, value, subvalue, icon, variant = 'default', trend }: StatCardProps) { return (
{error}
{truncateHash(item.artifact_id, 16)}
),
},
{
key: 'original_name',
header: 'Name',
render: (item: ReferencedArtifact) => (
{item.original_name || '—'}
),
},
{
key: 'size',
header: 'Size',
render: (item: ReferencedArtifact) => formatBytes(item.size),
},
{
key: 'ref_count',
header: 'References',
render: (item: ReferencedArtifact) => (
{formatNumber(item.ref_count)}
refs
),
},
{
key: 'storage_saved',
header: 'Storage Saved',
render: (item: ReferencedArtifact) => (
{formatBytes(item.storage_saved)}
),
},
];
return (
Real-time deduplication and storage analytics
These artifacts are referenced most frequently across your storage, maximizing deduplication savings.