import { useEffect, useState, type ReactNode, type ComponentType } from 'react'; import { cn } from '@/lib/utils'; import { ChevronDown } from 'lucide-react'; // At-a-glance health tones for the optional SectionCard status dot. const DOT_TONES: Record = { green: 'bg-emerald-500', amber: 'bg-amber-500', red: 'bg-rose-500', gray: 'bg-muted-foreground/40', }; export function fmt(isoStr: string | null | undefined): string { if (!isoStr) return '—'; const d = new Date(isoStr); return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }) + ' ' + d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } export interface ImportErrorState { message: string; error: string; code: string | null; details: unknown[]; error_id: string | null; } export function importErrorState(err: unknown, fallback: string): ImportErrorState { const e = (err ?? {}) as { data?: Record; message?: string; code?: string; details?: unknown }; const data = e.data || {}; return { message: e.message || (data.message as string) || (data.error as string) || fallback, error: (data.error as string) || fallback, code: (data.code as string) || e.code || null, details: Array.isArray(data.details) ? data.details : (Array.isArray(e.details) ? e.details : []), error_id: (data.error_id as string) || null, }; } export interface SectionCardProps { title?: ReactNode; subtitle?: ReactNode; icon?: ComponentType<{ className?: string }>; // optional lucide icon component, shown in a soft chip statusDot?: string; // optional 'green' | 'amber' | 'red' | 'gray' health dot badge?: ReactNode; // optional node rendered next to the title (e.g. a count pill) children?: ReactNode; className?: string; collapsible?: boolean; defaultOpen?: boolean; storageKey?: string; summary?: ReactNode; actions?: ReactNode; } export function SectionCard({ title, subtitle, icon: Icon, statusDot, badge, children, className, collapsible = false, defaultOpen = true, storageKey, summary, actions, }: SectionCardProps) { const [open, setOpen] = useState(() => { if (!collapsible || !storageKey || typeof window === 'undefined') return defaultOpen; const stored = window.localStorage.getItem(storageKey); return stored === null ? defaultOpen : stored === 'true'; }); useEffect(() => { if (!collapsible || !storageKey || typeof window === 'undefined') return; window.localStorage.setItem(storageKey, String(open)); }, [collapsible, open, storageKey]); const headerContent = ( <> {Icon && ( )}
{statusDot && }

{title}

{badge}
{subtitle &&

{subtitle}

} {collapsible && !open && summary && (

{summary}

)}
{actions &&
{actions}
} {collapsible && ( )} ); return (
{collapsible ? ( ) : (
{headerContent}
)} {open &&
{children}
}
); } export function CountPill({ label, value }: { label: ReactNode; value?: ReactNode }) { return (

{label}

{value ?? 0}

); }