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 (
);
}
// ── 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`;
}