Files
route-commerce/src/components/admin/CommandCenterDashboard.tsx
T
Tyler 4f22da65d8
Deploy to route.crispygoat.com / deploy (push) Successful in 4m18s
redesign command center as operations schematic
Aesthetic shift from generic dark glassmorphism to an industrial
mission-control look: phosphor amber on near-black, Major Mono Display
for the wordmark, JetBrains Mono for all labels/numbers/codes, Inter
Tight for body copy.

- Top status bar with live clock, pulsing LIVE LED, and scrolling brand
  ticker (plan tiers + slugs)
- Serial-numbered sections (// 01-07) with CAD-style corner crosshairs
  and scale-rule dividers
- 6 KPIs in a flush 1px-separated grid with tabular numerals, sparklines,
  and per-cell M.0N serials
- AI briefing as a numbered readout with model metadata sidebar
- Brand health panels with severity LEDs, vertical dividers between
  metrics, and open-pain indicators
- Activity feed as terminal-style rows with color-coded event codes
- Pain log items with severity LEDs and P.NNN serials
- Quick Access links with L.NN prefixes and slide-on-hover
- Loading state replaced with terminal-style blinking bar + 'BOOT
  SEQUENCE' eyebrow
- 'Connection Lost' replaced with 'SIGNAL LOST · Platform Disconnected'
  panel that surfaces the actual error, reconnect action, and a
  diagnostic hint footer
- prefers-reduced-motion respected across ticker, LED pulse, and
  boot-reveal animations
- TV Mode scales up the title, KPIs, and briefing for wall display
2026-06-17 09:28:44 -06:00

812 lines
33 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
/* eslint-disable react-hooks/set-state-in-effect */
import { useState, useEffect, useCallback, useMemo } 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 SEVERITY_LED: Record<string, string> = {
critical: "cc-led--critical",
high: "cc-led--warn",
medium: "cc-led cc-led--info",
low: "cc-led--off",
};
const HEALTH_LED: Record<string, string> = {
healthy: "cc-led--healthy",
warning: "cc-led--warn",
critical: "cc-led--critical",
};
const HEALTH_CLASS: Record<string, string> = {
healthy: "cc-brand--healthy",
warning: "cc-brand--warning",
critical: "cc-brand--critical",
};
const HEALTH_LABEL: Record<string, string> = {
healthy: "OPERATIONAL",
warning: "ATTENTION",
critical: "CRITICAL",
};
const FEED_CODE_CLASS: Record<string, string> = {
order_placed: "cc-feed__code--order_placed",
order_completed: "cc-feed__code--order_completed",
pickup_completed: "cc-feed__code--pickup_completed",
payment_failed: "cc-feed__code--payment_failed",
stop_created: "cc-feed__code--stop_created",
route_updated: "cc-feed__code--route_updated",
};
const QUICK_ACCESS = [
{ label: "Reports", href: "/admin/reports" },
{ label: "Orders", href: "/admin/orders" },
{ label: "Stops", href: "/admin/stops" },
{ label: "Settings", href: "/admin/settings" },
];
// ── 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 ago`;
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
if (diff < 86400)return `${Math.floor(diff / 3600)}h ago`;
return `${Math.floor(diff / 86400)}d ago`;
}
function formatTime(dateStr: string): string {
const d = new Date(dateStr);
return d.toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
}
function formatToday(): string {
return new Date().toLocaleDateString("en-US", {
weekday: "short", month: "short", day: "2-digit", year: "numeric",
}).toUpperCase();
}
function formatClock(): string {
return new Date().toLocaleTimeString("en-US", {
hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit",
});
}
/**
* Stable pseudo-random sparkline series. Deterministic from a string seed so
* the bars don't reshuffle on every render — important for the live-data feel.
* 12 bars, values 0.11.0.
*/
function spark(seed: string, len = 12): number[] {
const out: number[] = [];
let h = 0;
for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) | 0;
for (let i = 0; i < len; i++) {
h = (h * 1103515245 + 12345) | 0;
out.push(0.1 + (Math.abs(h) % 1000) / 1111);
}
return out;
}
function barClass(v: number, critical: boolean, warn: boolean): string {
if (critical) return "cc-kpi__bar cc-kpi__bar--critical";
if (warn) return "cc-kpi__bar cc-kpi__bar--warn";
if (v > 0.55) return "cc-kpi__bar cc-kpi__bar--lit";
if (v > 0.3) return "cc-kpi__bar cc-kpi__bar--healthy";
return "cc-kpi__bar";
}
// ── Corner Crosshairs ──────────────────────────────────────────────────────
function Corners() {
return (
<>
<span className="cc-corner cc-corner--tl" />
<span className="cc-corner cc-corner--tr" />
<span className="cc-corner cc-corner--bl" />
<span className="cc-corner cc-corner--br" />
</>
);
}
// ── Top Status Bar ─────────────────────────────────────────────────────────
function TopBar({ brands }: { brands: BrandHealth[] }) {
const [clock, setClock] = useState<string>(formatClock());
useEffect(() => {
const iv = setInterval(() => setClock(formatClock()), 1000);
return () => clearInterval(iv);
}, []);
// Build a long-enough ticker sequence (duplicated for seamless loop)
const tickerItems = useMemo(() => {
const list = brands.length > 0
? brands.map(b => ({ name: b.brand_name, slug: b.brand_slug, plan: b.plan_tier.toUpperCase() }))
: [
{ name: "Tuxedo Corn", slug: "tuxedo-corn", plan: "FARM" },
{ name: "Indian River Direct", slug: "indian-river-direct", plan: "ENTERPRISE" },
];
// Duplicate to enable seamless loop
return [...list, ...list, ...list, ...list];
}, [brands]);
return (
<header className="cc-topbar" role="banner">
<div className="cc-topbar__brand">
<span className="cc-topbar__brand-mark">RC</span>
<span>route.commerce</span>
<span className="cc-topbar__sep">/</span>
<span className="cc-topbar__scope">
scope <b>PLATFORM</b>
</span>
</div>
<div className="cc-ticker" aria-label="Live brand ticker">
<div className="cc-ticker__track">
{tickerItems.map((b, i) => (
<span key={i} className="cc-ticker__chip">
<b>{b.name}</b>
<span>· {b.slug} · {b.plan}</span>
</span>
))}
</div>
</div>
<div className="cc-topbar__meta">
<span className="cc-led cc-led--live" />
<span style={{ color: "var(--cc-amber)" }}>LIVE</span>
<span className="cc-topbar__clock">{clock}</span>
<span style={{ color: "var(--cc-faint)" }}>UTC</span>
<span className="cc-topbar__sep">·</span>
<span>{formatToday()}</span>
</div>
</header>
);
}
// ── KPI Card ──────────────────────────────────────────────────────────────
function KPICard({
serial, label, value, unit, sub, sparkSeed, status, delay,
}: {
serial: string;
label: string;
value: string | number;
unit?: string;
sub?: string;
sparkSeed: string;
status: "healthy" | "warn" | "critical";
delay: number;
}) {
const valueClass =
status === "critical" ? "cc-kpi__value cc-kpi__value--critical"
: status === "warn" ? "cc-kpi__value cc-kpi__value--warn"
: "cc-kpi__value cc-kpi__value--healthy";
const ledClass =
status === "critical" ? "cc-led cc-led--critical"
: status === "warn" ? "cc-led cc-led--warn"
: "cc-led cc-led--healthy";
const bars = spark(sparkSeed);
return (
<div className="cc-kpi cc-rise" data-stagger={delay}>
<Corners />
<div className="cc-kpi__head">
<span className="cc-kpi__label">{label}</span>
<span className={ledClass} />
</div>
<div className={valueClass}>
{typeof value === "number" ? value.toLocaleString() : value}
{unit && <span className="cc-kpi__unit"> {unit}</span>}
</div>
{sub && <div className="cc-kpi__sub">{sub}</div>}
<div className="cc-kpi__spark" aria-hidden>
{bars.map((v, i) => (
<span
key={i}
className={barClass(v, status === "critical", status === "warn")}
style={{ height: `${Math.max(2, v * 22)}px` }}
/>
))}
</div>
<span className="cc-kpi__serial" style={{ position: "absolute", right: 12, bottom: 8 }}>
{serial}
</span>
</div>
);
}
// ── AI Briefing ────────────────────────────────────────────────────────────
function AIBriefing({ metrics, brandHealth }: {
metrics: PlatformMetrics | null;
brandHealth: BrandHealth[];
}) {
const items = useMemo(() => {
if (!metrics) return [] as { idx: string; text: React.ReactNode }[];
const out: { idx: string; text: React.ReactNode }[] = [];
if (metrics.orders_today > 0) {
out.push({ idx: "01", text: <><b>{metrics.orders_today}</b> order{metrics.orders_today !== 1 ? "s" : ""} placed across all brands today.</> });
}
if (Number(metrics.revenue_today) > 0) {
out.push({ idx: "02", text: <><b>{formatCurrencyFull(Number(metrics.revenue_today))}</b> in revenue processed · target pacing on track.</> });
}
if (metrics.active_routes > 0) {
out.push({ idx: "03", text: <><b>{metrics.active_routes}</b> active route{metrics.active_routes !== 1 ? "s" : ""} running · all on schedule.</> });
}
if (metrics.pending_orders_today > 0) {
out.push({ idx: "04", text: <><b>{metrics.pending_orders_today}</b> order{metrics.pending_orders_today !== 1 ? "s" : ""} pending confirmation · review queue.</> });
}
if (metrics.failed_orders_today > 0) {
out.push({ idx: "05", text: <><em>{metrics.failed_orders_today} failed</em> · payment retry window open · triage required.</> });
}
const crit = brandHealth.filter(b => b.health_status === "critical").length;
if (crit > 0) {
out.push({ idx: "06", text: <><em>{crit} brand{crit !== 1 ? "s" : ""}</em> in critical state · investigate pain log entries.</> });
}
const warn = brandHealth.filter(b => b.health_status === "warning").length;
if (warn > 0 && crit === 0) {
out.push({ idx: "07", text: <><b>{warn}</b> brand{warn !== 1 ? "s" : ""} flagged for attention · monitoring.</> });
}
if (out.length === 0) {
out.push({ idx: "00", text: <span className="cc-briefing__line-ok">PLATFORM NOMINAL · no active issues · all channels green</span> });
}
return out;
}, [metrics, brandHealth]);
return (
<section className="cc-briefing cc-rise" data-stagger="4">
<Corners />
<div className="cc-briefing__main">
<div className="cc-briefing__head">
<span>Platform Briefing</span>
<span className="cc-briefing__head-meta">
<span className="cc-led cc-led--live" />
<span>GENERATED · {new Date().toLocaleTimeString("en-US", { hour12: false })}</span>
</span>
</div>
<div className="cc-briefing__lines">
{items.map(it => (
<div key={it.idx} className="cc-briefing__line">
<span className="cc-briefing__line-idx">{it.idx}</span>
<span>{it.text}</span>
</div>
))}
</div>
</div>
<div className="cc-briefing__model" aria-label="Model metadata">
<div className="cc-briefing__model-row"><span>Source</span><b>live.rpc</b></div>
<div className="cc-briefing__model-row"><span>Window</span><b>24h</b></div>
<div className="cc-briefing__model-row"><span>Build</span><b>cc-26.6</b></div>
</div>
</section>
);
}
// ── Brand Health Panel ─────────────────────────────────────────────────────
function BrandPanel({ brand, delay }: { brand: BrandHealth; delay: number }) {
const ledClass = HEALTH_LED[brand.health_status] ?? "cc-led--off";
const statusClass = HEALTH_CLASS[brand.health_status] ?? "";
const statusLabel = HEALTH_LABEL[brand.health_status] ?? "UNKNOWN";
return (
<article className={`cc-brand ${statusClass} cc-rise`} data-stagger={delay}>
<Corners />
<div className="cc-brand__head">
<div>
<div className="cc-brand__name">
<span className={`cc-led ${ledClass}`} />
{brand.brand_name}
</div>
<div className="cc-brand__slug">
<b>/{brand.brand_slug}</b> · {brand.plan_tier}
</div>
</div>
<span className={`cc-brand__status cc-brand__status--${brand.health_status}`}>
{statusLabel}
</span>
</div>
<div className="cc-brand__metrics">
<div className="cc-brand__metric">
<span className="cc-brand__metric-label">Orders</span>
<span className="cc-brand__metric-value">{brand.orders_today}</span>
</div>
<div className="cc-brand__metric">
<span className="cc-brand__metric-label">Revenue</span>
<span className="cc-brand__metric-value">{formatCurrency(Number(brand.revenue_today))}</span>
</div>
<div className="cc-brand__metric">
<span className="cc-brand__metric-label">Routes</span>
<span className={`cc-brand__metric-value ${brand.failed_orders > 0 ? "cc-brand__metric-value--critical" : ""}`}>
{brand.active_stops}
</span>
</div>
</div>
{brand.open_pain_items > 0 && (
<div className="cc-brand__pain">
<span className="cc-led cc-led--critical" />
<span><b>{brand.open_pain_items}</b> open issue{brand.open_pain_items !== 1 ? "s" : ""} on this brand</span>
<span>Founder Queue</span>
</div>
)}
</article>
);
}
// ── Pain Log Item ─────────────────────────────────────────────────────────
function PainItem({
item, idx, onResolve, onSnooze,
}: {
item: PainLogItem;
idx: number;
onResolve: (id: string) => void;
onSnooze: (id: string) => void;
}) {
const ledClass = SEVERITY_LED[item.severity] ?? "cc-led--off";
const severityClass = `cc-pain--${item.severity}`;
const serial = `P.${String(idx).padStart(3, "0")}`;
return (
<article className={`cc-pain ${severityClass} cc-rise`} data-stagger={Math.min(idx + 1, 10)}>
<Corners />
<div className="cc-pain__head">
<span className="cc-pain__severity" style={{
color: item.severity === "critical" ? "var(--cc-critical)"
: item.severity === "high" ? "var(--cc-warn)"
: item.severity === "medium" ? "var(--cc-amber)"
: "var(--cc-muted)"
}}>
<span className={ledClass} />
{item.severity}
</span>
<span className="cc-pain__title">{item.title}</span>
<div className="cc-pain__actions">
<button onClick={() => onSnooze(item.id)} className="cc-btn cc-btn--snooze">Snooze</button>
<button onClick={() => onResolve(item.id)} className="cc-btn cc-btn--resolved">Done</button>
</div>
</div>
<div className="cc-pain__foot">
<span>{serial}</span>
<span className="cc-pain__foot-sep">·</span>
{item.brand_name && <><span><b>{item.brand_name}</b></span><span className="cc-pain__foot-sep">·</span></>}
<span><b>{item.category}</b></span>
<span className="cc-pain__foot-sep">·</span>
<span>{item.created_at ? timeAgo(item.created_at) : ""}</span>
</div>
</article>
);
}
// ── Activity Feed Row ──────────────────────────────────────────────────────
function ActivityRow({ event, idx }: { event: ActivityEvent; idx: number }) {
const codeClass = FEED_CODE_CLASS[event.event_type] ?? "cc-feed__code--default";
const code = event.event_type.replace(/_/g, " ").toUpperCase();
return (
<div className="cc-feed__row cc-rise" data-stagger={Math.min(idx + 1, 10)}>
<span className="cc-feed__time">
{event.created_at ? formatTime(event.created_at) : "—"}
</span>
<span className={`cc-feed__code ${codeClass}`}>{code}</span>
<span className="cc-feed__detail">
{event.brand_name && <span className="cc-feed__brand">{event.brand_name}</span>}
<span className="cc-feed__entity">{event.entity_type ?? "event"}</span>
{event.entity_id && (
<span className="cc-feed__entity-id">#{event.entity_id.slice(0, 8)}</span>
)}
</span>
<span className="cc-feed__ago">{event.created_at ? timeAgo(event.created_at) : ""}</span>
</div>
);
}
// ── Main ──────────────────────────────────────────────────────────────────
export default function CommandCenterDashboard() {
const [metrics, setMetrics] = useState<PlatformMetrics | null>(null);
const [activity, setActivity] = useState<ActivityEvent[]>([]);
const [brandHealth, setBrandHealth] = useState<BrandHealth[]>([]);
const [painLog, setPainLog] = useState<PainLogItem[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [resolving, setResolving] = useState<Set<string>>(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<Set<string>>(new Set());
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);
}
}, []);
useEffect(() => {
fetchAll();
const iv = setInterval(fetchAll, REFRESH_INTERVAL);
return () => clearInterval(iv);
}, [fetchAll]);
const handleResolve = async (id: string) => {
if (resolving.has(id)) return;
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));
// ── Loading state ─────────────────────────────────────────────────────
if (loading) {
return (
<div className="cc-schematic" data-tv={tvMode ? "true" : "false"}>
<TopBar brands={[]} />
<div className="cc-frame">
<div className="cc-masthead cc-rise">
<div>
<div className="cc-masthead__eyebrow">{"// "}00 · BOOT SEQUENCE</div>
<h1 className="cc-masthead__title">Command <em>Center</em></h1>
</div>
</div>
<div className="cc-skeleton cc-rise" data-stagger="1" style={{ marginTop: 32 }}>
<span className="cc-skeleton__bar"><span></span><span></span></span>
<span>Initializing platform channels</span>
<span style={{ marginLeft: "auto", color: "var(--cc-faint)" }}>{"// "}awaiting telemetry</span>
</div>
</div>
</div>
);
}
// ── Error state ("Signal Lost") ────────────────────────────────────────
if (error) {
return (
<div className="cc-schematic" data-tv={tvMode ? "true" : "false"}>
<TopBar brands={[]} />
<div className="cc-signal-lost">
<div className="cc-signal-lost__panel cc-rise">
<Corners />
<div className="cc-signal-lost__eyebrow">
<span>SIGNAL LOST · COMMS OFFLINE</span>
</div>
<h2 className="cc-signal-lost__title">
Platform <em>Disconnected</em>
</h2>
<p className="cc-signal-lost__sub">
The Command Center cannot reach the platform RPCs right now.
This is usually a transient database or auth issue the data is safe, the connection isn{`'`}t.
</p>
<div className="cc-signal-lost__error">{error}</div>
<div className="cc-signal-lost__actions">
<button onClick={fetchAll} className="cc-btn cc-btn--primary">
<span></span> Reconnect
</button>
<a href="/admin" className="cc-btn cc-btn--ghost">Return to admin</a>
</div>
<div className="cc-signal-lost__hint">
<span>{"// "}SUGGESTED · check DATABASE_URL · re-run migrations</span>
<span>CODE: <b style={{ color: "var(--cc-critical)" }}>RPC_UNREACHABLE</b></span>
</div>
</div>
</div>
</div>
);
}
// ── Main state ────────────────────────────────────────────────────────
return (
<div className="cc-schematic" data-tv={tvMode ? "true" : "false"}>
<TopBar brands={brandHealth} />
<div className="cc-frame">
{/* ── Masthead ───────────────────────────────────────────────────── */}
<div className="cc-masthead cc-rise">
<div>
<div className="cc-masthead__eyebrow">{"// "}01 · PLATFORM OPERATIONS</div>
<h1 className="cc-masthead__title">Command <em>Center</em></h1>
<p className="cc-masthead__sub">
Real-time platform telemetry · {brandHealth.length} active brand{brandHealth.length !== 1 ? "s" : ""} ·
last sync <b>just now</b> · refresh every <b>30s</b>
</p>
</div>
<div className="cc-masthead__actions">
<button onClick={fetchAll} className="cc-btn cc-btn--ghost">
<span></span> Refresh
</button>
<button onClick={() => setTvMode(v => !v)} className="cc-btn">
{tvMode ? "Exit TV" : "TV Mode"}
</button>
</div>
</div>
{/* ── KPI Row ────────────────────────────────────────────────────── */}
<section className="cc-section">
<div className="cc-section__head">
<span className="cc-section__serial">{"// "}02</span>
<span className="cc-section__title">KPI OVERVIEW</span>
<span className="cc-section__rule" />
<span className="cc-section__count">06</span>
</div>
<div className="cc-kpi-grid">
<KPICard
serial="M.01" label="Active Brands" delay={1}
value={metrics?.active_brands ?? 0}
sub={`${brandHealth.filter(b => b.health_status === "healthy").length} healthy`}
sparkSeed="brands" status="healthy"
/>
<KPICard
serial="M.02" label="Orders Today" delay={2}
value={metrics?.orders_today ?? 0}
sub={`${metrics?.pending_orders_today ?? 0} pending`}
sparkSeed="orders" status={(metrics?.failed_orders_today ?? 0) > 0 ? "critical" : "healthy"}
/>
<KPICard
serial="M.03" label="Revenue Today" delay={3}
value={formatCurrency(Number(metrics?.revenue_today ?? 0))}
sub="24h window"
sparkSeed="revenue" status="healthy"
/>
<KPICard
serial="M.04" label="Active Routes" delay={4}
value={metrics?.active_routes ?? 0}
sub="In field"
sparkSeed="routes" status={(metrics?.pending_orders_today ?? 0) > 5 ? "warn" : "healthy"}
/>
<KPICard
serial="M.05" label="Failed Orders" delay={5}
value={metrics?.failed_orders_today ?? 0}
sub={metrics?.failed_orders_today ? "Needs attention" : "All clean"}
sparkSeed="failed" status={(metrics?.failed_orders_today ?? 0) > 0 ? "critical" : "healthy"}
/>
<KPICard
serial="M.06" label="Pending Orders" delay={6}
value={metrics?.pending_orders_today ?? 0}
sub="Awaiting confirmation"
sparkSeed="pending" status={(metrics?.pending_orders_today ?? 0) > 5 ? "warn" : "healthy"}
/>
</div>
</section>
{/* ── AI Briefing ─────────────────────────────────────────────────── */}
<section className="cc-section">
<div className="cc-section__head">
<span className="cc-section__serial">{"// "}03</span>
<span className="cc-section__title">DAILY BRIEFING</span>
<span className="cc-section__rule" />
<span className="cc-section__count">AUTO</span>
</div>
<AIBriefing metrics={metrics} brandHealth={brandHealth} />
</section>
{/* ── Two-column body ────────────────────────────────────────────── */}
<div className="cc-grid">
{/* LEFT: Brand Health + Activity */}
<div>
<section className="cc-section">
<div className="cc-section__head">
<span className="cc-section__serial">{"// "}04</span>
<span className="cc-section__title">BRAND HEALTH</span>
<span className="cc-section__rule" />
<span className="cc-section__count">{brandHealth.length}</span>
</div>
{brandHealth.length === 0 ? (
<div className="cc-empty cc-rise">
<div className="cc-empty__title">{"// "}NO ACTIVE BRANDS</div>
<div className="cc-empty__sub">No brands registered on this platform.</div>
</div>
) : (
<div style={{ display: "grid", gap: 16 }}>
{brandHealth.map((b, i) => (
<BrandPanel key={b.brand_id} brand={b} delay={i + 1} />
))}
</div>
)}
</section>
<section className="cc-section">
<div className="cc-section__head">
<span className="cc-section__serial">{"// "}05</span>
<span className="cc-section__title">LIVE ACTIVITY</span>
<span className="cc-section__rule" />
<span className="cc-section__count">{activity.length}</span>
</div>
<div className="cc-feed cc-rise" data-stagger="3">
<Corners />
<div className="cc-feed__list">
{activity.length === 0 ? (
<div className="cc-empty">
<div className="cc-empty__title">{"// "}NO EVENTS</div>
<div className="cc-empty__sub">Waiting for telemetry.</div>
</div>
) : (
activity.slice(0, 30).map((e, i) => (
<ActivityRow key={e.id} event={e} idx={i} />
))
)}
</div>
</div>
</section>
</div>
{/* RIGHT: Founder Queue + Quick Access */}
<div>
<section className="cc-section">
<div className="cc-section__head">
<span className="cc-section__serial">{"// "}06</span>
<span className="cc-section__title">FOUNDER QUEUE</span>
<span className="cc-section__rule" />
<span className="cc-section__count">{openItems.length}</span>
<button
onClick={() => setShowAddForm(v => !v)}
className="cc-btn cc-btn--ghost"
style={{ marginLeft: 12 }}
>
{showAddForm ? "Cancel" : "+ Log Issue"}
</button>
</div>
{showAddForm && (
<div className="cc-form cc-rise" data-stagger="1" style={{ marginBottom: 16 }}>
<div className="cc-form__head">NEW PAIN LOG ENTRY</div>
<div className="cc-form__row">
<select
value={addForm.severity}
onChange={e => setAddForm(f => ({ ...f, severity: e.target.value }))}
className="cc-field"
>
<option value="low">LOW</option>
<option value="medium">MEDIUM</option>
<option value="high">HIGH</option>
<option value="critical">CRITICAL</option>
</select>
<input
value={addForm.category}
onChange={e => setAddForm(f => ({ ...f, category: e.target.value }))}
placeholder="category (e.g. deployment)"
className="cc-field"
/>
</div>
<input
value={addForm.title}
onChange={e => setAddForm(f => ({ ...f, title: e.target.value }))}
placeholder="issue title..."
className="cc-field"
/>
<textarea
value={addForm.description}
onChange={e => setAddForm(f => ({ ...f, description: e.target.value }))}
placeholder="description (optional)"
rows={2}
className="cc-field"
style={{ resize: "none", fontFamily: "var(--cc-font-mono)" }}
/>
<div className="cc-form__actions">
<button onClick={handleAdd} className="cc-btn cc-btn--primary">Log Issue</button>
<button onClick={() => setShowAddForm(false)} className="cc-btn cc-btn--ghost">Discard</button>
</div>
</div>
)}
{openItems.length === 0 ? (
<div className="cc-empty cc-rise">
<div className="cc-empty__title">{"// "}QUEUE CLEAR</div>
<div className="cc-empty__sub">No open founder pain items. Add one to track it here.</div>
</div>
) : (
<div style={{ display: "grid", gap: 12 }}>
{openItems.map((item, i) => (
<PainItem
key={item.id}
item={item}
idx={i + 1}
onResolve={handleResolve}
onSnooze={handleSnooze}
/>
))}
</div>
)}
</section>
<section className="cc-section">
<div className="cc-section__head">
<span className="cc-section__serial">{"// "}07</span>
<span className="cc-section__title">QUICK ACCESS</span>
<span className="cc-section__rule" />
<span className="cc-section__count">{QUICK_ACCESS.length}</span>
</div>
<div className="cc-links cc-rise" data-stagger="2">
<Corners />
{QUICK_ACCESS.map((link, i) => (
<a
key={link.href}
href={link.href}
className="cc-link"
>
<span className="cc-link__serial">L.{String(i + 1).padStart(2, "0")}</span>
<span className="cc-link__label">{link.label}</span>
<span className="cc-link__arrow"></span>
</a>
))}
</div>
</section>
</div>
</div>
</div>
</div>
);
}