import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import type { LucideIcon } from "lucide-react"; const COLORS = ["#3b82f6", "#8b5cf6", "#10b981", "#f59e0b", "#ef4444", "#06b6d4", "#ec4899", "#84cc16"]; export { COLORS }; // ── Big number stat card ── export function Stat({ label, value, sub, icon: Icon, color }: { label: string; value: string | number; sub: string; icon: LucideIcon; color: string; }) { return ( {label}
{value}

{sub}

); } // ── Mini number ── export function Mini({ label, value, color }: { label: string; value: string | number; color?: string }) { return (
{value}

{label}

); } // ── Ratio bar ── export function RatioBar({ items }: { items: { label: string; value: number; color: string }[] }) { const total = items.reduce((a, b) => a + b.value, 0); if (total === 0) return null; return (
{items.map((item, i) => (
))}
{items.map((item, i) => ( {item.label}: {item.value} ({Math.round(100 * item.value / total)}%) ))}
); } // ── Relative time helper ── export function timeAgo(dateStr: string | null | undefined): string { if (!dateStr) return "-"; const d = new Date(dateStr); if (isNaN(d.getTime())) return dateStr; const now = Date.now(); const diffMs = now - d.getTime(); if (diffMs < 0) return "just now"; const mins = Math.floor(diffMs / 60000); if (mins < 1) return "just now"; if (mins < 60) return `${mins}m ago`; const hours = Math.floor(mins / 60); if (hours < 24) return `${hours}h ago`; const days = Math.floor(hours / 24); if (days < 7) return `${days}d ago`; const weeks = Math.floor(days / 7); if (weeks < 5) return `${weeks}w ago`; return `${Math.floor(days / 30)}mo ago`; } // ── Date group label ── export function dateGroup(dateStr: string | null | undefined): string { if (!dateStr) return "Older"; const d = new Date(dateStr); if (isNaN(d.getTime())) return "Older"; const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const yesterday = new Date(today.getTime() - 86400000); const weekAgo = new Date(today.getTime() - 7 * 86400000); const target = new Date(d.getFullYear(), d.getMonth(), d.getDate()); if (target >= today) return "Today"; if (target >= yesterday) return "Yesterday"; if (target >= weekAgo) return "This Week"; return "Older"; } // ── Parse source label into badges ── export function parseSourceLabel(label: string): string[] { let cleaned = label; if (cleaned.startsWith("batch:")) cleaned = cleaned.slice(6); const parts = cleaned.split(",").map(s => s.trim()).filter(Boolean); return parts.slice(0, 3); } // ── Duration formatter ── export function formatDuration(mins: number): string { if (mins < 1) return "<1m"; if (mins < 60) return `${Math.round(mins)}m`; const h = Math.floor(mins / 60); const m = Math.round(mins % 60); return m > 0 ? `${h}h ${m}m` : `${h}h`; }