"use client"; /* eslint-disable react-hooks/set-state-in-effect */ import { useState, useEffect, useCallback } from "react"; import { getPlatformMetrics, getPlatformActivityFeed, getBrandHealthSnapshot, getPainLog, resolvePainLogItem, createPainLogItem, type PlatformMetrics, type ActivityEvent, type BrandHealth, type PainLogItem, } from "@/actions/platform/command-center"; // ── Constants ───────────────────────────────────────────────────────────────── const REFRESH_INTERVAL = 30000; const EVENT_COLORS: Record = { order_placed: { bg: "bg-violet-500/20", text: "text-violet-300", dot: "bg-violet-400" }, order_completed: { bg: "bg-emerald-500/20", text: "text-emerald-300", dot: "bg-emerald-400" }, pickup_completed: { bg: "bg-blue-900/300/20", text: "text-blue-300", dot: "bg-blue-400" }, payment_failed: { bg: "bg-red-900/300/20", text: "text-red-300", dot: "bg-red-400" }, stop_created: { bg: "bg-amber-900/300/20", text: "text-amber-300", dot: "bg-amber-400" }, route_updated: { bg: "bg-cyan-500/20", text: "text-cyan-300", dot: "bg-cyan-400" }, default: { bg: "bg-zinc-900/10", text: "text-white/60", dot: "bg-zinc-900/40" }, }; const SEVERITY_CONFIG: Record = { critical: { bg: "bg-red-900/300/15", text: "text-red-300", border: "border-red-500/30" }, high: { bg: "bg-orange-500/15",text: "text-orange-300", border: "border-orange-500/30" }, medium: { bg: "bg-amber-900/300/15",text: "text-amber-300", border: "border-amber-500/30" }, low: { bg: "bg-zinc-900/8", text: "text-white/60", border: "border-white/10" }, }; const HEALTH_CONFIG: Record = { healthy: { label: "Operational", bg: "bg-emerald-500/15", text: "text-emerald-300", border: "border-emerald-500/25", dot: "bg-emerald-400" }, warning: { label: "Attention", bg: "bg-amber-900/300/15", text: "text-amber-300", border: "border-amber-500/25", dot: "bg-amber-400" }, critical: { label: "Critical", bg: "bg-red-900/300/15", text: "text-red-300", border: "border-red-500/25", dot: "bg-red-400" }, }; // ── Helpers ─────────────────────────────────────────────────────────────────── function formatCurrency(n: number): string { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(n); } function formatCurrencyFull(n: number): string { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(n); } function timeAgo(dateStr: string): string { const diff = Math.floor((Date.now() - new Date(dateStr).getTime()) / 1000); if (diff < 60) return `${diff}s`; if (diff < 3600) return `${Math.floor(diff / 60)}m`; if (diff < 86400)return `${Math.floor(diff / 3600)}h`; return `${Math.floor(diff / 86400)}d`; } // ── Metric Card ───────────────────────────────────────────────────────────────── function MetricCard({ label, value, sub, prefix, suffix, status, delay = 0, tv = false, }: { label: string; value: string | number; sub?: string; prefix?: string; suffix?: string; status?: "healthy" | "warning" | "critical"; delay?: number; tv?: boolean; }) { const valueColor = { healthy: "text-white", warning: "text-amber-300", critical: "text-red-300", }[status ?? "healthy"]!; return (

{label}

{prefix && {prefix}} {typeof value === "number" ? value.toLocaleString() : value} {suffix && {suffix}}
{sub &&

{sub}

}
); } // ── Brand Health Card ───────────────────────────────────────────────────────── function BrandCard({ brand, tv = false }: { brand: BrandHealth; tv?: boolean }) { const c = HEALTH_CONFIG[brand.health_status as keyof typeof HEALTH_CONFIG] ?? HEALTH_CONFIG.warning; return (

{brand.brand_name}

{brand.brand_slug}

{c.label}
{[ { label: "Orders", value: brand.orders_today }, { label: "Revenue", value: formatCurrency(Number(brand.revenue_today)) }, { label: "Routes", value: brand.active_stops }, ].map(({ label, value }) => (

{label}

{value}

))}
{brand.open_pain_items > 0 && (
{brand.open_pain_items} open issue{brand.open_pain_items !== 1 ? "s" : ""}
)}
); } // ── Activity Item ────────────────────────────────────────────────────────────── function ActivityItem({ event }: { event: ActivityEvent }) { const c = EVENT_COLORS[event.event_type] ?? EVENT_COLORS.default; const label = event.event_type.replace(/_/g, " ").replace(/\b\w/g, l => l.toUpperCase()); return (
{label} {event.brand_name && ( {event.brand_name} )}

{event.entity_type && {event.entity_type}} {event.entity_id && #{event.entity_id.slice(0, 6)}}

{event.created_at ? timeAgo(event.created_at) : ""}
); } // ── Pain Item ───────────────────────────────────────────────────────────────── function PainItem({ item, onResolve, onSnooze, }: { item: PainLogItem; onResolve: (id: string) => void; onSnooze: (id: string) => void; }) { const c = SEVERITY_CONFIG[item.severity] ?? SEVERITY_CONFIG.low; return (
{item.severity} {item.title}
{item.brand_name && {item.brand_name}} · {item.category} · {item.created_at ? timeAgo(item.created_at) + " ago" : ""}
); } // ── AI Briefing ──────────────────────────────────────────────────────────────── function AIBriefing({ metrics, brandHealth }: { metrics: PlatformMetrics | null; brandHealth: BrandHealth[]; }) { const lines: string[] = []; if (!metrics) return
; if (metrics.orders_today > 0) { lines.push(`${metrics.orders_today} order${metrics.orders_today !== 1 ? "s" : ""} placed today.`); } if (Number(metrics.revenue_today) > 0) { lines.push(`${formatCurrencyFull(Number(metrics.revenue_today))} in revenue processed.`); } if (metrics.failed_orders_today > 0) { lines.push(`${metrics.failed_orders_today} failed order${metrics.failed_orders_today !== 1 ? "s" : ""} need attention.`); } if (metrics.pending_orders_today > 0) { lines.push(`${metrics.pending_orders_today} order${metrics.pending_orders_today !== 1 ? "s" : ""} pending confirmation.`); } const crit = brandHealth.filter(b => b.health_status === "critical").length; if (crit > 0) lines.push(`${crit} brand${crit !== 1 ? "s" : ""} in critical state.`); const warn = brandHealth.filter(b => b.health_status === "warning").length; if (warn > 0 && crit === 0) lines.push(`${warn} brand${warn !== 1 ? "s" : ""} need attention.`); if (lines.length === 0) { lines.push("Platform is running smoothly — no active issues."); } return (
{lines.map((line, i) => (

{line}

))}
); } // ── Main ───────────────────────────────────────────────────────────────────── export default function CommandCenterDashboard() { const [metrics, setMetrics] = useState(null); const [activity, setActivity] = useState([]); const [brandHealth, setBrandHealth] = useState([]); const [painLog, setPainLog] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [resolving, setResolving] = useState>(new Set()); const [showAddForm, setShowAddForm] = useState(false); const [tvMode, setTvMode] = useState(false); const [addForm, setAddForm] = useState({ severity: "medium", category: "operations", title: "", description: "" }); const [snoozed, setSnoozed] = useState>(new Set()); const tv = tvMode; const fetchAll = useCallback(async () => { try { const [m, a, b, p] = await Promise.all([ getPlatformMetrics(), getPlatformActivityFeed(), getBrandHealthSnapshot(), getPainLog(), ]); setMetrics(m); setActivity(a); setBrandHealth(b); setPainLog(p); setError(null); } catch (err) { setError(err instanceof Error ? err.message : "Failed to load"); } finally { setLoading(false); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { fetchAll(); const iv = setInterval(fetchAll, REFRESH_INTERVAL); return () => clearInterval(iv); }, [fetchAll]); const handleResolve = async (id: string) => { setResolving(prev => new Set([...prev, id])); try { const r = await resolvePainLogItem(id); if (r.success) setPainLog(prev => prev.filter(i => i.id !== id)); } finally { setResolving(prev => { const n = new Set(prev); n.delete(id); return n; }); } }; const handleSnooze = (id: string) => { setSnoozed(prev => new Set([...prev, id])); setTimeout(() => { setSnoozed(prev => { const n = new Set(prev); n.delete(id); return n; }); }, 3600000); }; const handleAdd = async () => { if (!addForm.title.trim()) return; const r = await createPainLogItem({ severity: addForm.severity as "low" | "medium" | "high" | "critical", category: addForm.category, title: addForm.title, description: addForm.description || null, }); if (r.success) { setAddForm({ severity: "medium", category: "operations", title: "", description: "" }); setShowAddForm(false); fetchAll(); } }; const openItems = painLog.filter(p => p.status === "open" && !snoozed.has(p.id)); if (loading) { return (

Initializing

); } if (error) { return (

Connection Lost

{error}

); } return (
{/* ── Header ─────────────────────────────────────────────────────────── */}

Command Center

{new Date().toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric", year: "numeric" })} {" · "} LIVE

{/* ── KPI Row ──────────────────────────────────────────────────────────── */}
5 ? "warning" : "healthy"} /> 0 ? "critical" : "healthy"} /> 5 ? "warning" : "healthy"} />
{/* ── AI Briefing (full width) ──────────────────────────────────────── */}
🤖

Daily Briefing

Platform intelligence summary

{/* ── 2-Column Body ───────────────────────────────────────────────────── */}
{/* ── LEFT: Brand Health + Activity ───────────────────────────── */}
{/* Brand Health */}

Brand Health

{brandHealth.length}
{brandHealth.length === 0 ? (

No active brands

) : ( brandHealth.map((b) => ( )) )}
{/* Activity Feed */}

Live Activity

{activity.length}
{activity.length === 0 ? (

No recent events

) : ( activity.slice(0, 30).map((e) => ( )) )}
{/* ── RIGHT: Founder Queue ─────────────────────────────── */}

Founder Queue

{openItems.length > 0 && ( {openItems.length} )}
{showAddForm && (
setAddForm(f => ({ ...f, title: e.target.value }))} placeholder="Issue title..." className="w-full rounded-xl bg-zinc-900/5 border border-white/10 px-4 py-3 text-sm text-white/75 placeholder-white/15 outline-none focus:border-white/20" /> setAddForm(f => ({ ...f, category: e.target.value }))} placeholder="Category (e.g. deployment, payment)" className="w-full rounded-xl bg-zinc-900/5 border border-white/10 px-4 py-3 text-sm text-white/75 placeholder-white/15 outline-none focus:border-white/20" />