import { useState, useMemo, useRef } from "react"; // ─── DATASET ──────────────────────────────────────────────────────────────── import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const SEED_CAMPAIGNS = [{ id: 1, name: "Marriott Summer Escape", advertiser: "Marriott Bonvoy", budget: 120000, spend_to_date: 28000, start_date: "2025-05-01", end_date: "2025-07-31", ctr: 0.021, notes: "Narrow geo targeting to NYC/LA only", metrics: { impressions: 1320000, clicks: 27720, attributed_sales: 94000, attributed_units: 312, cpc: 1.01, ntb_sales: 38000, ntb_pct: 0.40, conversions: 890, daily_spend: [2100, 1950, 2300, 2180, 2050, 2400, 2250, 1980, 2100, 2350, 2200, 2080, 2190, 2310] } }, { id: 2, name: "Delta SkyMiles Spring Push", advertiser: "Delta Air Lines", budget: 85000, spend_to_date: 72000, start_date: "2025-04-01", end_date: "2025-06-10", ctr: 0.003, notes: "Running well, strong impressions", metrics: { impressions: 4800000, clicks: 14400, attributed_sales: 58000, attributed_units: 210, cpc: 5.00, ntb_sales: 12000, ntb_pct: 0.21, conversions: 310, daily_spend: [2400, 2600, 2200, 2800, 2500, 2300, 2700, 2400, 2600, 2100, 2400, 2300, 2500, 2200] } }, { id: 3, name: "Hilton Honors Q2", advertiser: "Hilton Hotels", budget: 200000, spend_to_date: 0, start_date: "2025-05-10", end_date: "2025-08-10", ctr: null, notes: "Waiting on assets from creative team", metrics: { impressions: null, clicks: null, attributed_sales: null, attributed_units: null, cpc: null, ntb_sales: null, ntb_pct: null, conversions: null, daily_spend: [] } }, { id: 4, name: "Expedia Package Deals", advertiser: "Expedia Group", budget: 65000, spend_to_date: 18000, start_date: "2025-04-15", end_date: "2025-06-30", ctr: 0.008, notes: "Pixel tracking issue flagged by eng", metrics: { impressions: 2250000, clicks: 18000, attributed_sales: null, attributed_units: null, cpc: 1.00, ntb_sales: null, ntb_pct: null, conversions: null, daily_spend: [900, 1100, 1050, 980, 1200, 950, 880, 1100, 1050, 1000, 1150, 920, 1080, 990] } }, { id: 5, name: "United MileagePlus Summer", advertiser: "United Airlines", budget: 150000, spend_to_date: 134000, start_date: "2025-04-01", end_date: "2025-06-25", ctr: 0.006, notes: "Pacing ahead, watch end date", metrics: { impressions: 8900000, clicks: 53400, attributed_sales: 210000, attributed_units: 780, cpc: 2.51, ntb_sales: 62000, ntb_pct: 0.30, conversions: 1840, daily_spend: [4500, 4800, 5100, 4600, 5200, 4900, 4700, 5300, 4800, 4600, 5100, 4700, 4900, 5200] } }, { id: 6, name: "Airbnb Experiences NYC", advertiser: "Airbnb", budget: 45000, spend_to_date: 41000, start_date: "2025-05-01", end_date: "2025-07-15", ctr: 0.019, notes: "Strong performance, creative fresh", metrics: { impressions: 2160000, clicks: 41040, attributed_sales: 138000, attributed_units: 460, cpc: 1.00, ntb_sales: 55000, ntb_pct: 0.40, conversions: 1230, daily_spend: [2700, 2850, 2600, 2900, 2750, 2680, 2820, 2700, 2950, 2800, 2650, 2900, 2750, 2820] } }, { id: 7, name: "Hyatt Globalist Promo", advertiser: "Hyatt Hotels", budget: 90000, spend_to_date: 12000, start_date: "2025-04-20", end_date: "2025-06-30", ctr: 0.002, notes: "Launch delayed, awaiting legal approval", metrics: { impressions: 6000000, clicks: 12000, attributed_sales: 18000, attributed_units: 62, cpc: 1.00, ntb_sales: 4500, ntb_pct: 0.25, conversions: 180, daily_spend: [800, 850, 920, 880, 760, 900, 840, 870, 820, 900, 780, 860, 840, 890] } }, { id: 8, name: "Southwest Wanna Get Away", advertiser: "Southwest Airlines", budget: 55000, spend_to_date: 8000, start_date: "2025-05-05", end_date: "2025-06-20", ctr: 0.011, notes: "Geo limited to Texas markets", metrics: { impressions: 727000, clicks: 8000, attributed_sales: 28000, attributed_units: 95, cpc: 1.00, ntb_sales: 9500, ntb_pct: 0.34, conversions: 320, daily_spend: [500, 560, 520, 580, 540, 510, 570, 530, 550, 490, 560, 540, 520, 580] } }, { id: 9, name: "Booking.com Summer Sale", advertiser: "Booking.com", budget: 175000, spend_to_date: 88000, start_date: "2025-04-01", end_date: "2025-07-01", ctr: 0.009, notes: "On track, mid-flight review done", metrics: { impressions: 9780000, clicks: 88020, attributed_sales: 295000, attributed_units: 1100, cpc: 1.00, ntb_sales: 91000, ntb_pct: 0.31, conversions: 3200, daily_spend: [2800, 3100, 2950, 3200, 2900, 3050, 2800, 3100, 2950, 3200, 2750, 3000, 2900, 3100] } }, { id: 10, name: "Four Seasons Luxury Launch", advertiser: "Four Seasons", budget: 300000, spend_to_date: 0, start_date: "2025-05-12", end_date: "2025-09-01", ctr: null, notes: "Not yet launched — integration on hold", metrics: { impressions: null, clicks: null, attributed_sales: null, attributed_units: null, cpc: null, ntb_sales: null, ntb_pct: null, conversions: null, daily_spend: [] } }, { id: 11, name: "American Airlines AAdvantage", advertiser: "American Airlines", budget: 110000, spend_to_date: 96000, start_date: "2025-04-10", end_date: "2025-06-15", ctr: 0.004, notes: "High frequency, users seeing ads repeatedly", metrics: { impressions: 6000000, clicks: 24000, attributed_sales: 72000, attributed_units: 240, cpc: 4.00, ntb_sales: 11000, ntb_pct: 0.15, conversions: 520, daily_spend: [3200, 3400, 3100, 3500, 3200, 3400, 3100, 3600, 3200, 3300, 3500, 3100, 3400, 3200] } }, { id: 12, name: "VRBO Beach Summer", advertiser: "VRBO", budget: 40000, spend_to_date: 22000, start_date: "2025-05-01", end_date: "2025-06-30", ctr: 0.013, notes: "Performing well in coastal markets", metrics: { impressions: 1690000, clicks: 21970, attributed_sales: 74000, attributed_units: 248, cpc: 1.00, ntb_sales: 29000, ntb_pct: 0.39, conversions: 740, daily_spend: [1400, 1550, 1480, 1620, 1500, 1450, 1580, 1520, 1490, 1560, 1430, 1510, 1550, 1480] } }, { id: 13, name: "IHG Rewards Club Push", advertiser: "IHG Hotels", budget: 70000, spend_to_date: 9000, start_date: "2025-04-25", end_date: "2025-06-28", ctr: 0.007, notes: "Paused by client, awaiting new brief", metrics: { impressions: 1285000, clicks: 9000, attributed_sales: 22000, attributed_units: 78, cpc: 1.00, ntb_sales: 6600, ntb_pct: 0.30, conversions: 220, daily_spend: [600, 640, 580, 620, 590, 0, 0, 0, 0, 0, 0, 0, 0, 0] } }, { id: 14, name: "Norwegian Cruise Q2", advertiser: "Norwegian Cruise", budget: 95000, spend_to_date: 51000, start_date: "2025-04-01", end_date: "2025-06-30", ctr: 0.010, notes: "Steady delivery, no issues reported", metrics: { impressions: 5100000, clicks: 51000, attributed_sales: 168000, attributed_units: 560, cpc: 1.00, ntb_sales: 58000, ntb_pct: 0.35, conversions: 1400, daily_spend: [1700, 1800, 1650, 1900, 1750, 1820, 1700, 1850, 1780, 1720, 1860, 1740, 1800, 1750] } }, { id: 15, name: "Tripadvisor Sponsored", advertiser: "Tripadvisor", budget: 30000, spend_to_date: 4000, start_date: "2025-05-08", end_date: "2025-06-18", ctr: 0.016, notes: "Narrow audience — travel enthusiasts 45+", metrics: { impressions: 250000, clicks: 4000, attributed_sales: 14000, attributed_units: 48, cpc: 1.00, ntb_sales: 4200, ntb_pct: 0.30, conversions: 160, daily_spend: [280, 300, 260, 320, 290, 310, 270, 300, 285, 295, 310, 275, 290, 305] } }]; // Simulated action log per campaign → maps to team handles const ACTION_LOG = [{ campaignId: 3, teamHandle: "Creative", action: "Retrieve creative assets", status: "overdue", dueDate: "2025-06-08" }, { campaignId: 10, teamHandle: "Engineering", action: "Resolve integration blocker", status: "overdue", dueDate: "2025-06-05" }, { campaignId: 4, teamHandle: "Engineering", action: "Fix pixel tracking tag", status: "overdue", dueDate: "2025-06-07" }, { campaignId: 7, teamHandle: "Legal", action: "Complete legal approval for launch", status: "overdue", dueDate: "2025-06-06" }, { campaignId: 13, teamHandle: "Sales", action: "Resume campaign — get new brief", status: "pending", dueDate: "2025-06-14" }, { campaignId: 2, teamHandle: "AdOps", action: "Increase daily spend cap", status: "pending", dueDate: "2025-06-13" }, { campaignId: 5, teamHandle: "AdOps", action: "Apply daily spend cap before end date", status: "pending", dueDate: "2025-06-14" }, { campaignId: 11, teamHandle: "Creative", action: "Refresh creative — fatigue detected", status: "pending", dueDate: "2025-06-15" }, { campaignId: 8, teamHandle: "AdOps", action: "Expand geo targeting beyond Texas", status: "in_progress", dueDate: "2025-06-13" }, { campaignId: 1, teamHandle: "AdOps", action: "Remove frequency caps", status: "in_progress", dueDate: "2025-06-14" }, { campaignId: 9, teamHandle: "AdOps", action: "Weekly pacing check", status: "done", dueDate: "2025-06-10" }, { campaignId: 6, teamHandle: "Creative", action: "Prepare next creative rotation", status: "done", dueDate: "2025-06-12" }]; const TEAM = [{ handle: "AdOps", name: "Ad Operations", avatar: "AO", color: "#5b8dd9" }, { handle: "Creative", name: "Creative Team", avatar: "CR", color: "#a855c8" }, { handle: "Engineering", name: "Engineering", avatar: "EN", color: "#d97b3a" }, { handle: "Sales", name: "Sales Team", avatar: "SA", color: "#3ab87a" }, { handle: "Legal", name: "Legal", avatar: "LG", color: "#c8a83a" }, { handle: "BobaFett", name: "Boba Fett", avatar: "BF", color: "#7ab83a" }, { handle: "Chewbacca", name: "Chewbacca", avatar: "CW", color: "#3ab8b8" }, { handle: "DarthVader", name: "Darth Vader", avatar: "DV", color: "#d93a3a" }, { handle: "LukeSkywalker", name: "Luke Skywalker", avatar: "LS", color: "#3a8cd9" }, { handle: "R2D2", name: "R2-D2", avatar: "R2", color: "#8cd93a" }]; const STATUS_STYLE = { overdue: { color: "#d93030", bg: "#1c0404", border: "#d9303035", label: "Overdue" }, pending: { color: "#d96800", bg: "#1a0c00", border: "#d9680035", label: "Pending" }, in_progress: { color: "#c9a200", bg: "#141200", border: "#c9a20035", label: "In Progress" }, done: { color: "#00a855", bg: "#001508", border: "#00a85535", label: "Done" } }; // ─── HELPERS ──────────────────────────────────────────────────────────────── const TODAY = new Date("2025-06-12"); const daysBetween = (a, b) => Math.max(0, (new Date(b) - new Date(a)) / 86400000); const daysPast = s => Math.max(0, daysBetween(s, TODAY)); const daysLeft = e => Math.max(0, daysBetween(TODAY, e)); const totalDays = c => daysBetween(c.start_date, c.end_date); const flightProg = c => Math.min(1, daysPast(c.start_date) / totalDays(c)); const flightLeft = c => 1 - flightProg(c); const spendProg = c => c.spend_to_date / c.budget; const pacingRatio = c => flightProg(c) > 0 ? spendProg(c) / flightProg(c) : 1; const pct = n => `${Math.round(n * 100)}%`; const money = n => `$${n.toLocaleString()}`; const moneyK = n => n >= 1000 ? `$${(n / 1000).toFixed(0)}K` : `$${n}`; const nextId = arr => Math.max(0, ...arr.map(c => c.id)) + 1; // ─── RISK ENGINE ──────────────────────────────────────────────────────────── const SIGNALS = [{ id: "not_launched", label: "Not Launched", severity: "critical", confidence: "high", check: c => c.spend_to_date === 0 && daysPast(c.start_date) > 0, reason: c => `Campaign launched ${Math.round(daysPast(c.start_date))} days ago with $0 recorded spend.`, action: "Confirm launch status. Check ad server for trafficking errors immediately." }, { id: "qualitative_blocker", label: "Operational Blocker", severity: "critical", confidence: "medium", check: c => /delayed|waiting on assets|paused|on hold|pixel|tracking|integration|legal/i.test(c.notes), reason: c => `A non-performance blocker is preventing delivery: "${c.notes}"`, action: "Identify blocker owner and set a 24-hour resolution SLA." }, { id: "end_date_crunch", label: "End-Date Crunch", severity: "high", confidence: "high", check: c => flightLeft(c) < 0.20 && spendProg(c) < 0.80, reason: c => `${pct(flightLeft(c))} of flight remains but only ${pct(spendProg(c))} of budget spent.`, action: "Increase daily spend cap or request a 1-week flight extension." }, { id: "under_pacing", label: "Under-Pacing", severity: "high", confidence: "high", check: c => pacingRatio(c) < 0.70 && flightProg(c) > 0.15, reason: c => `Spend at ${pct(spendProg(c))} but ${pct(flightProg(c))} of flight elapsed. Pacing: ${pct(pacingRatio(c))}.`, action: "Review targeting and daily caps. Escalate to account manager today." }, { id: "performance_risk", label: "Creative Fatigue", severity: "medium", confidence: "medium", check: c => c.ctr !== null && c.ctr < 0.005 && spendProg(c) > 0.40, reason: c => `CTR ${((c.ctr || 0) * 100).toFixed(2)}% below 0.5% benchmark after ${pct(spendProg(c))} spend.`, action: "Request creative refresh. Pause lowest-performing placements." }, { id: "healthy", label: "On Track", severity: "low", confidence: "high", check: () => true, reason: () => "Campaign pacing on track with no active flags.", action: "No intervention needed. Monitor weekly." }]; const ARCHETYPES = [{ id: "ghost", label: "The Ghost", icon: "👻", check: c => c.spend_to_date < c.budget * 0.35 && (c.ctr || 0) > 0.015 && /geo|narrow|limited/i.test(c.notes), insight: "Strong CTR but almost no impressions — audience too narrow." }, { id: "burnout", label: "The Burnout", icon: "🔥", check: c => spendProg(c) > 0.60 && c.ctr !== null && c.ctr < 0.004, insight: "High spend, declining engagement — creative fatigue." }, { id: "bottleneck", label: "The Bottleneck", icon: "🔧", check: c => pacingRatio(c) < 0.70 && /pixel|tracking|tag|integration/i.test(c.notes), insight: "Technical blocker causing under-delivery." }, { id: "cliff", label: "The Cliff", icon: "📉", check: c => spendProg(c) > 0.85 && daysLeft(c.end_date) > 10, insight: "Budget exhausts 10+ days before flight ends." }]; const dataFlags = c => { const flags = []; if (c.spend_to_date === 0 && daysPast(c.start_date) > 0) flags.push({ field: "All metrics", reason: "Campaign not delivering — no data available.", severity: "critical" }); if (/pixel|tracking|integration/i.test(c.notes)) flags.push({ field: "Attributed sales, conversions", reason: "Pixel/tracking issue detected. Conversion data may be incomplete.", severity: "high" }); if (c.metrics.impressions && c.metrics.clicks && c.metrics.impressions / c.metrics.clicks < 20) flags.push({ field: "CTR", reason: "CTR unusually high — possible bot traffic or over-retargeting.", severity: "medium" }); if (c.metrics.attributed_sales && c.spend_to_date && c.metrics.attributed_sales / c.spend_to_date > 5) flags.push({ field: "ROAS", reason: "ROAS >5x — verify 14-day click attribution window is set correctly.", severity: "medium" }); if (c.metrics.ntb_pct === null && c.spend_to_date > 0) flags.push({ field: "NTB data", reason: "New-to-brand data unavailable. May require additional tracking setup.", severity: "low" }); return flags; }; const evaluateOne = c => { const signal = SIGNALS.find(s => s.check(c)) || SIGNALS[SIGNALS.length - 1]; const archetype = ARCHETYPES.find(a => a.check(c)) || null; const allSignals = SIGNALS.filter(s => s.id !== "healthy" && s.check(c)).map(s => s.label); const m = c.metrics || {}; const roas = m.attributed_sales && c.spend_to_date > 0 ? m.attributed_sales / c.spend_to_date : null; const cac = m.conversions && c.spend_to_date > 0 ? c.spend_to_date / m.conversions : null; const convRate = m.conversions && m.clicks ? m.conversions / m.clicks : null; return { ...c, signal, archetype, allSignals, flightPct: flightProg(c), spendPct: spendProg(c), pacingPct: pacingRatio(c), daysRemaining: Math.round(daysLeft(c.end_date)), roas, cac, convRate, dataFlags: dataFlags(c) }; }; // ─── THEME ────────────────────────────────────────────────────────────────── const SEV = { critical: { bg: "#1c0404", border: "#d93030", accent: "#d93030", text: "#ff7070", label: "Critical", dot: "#d93030" }, high: { bg: "#1a0c00", border: "#d96800", accent: "#d96800", text: "#ff9944", label: "High Risk", dot: "#d96800" }, medium: { bg: "#141200", border: "#c9a200", accent: "#c9a200", text: "#f0c830", label: "Medium", dot: "#c9a200" }, low: { bg: "#001508", border: "#00a855", accent: "#00a855", text: "#33cc77", label: "Healthy", dot: "#00a855" } }; const DATA_FLAG_COLOR = { critical: "#d93030", high: "#d96800", medium: "#c9a200", low: "#888" }; // ─── SHARED COMPONENTS ────────────────────────────────────────────────────── const Bar = ({ value, color, bg = "#1e1e1e", h = 6 }) => /*#__PURE__*/_jsx("div", { style: { background: bg, borderRadius: 99, height: h, overflow: "hidden", width: "100%" }, children: /*#__PURE__*/_jsx("div", { style: { width: `${Math.min(100, Math.max(0, value * 100))}%`, background: color, height: "100%", borderRadius: 99, transition: "width .4s" } }) }); const Chip = ({ label, color, bg, size = 10 }) => /*#__PURE__*/_jsx("span", { style: { background: bg || color + "18", color, border: `1px solid ${color}35`, borderRadius: 4, padding: `1px ${size === 10 ? "7" : "9"}px`, fontSize: size, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", whiteSpace: "nowrap", display: "inline-block" }, children: label }); function Spark({ data, color = "#5b8dd9", h = 28, w = 80 }) { if (!data || data.length < 2) return /*#__PURE__*/_jsx("span", { style: { color: "#444", fontSize: 10 }, children: "\u2014" }); const max = Math.max(...data) || 1; const pts = data.map((v, i) => `${i / (data.length - 1) * w},${h - v / max * h}`).join(" "); return /*#__PURE__*/_jsx("svg", { width: w, height: h, style: { display: "block" }, children: /*#__PURE__*/_jsx("polyline", { points: pts, fill: "none", stroke: color, strokeWidth: 1.5, strokeLinejoin: "round" }) }); } // ─── @MENTION TEXTAREA ────────────────────────────────────────────────────── function MentionInput({ defaultText, campaignId }) { const [val, setVal] = useState(defaultText || ""); const [query, setQuery] = useState(""); const [show, setShow] = useState(false); const [pos, setPos] = useState(0); const [tags, setTags] = useState([]); const [sent, setSent] = useState(false); const ref = useRef(); const filtered = TEAM.filter(t => query === "" || t.handle.toLowerCase().includes(query.toLowerCase()) || t.name.toLowerCase().includes(query.toLowerCase())); const onChange = e => { const v = e.target.value, p = e.target.selectionStart; setVal(v); setPos(p); const at = v.lastIndexOf("@", p - 1); if (at !== -1 && at >= v.lastIndexOf(" ", p - 1) + 1) { setQuery(v.slice(at + 1, p)); setShow(true); } else { setShow(false); setQuery(""); } }; const insert = m => { const at = val.lastIndexOf("@", pos - 1); setVal(val.slice(0, at) + "@" + m.handle + " " + val.slice(pos)); setTags(t => [...t.filter(x => x.handle !== m.handle), m]); setShow(false); setQuery(""); setTimeout(() => { var _ref$current; return (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.focus(); }, 0); }; const preview = () => val.split(/(@\w+)/g).map((p, i) => { if (p.startsWith("@")) { const m = TEAM.find(t => t.handle === p.slice(1)); if (m) return /*#__PURE__*/_jsx("span", { style: { background: m.color + "22", color: m.color, borderRadius: 3, padding: "0 3px", fontWeight: 700 }, children: p }, i); } return /*#__PURE__*/_jsx("span", { children: p }, i); }); if (sent) return /*#__PURE__*/_jsxs("div", { style: { background: "#001a0a", border: "1px solid #00a85555", borderRadius: 8, padding: "12px 16px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#00a855", fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6 }, children: "\u2713 Action Logged" }), /*#__PURE__*/_jsx("div", { style: { color: "#ccc", fontSize: 13, lineHeight: 1.6 }, children: preview() }), tags.length > 0 && /*#__PURE__*/_jsx("div", { style: { marginTop: 8, display: "flex", gap: 5, flexWrap: "wrap" }, children: tags.map(m => /*#__PURE__*/_jsxs("span", { style: { display: "flex", alignItems: "center", gap: 4, background: m.color + "18", border: `1px solid ${m.color}40`, borderRadius: 20, padding: "2px 8px 2px 5px" }, children: [/*#__PURE__*/_jsx("span", { style: { width: 16, height: 16, borderRadius: "50%", background: m.color, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 7, fontWeight: 800, color: "#fff" }, children: m.avatar }), /*#__PURE__*/_jsx("span", { style: { color: m.color, fontSize: 11, fontWeight: 600 }, children: m.name }), /*#__PURE__*/_jsx("span", { style: { color: m.color + "80", fontSize: 10 }, children: "notified" })] }, m.handle)) }), /*#__PURE__*/_jsx("button", { onClick: () => setSent(false), style: { marginTop: 8, background: "none", border: "1px solid #333", color: "#555", borderRadius: 4, padding: "3px 10px", fontSize: 11, cursor: "pointer" }, children: "Edit" })] }); return /*#__PURE__*/_jsxs("div", { style: { position: "relative" }, children: [/*#__PURE__*/_jsx("textarea", { ref: ref, value: val, onChange: onChange, rows: 3, style: { width: "100%", background: "#001408", border: "1px solid #1a4030", borderRadius: 7, padding: "10px 12px", color: "#e4ffe4", fontSize: 13, lineHeight: 1.7, fontWeight: 500, resize: "vertical", outline: "none", boxSizing: "border-box", fontFamily: "inherit" } }), show && filtered.length > 0 && /*#__PURE__*/_jsx("div", { style: { position: "absolute", top: "100%", left: 0, zIndex: 300, background: "#0e1a12", border: "1px solid #1e4428", borderRadius: 8, padding: 4, minWidth: 220, boxShadow: "0 8px 30px #00000070", marginTop: 2 }, children: filtered.map(m => /*#__PURE__*/_jsxs("div", { onClick: () => insert(m), style: { display: "flex", alignItems: "center", gap: 8, padding: "7px 10px", cursor: "pointer", borderRadius: 5 }, onMouseEnter: e => e.currentTarget.style.background = "#162a1e", onMouseLeave: e => e.currentTarget.style.background = "transparent", children: [/*#__PURE__*/_jsx("span", { style: { width: 22, height: 22, borderRadius: "50%", background: m.color, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 8, fontWeight: 800, color: "#fff", flexShrink: 0 }, children: m.avatar }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsxs("div", { style: { color: "#ddd", fontSize: 12, fontWeight: 600 }, children: ["@", m.handle] }), /*#__PURE__*/_jsx("div", { style: { color: "#555", fontSize: 10 }, children: m.name })] })] }, m.handle)) }), tags.length > 0 && /*#__PURE__*/_jsx("div", { style: { marginTop: 6, display: "flex", gap: 5, flexWrap: "wrap" }, children: tags.map(m => /*#__PURE__*/_jsxs("span", { style: { display: "flex", alignItems: "center", gap: 4, background: m.color + "15", border: `1px solid ${m.color}35`, borderRadius: 20, padding: "2px 8px 2px 5px" }, children: [/*#__PURE__*/_jsx("span", { style: { width: 15, height: 15, borderRadius: "50%", background: m.color, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 7, fontWeight: 800, color: "#fff" }, children: m.avatar }), /*#__PURE__*/_jsxs("span", { style: { color: m.color, fontSize: 10, fontWeight: 600 }, children: ["@", m.handle] })] }, m.handle)) }), /*#__PURE__*/_jsxs("div", { style: { marginTop: 8, display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#2a5a3a", fontSize: 10 }, children: "Type @ to tag a teammate" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 6 }, children: [/*#__PURE__*/_jsx("button", { onClick: () => { setVal(defaultText || ""); setTags([]); }, style: { background: "none", border: "1px solid #1e3a28", color: "#446655", borderRadius: 5, padding: "5px 12px", fontSize: 11, cursor: "pointer" }, children: "Reset" }), /*#__PURE__*/_jsx("button", { onClick: () => setSent(true), style: { background: "#00a855", border: "none", color: "#fff", borderRadius: 5, padding: "5px 14px", fontSize: 11, fontWeight: 700, cursor: "pointer" }, children: "Send Action \u2192" })] })] })] }); } // ─── CAMPAIGN DETAIL MODAL ─────────────────────────────────────────────────── function CampaignModal({ c, onClose }) { if (!c) return null; const s = SEV[c.signal.severity]; const m = c.metrics || {}; const flags = c.dataFlags; const perfMetrics = [{ label: "ROAS", value: c.roas, unit: "x", bm: "Industry avg: 3–5x", good: c.roas != null && c.roas >= 3, flag: flags.some(f => f.field.includes("ROAS")) }, { label: "Attributed Sales", value: m.attributed_sales, unit: "$", bm: "Primary revenue signal", good: m.attributed_sales != null && m.attributed_sales > c.spend_to_date, flag: flags.some(f => f.field.includes("sales")) }, { label: "Spend to Date", value: c.spend_to_date, unit: "$", bm: `Budget: ${money(c.budget)}`, good: c.spendPct >= 0.6 && c.spendPct <= 1.1, flag: false, trend: m.daily_spend }, { label: "Conversion Rate", value: c.convRate, unit: "%", bm: "Benchmark: 8–15%", good: c.convRate != null && c.convRate >= 0.08, flag: flags.some(f => f.field.includes("conv")) }, { label: "Avg CTR", value: c.ctr, unit: "%", bm: "Benchmark: >0.5%", good: c.ctr != null && c.ctr >= 0.005, flag: c.ctr === null }, { label: "Attributed Units", value: m.attributed_units, unit: "", bm: "Units via ad", good: null, flag: flags.some(f => f.field.includes("conv")) }, { label: "Clicks", value: m.clicks, unit: "", bm: "", good: null, flag: m.clicks === null }, { label: "Viewable Impressions", value: m.impressions, unit: "", bm: "", good: null, flag: m.impressions === null }, { label: "Avg CPC", value: m.cpc, unit: "$", bm: "Benchmark: <$2.00", good: m.cpc != null && m.cpc < 2, flag: m.cpc === null }, { label: "Customer Acq. Cost", value: c.cac, unit: "$", bm: "Lower is better", good: c.cac != null && c.cac < 100, flag: c.cac === null }, { label: "New-to-Brand Sales", value: m.ntb_sales, unit: "$", bm: "Brand growth signal", good: null, flag: m.ntb_sales === null }, { label: "NTB Sales %", value: m.ntb_pct, unit: "%", bm: "Target: >25%", good: m.ntb_pct != null && m.ntb_pct >= 0.25, flag: m.ntb_pct === null }]; const fmtVal = (v, unit) => { if (v == null) return "—"; if (unit === "$") return money(v); if (unit === "%") return `${(v * 100).toFixed(2)}%`; if (unit === "x") return `${v.toFixed(2)}x`; return v.toLocaleString(); }; return /*#__PURE__*/_jsx("div", { style: { position: "fixed", inset: 0, zIndex: 500, display: "flex", alignItems: "flex-start", justifyContent: "center", background: "#000000cc", overflowY: "auto", padding: "32px 20px" }, onClick: e => { if (e.target === e.currentTarget) onClose(); }, children: /*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #252525", borderRadius: 14, width: "100%", maxWidth: 1060, boxShadow: "0 24px 80px #000000aa" }, children: [/*#__PURE__*/_jsxs("div", { style: { borderBottom: "1px solid #1e1e1e", padding: "16px 22px", display: "flex", alignItems: "flex-start", justifyContent: "space-between", background: "#0a0a0a", borderRadius: "14px 14px 0 0" }, children: [/*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 11, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 4 }, children: c.advertiser }), /*#__PURE__*/_jsx("h2", { style: { color: "#f0f0f0", fontSize: 20, fontWeight: 800, margin: "0 0 8px", letterSpacing: "-0.03em" }, children: c.name }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 6, flexWrap: "wrap", alignItems: "center" }, children: [/*#__PURE__*/_jsx(Chip, { label: s.label, color: s.accent, size: 11 }), c.archetype && /*#__PURE__*/_jsx(Chip, { label: `${c.archetype.icon} ${c.archetype.label}`, color: "#8888cc", bg: "#12121e", size: 10 }), /*#__PURE__*/_jsxs("span", { style: { color: "#404040", fontSize: 11 }, children: [c.start_date, " \u2192 ", c.end_date, " \xB7 ", c.daysRemaining, "d remaining"] })] })] }), /*#__PURE__*/_jsx("button", { onClick: onClose, style: { background: "none", border: "1px solid #2a2a2a", color: "#555", borderRadius: 7, padding: "7px 14px", cursor: "pointer", fontSize: 12, flexShrink: 0 }, children: "\u2715 Close" })] }), /*#__PURE__*/_jsxs("div", { style: { padding: "18px 22px", display: "flex", flexDirection: "column", gap: 14 }, children: [/*#__PURE__*/_jsxs("div", { style: { background: "linear-gradient(135deg,#001e10,#002915)", border: "1.5px solid #00a85555", borderRadius: 10, padding: "16px 18px" }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#00a855", fontSize: 15 }, children: "\u2192" }), /*#__PURE__*/_jsx("span", { style: { color: "#00a855", fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em" }, children: "Suggested Action" }), /*#__PURE__*/_jsx("span", { style: { marginLeft: "auto", color: "#2a5a3a", fontSize: 10 }, children: "Type @ to assign" })] }), /*#__PURE__*/_jsx(MentionInput, { defaultText: c.signal.action, campaignId: c.id }, c.id)] }), /*#__PURE__*/_jsxs("div", { style: { background: s.bg, border: `1.5px solid ${s.border}`, borderRadius: 10, padding: "14px 18px" }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, children: [/*#__PURE__*/_jsx("span", { style: { width: 8, height: 8, borderRadius: "50%", background: s.accent, display: "inline-block" } }), /*#__PURE__*/_jsx("span", { style: { color: s.text, fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em" }, children: "Risk Assessment" }), c.archetype && /*#__PURE__*/_jsxs("span", { style: { marginLeft: "auto", color: "#666", fontSize: 11 }, children: [c.archetype.icon, " ", c.archetype.insight] })] }), /*#__PURE__*/_jsx("p", { style: { color: "#ddd", fontSize: 14, lineHeight: 1.8, margin: 0 }, children: c.signal.reason(c) })] }), flags.length > 0 && /*#__PURE__*/_jsxs("div", { style: { background: "#0f0e00", border: "1px solid #c9a20040", borderRadius: 10, padding: "12px 16px" }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, children: [/*#__PURE__*/_jsx("span", { style: { fontSize: 13 }, children: "\uD83E\uDD16" }), /*#__PURE__*/_jsx("span", { style: { color: "#c9a200", fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.1em" }, children: "AI Data Flags" }), /*#__PURE__*/_jsxs("span", { style: { color: "#444", fontSize: 10, marginLeft: "auto" }, children: [flags.length, " issue", flags.length !== 1 ? "s" : ""] })] }), /*#__PURE__*/_jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: flags.map((f, i) => /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", background: "#161000", borderRadius: 6, padding: "7px 10px", borderLeft: `2px solid ${DATA_FLAG_COLOR[f.severity]}` }, children: [/*#__PURE__*/_jsx("span", { style: { color: DATA_FLAG_COLOR[f.severity], fontSize: 11, fontWeight: 700, flexShrink: 0, minWidth: 120 }, children: f.field }), /*#__PURE__*/_jsx("span", { style: { color: "#aaa", fontSize: 11.5, lineHeight: 1.5 }, children: f.reason }), /*#__PURE__*/_jsx(Chip, { label: f.severity, color: DATA_FLAG_COLOR[f.severity], size: 9 })] }, i)) })] }), /*#__PURE__*/_jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(6,1fr)", gap: 8 }, children: [{ label: "Budget", val: money(c.budget), color: "#e0e0e0" }, { label: "Spent", val: money(c.spend_to_date), color: s.text }, { label: "Spend %", val: pct(c.spendPct), color: s.text }, { label: "ROAS", val: c.roas ? `${c.roas.toFixed(2)}x` : "—", color: c.roas && c.roas >= 3 ? "#33cc77" : c.roas ? "#d96800" : "#555" }, { label: "CTR", val: c.ctr ? `${(c.ctr * 100).toFixed(2)}%` : "—", color: c.ctr && c.ctr >= 0.005 ? "#33cc77" : c.ctr ? "#d96800" : "#555" }, { label: "Days Left", val: `${c.daysRemaining}d`, color: c.daysRemaining < 14 ? s.text : "#bbb" }].map(k => /*#__PURE__*/_jsxs("div", { style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 8, padding: "10px 12px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 4 }, children: k.label }), /*#__PURE__*/_jsx("div", { style: { color: k.color, fontSize: 14, fontWeight: 800, fontFamily: "monospace" }, children: k.val })] }, k.label)) }), /*#__PURE__*/_jsxs("div", { style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 10, padding: "14px 16px" }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6 }, children: [/*#__PURE__*/_jsxs("span", { style: { color: "#555", fontSize: 12 }, children: ["Budget: ", /*#__PURE__*/_jsx("span", { style: { color: "#bbb", fontWeight: 600 }, children: money(c.spend_to_date) }), " of ", /*#__PURE__*/_jsx("span", { style: { color: "#bbb", fontWeight: 600 }, children: money(c.budget) }), " (", pct(c.spendPct), ")"] }), /*#__PURE__*/_jsxs("span", { style: { color: "#555", fontSize: 12 }, children: ["Remaining: ", /*#__PURE__*/_jsx("span", { style: { color: "#ccc", fontWeight: 600 }, children: money(c.budget - c.spend_to_date) })] })] }), /*#__PURE__*/_jsx(Bar, { value: c.spendPct, color: s.accent, h: 9, bg: "#1a1a1a" }), /*#__PURE__*/_jsxs("div", { style: { marginTop: 6 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 4 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#555", fontSize: 10 }, children: "Flight elapsed" }), /*#__PURE__*/_jsx("span", { style: { color: "#4488ff", fontSize: 10, fontWeight: 700 }, children: pct(c.flightPct) })] }), /*#__PURE__*/_jsx(Bar, { value: c.flightPct, color: "#4488ff", h: 5, bg: "#1a1a1a" })] }), m.daily_spend && m.daily_spend.length > 1 && /*#__PURE__*/_jsxs("div", { style: { marginTop: 10 }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Daily Spend (last 14 days)" }), /*#__PURE__*/_jsx(Spark, { data: m.daily_spend, color: s.accent, h: 34, w: 500 })] })] }), /*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #1e1e1e", borderRadius: 10, overflow: "hidden" }, children: [/*#__PURE__*/_jsxs("div", { style: { padding: "12px 16px", borderBottom: "1px solid #1e1e1e", display: "flex", alignItems: "center", gap: 10 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#e0e0e0", fontSize: 13, fontWeight: 700 }, children: "Full Performance Metrics" }), /*#__PURE__*/_jsx("span", { style: { color: "#505050", fontSize: 11 }, children: "ordered by decision impact" }), flags.length > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#1a1400", border: "1px solid #c9a20040", borderRadius: 4, padding: "2px 7px", fontSize: 10, color: "#c9a200", marginLeft: "auto" }, children: ["\u26A0 ", flags.length, " data flag", flags.length !== 1 ? "s" : ""] })] }), /*#__PURE__*/_jsxs("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [/*#__PURE__*/_jsx("thead", { children: /*#__PURE__*/_jsx("tr", { style: { background: "#111", borderBottom: "1px solid #1e1e1e" }, children: ["Metric", "Value", "Benchmark", "Status", "Trend"].map(h => /*#__PURE__*/_jsx("th", { style: { padding: "7px 14px", color: "#505050", fontSize: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.08em", textAlign: "left" }, children: h }, h)) }) }), /*#__PURE__*/_jsx("tbody", { children: perfMetrics.map((r, i) => { const sc = r.value == null ? "#444" : r.good === true ? "#00a855" : r.good === false ? "#d93030" : "#888"; return /*#__PURE__*/_jsxs("tr", { style: { borderBottom: "1px solid #161616", background: i % 2 === 0 ? "#111" : "transparent" }, children: [/*#__PURE__*/_jsx("td", { style: { padding: "9px 14px", color: "#aaa", fontSize: 12.5, fontWeight: 500 }, children: r.label }), /*#__PURE__*/_jsx("td", { style: { padding: "9px 14px", fontFamily: "monospace", fontSize: 13, fontWeight: 700, color: sc }, children: fmtVal(r.value, r.unit) }), /*#__PURE__*/_jsx("td", { style: { padding: "9px 14px", color: "#555", fontSize: 11 }, children: r.bm }), /*#__PURE__*/_jsx("td", { style: { padding: "9px 14px" }, children: r.flag ? /*#__PURE__*/_jsx("span", { style: { background: "#1a1400", border: "1px solid #c9a20040", borderRadius: 4, padding: "2px 7px", fontSize: 9, color: "#c9a200", whiteSpace: "nowrap" }, children: "\u26A0 AI Flag" }) : r.value != null ? /*#__PURE__*/_jsx("span", { style: { color: "#333", fontSize: 11 }, children: "\u2713" }) : /*#__PURE__*/_jsx("span", { style: { color: "#333", fontSize: 11 }, children: "\u2014" }) }), /*#__PURE__*/_jsx("td", { style: { padding: "9px 8px" }, children: r.trend && /*#__PURE__*/_jsx(Spark, { data: r.trend, color: sc || "#5b8dd9", h: 22, w: 60 }) })] }, r.label); }) })] })] }), c.notes && /*#__PURE__*/_jsxs("div", { style: { background: "#0d0d0d", border: "1px solid #1e1e1e", borderLeft: "2px solid #2a2a2a", borderRadius: 8, padding: "12px 16px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Campaign Notes" }), /*#__PURE__*/_jsxs("div", { style: { color: "#666", fontSize: 12.5, lineHeight: 1.65, fontStyle: "italic" }, children: ["\"", c.notes, "\""] })] })] })] }) }); } // ─── NEW CAMPAIGN MODAL ────────────────────────────────────────────────────── function NewCampaignModal({ onClose, onCreate }) { const [form, setForm] = useState({ name: "", advertiser: "", budget: "", spend_to_date: "0", start_date: "", end_date: "", ctr: "", notes: "" }); const [err, setErr] = useState(""); const set = k => e => setForm(f => ({ ...f, [k]: e.target.value })); const submit = () => { if (!form.name.trim() || !form.advertiser.trim() || !form.budget || !form.start_date || !form.end_date) { setErr("Name, Advertiser, Budget, Start & End Date are required."); return; } if (new Date(form.end_date) <= new Date(form.start_date)) { setErr("End date must be after start date."); return; } const raw = { id: Date.now(), name: form.name.trim(), advertiser: form.advertiser.trim(), budget: parseInt(form.budget) || 0, spend_to_date: parseInt(form.spend_to_date) || 0, start_date: form.start_date, end_date: form.end_date, ctr: form.ctr ? parseFloat(form.ctr) : null, notes: form.notes.trim(), metrics: { impressions: null, clicks: null, attributed_sales: null, attributed_units: null, cpc: null, ntb_sales: null, ntb_pct: null, conversions: null, daily_spend: [] } }; onCreate(evaluateOne(raw)); onClose(); }; const F = ({ label, k, type = "text", placeholder = "", required = false }) => /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsxs("label", { style: { color: "#888", fontSize: 11, display: "block", marginBottom: 4, textTransform: "uppercase", letterSpacing: "0.06em" }, children: [label, required && /*#__PURE__*/_jsx("span", { style: { color: "#d93030", marginLeft: 2 }, children: "*" })] }), /*#__PURE__*/_jsx("input", { type: type, value: form[k], onChange: set(k), placeholder: placeholder, style: { width: "100%", background: "#111", border: "1px solid #252525", borderRadius: 6, padding: "8px 11px", color: "#e0e0e0", fontSize: 13, outline: "none", colorScheme: "dark" } })] }); return /*#__PURE__*/_jsx("div", { style: { position: "fixed", inset: 0, zIndex: 600, display: "flex", alignItems: "center", justifyContent: "center", background: "#000000cc", padding: "20px" }, onClick: e => { if (e.target === e.currentTarget) onClose(); }, children: /*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #252525", borderRadius: 14, width: "100%", maxWidth: 560, boxShadow: "0 24px 80px #000" }, children: [/*#__PURE__*/_jsxs("div", { style: { borderBottom: "1px solid #1e1e1e", padding: "16px 22px", display: "flex", alignItems: "center", justifyContent: "space-between", background: "#0a0a0a", borderRadius: "14px 14px 0 0" }, children: [/*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#f0f0f0", fontSize: 16, fontWeight: 700 }, children: "New Campaign" }), /*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 11, marginTop: 2 }, children: "Add a campaign to the risk monitor" })] }), /*#__PURE__*/_jsx("button", { onClick: onClose, style: { background: "none", border: "1px solid #2a2a2a", color: "#555", borderRadius: 6, padding: "6px 12px", cursor: "pointer", fontSize: 12 }, children: "\u2715" })] }), /*#__PURE__*/_jsxs("div", { style: { padding: "20px 22px", display: "flex", flexDirection: "column", gap: 12 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }, children: [/*#__PURE__*/_jsx(F, { label: "Campaign Name", k: "name", placeholder: "e.g. Marriott Summer '25", required: true }), /*#__PURE__*/_jsx(F, { label: "Advertiser", k: "advertiser", placeholder: "e.g. Marriott Bonvoy", required: true })] }), /*#__PURE__*/_jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }, children: [/*#__PURE__*/_jsx(F, { label: "Budget ($)", k: "budget", type: "number", placeholder: "100000", required: true }), /*#__PURE__*/_jsx(F, { label: "Spend to Date ($)", k: "spend_to_date", type: "number", placeholder: "0" }), /*#__PURE__*/_jsx(F, { label: "CTR (decimal)", k: "ctr", type: "number", placeholder: "0.012" })] }), /*#__PURE__*/_jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }, children: [/*#__PURE__*/_jsx(F, { label: "Start Date", k: "start_date", type: "date", required: true }), /*#__PURE__*/_jsx(F, { label: "End Date", k: "end_date", type: "date", required: true })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("label", { style: { color: "#888", fontSize: 11, display: "block", marginBottom: 4, textTransform: "uppercase", letterSpacing: "0.06em" }, children: "Notes / Status" }), /*#__PURE__*/_jsx("textarea", { value: form.notes, onChange: set("notes"), placeholder: "e.g. Waiting on assets, pixel issue, geo restrictions...", rows: 2, style: { width: "100%", background: "#111", border: "1px solid #252525", borderRadius: 6, padding: "8px 11px", color: "#e0e0e0", fontSize: 13, outline: "none", resize: "vertical", fontFamily: "inherit", boxSizing: "border-box" } })] }), err && /*#__PURE__*/_jsx("div", { style: { color: "#d93030", fontSize: 12, background: "#1c0404", border: "1px solid #d9303035", borderRadius: 6, padding: "8px 12px" }, children: err }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, paddingTop: 4 }, children: [/*#__PURE__*/_jsx("button", { onClick: onClose, style: { background: "none", border: "1px solid #252525", color: "#555", borderRadius: 6, padding: "8px 16px", fontSize: 12, cursor: "pointer" }, children: "Cancel" }), /*#__PURE__*/_jsx("button", { onClick: submit, style: { background: "#5b8dd9", border: "none", color: "#fff", borderRadius: 6, padding: "8px 18px", fontSize: 12, fontWeight: 700, cursor: "pointer" }, children: "Create Campaign" })] })] })] }) }); } // ─── CAMPAIGN TABLE ROW ────────────────────────────────────────────────────── function CampaignRow({ c, onExpand }) { const s = SEV[c.signal.severity]; return /*#__PURE__*/_jsxs("tr", { style: { borderBottom: "1px solid #161616", cursor: "default" }, onMouseEnter: e => e.currentTarget.style.background = "#111", onMouseLeave: e => e.currentTarget.style.background = "transparent", children: [/*#__PURE__*/_jsx("td", { style: { width: 4, padding: 0 }, children: /*#__PURE__*/_jsx("div", { style: { width: 4, height: "100%", minHeight: 56, background: s.accent } }) }), /*#__PURE__*/_jsxs("td", { style: { padding: "11px 14px 11px 10px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#eee", fontSize: 13, fontWeight: 600, marginBottom: 2 }, children: c.name }), /*#__PURE__*/_jsx("div", { style: { color: "#555", fontSize: 11 }, children: c.advertiser })] }), /*#__PURE__*/_jsx("td", { style: { padding: "11px 10px", whiteSpace: "nowrap" }, children: /*#__PURE__*/_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 3 }, children: [/*#__PURE__*/_jsx(Chip, { label: c.signal.label, color: s.accent }), c.archetype && /*#__PURE__*/_jsxs("span", { style: { fontSize: 10, color: "#555" }, children: [c.archetype.icon, " ", c.archetype.label] })] }) }), /*#__PURE__*/_jsxs("td", { style: { padding: "11px 10px", minWidth: 150 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 4 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#888", fontSize: 11, fontFamily: "monospace" }, children: moneyK(c.spend_to_date) }), /*#__PURE__*/_jsxs("span", { style: { color: "#555", fontSize: 11 }, children: ["/ ", moneyK(c.budget)] }), /*#__PURE__*/_jsx("span", { style: { color: s.text, fontSize: 11, fontWeight: 700, fontFamily: "monospace" }, children: pct(c.spendPct) })] }), /*#__PURE__*/_jsx(Bar, { value: c.spendPct, color: s.accent, h: 5, bg: "#1a1a1a" }), /*#__PURE__*/_jsx(Bar, { value: c.flightPct, color: "#3a6aaa", h: 3, bg: "#141414" })] }), /*#__PURE__*/_jsxs("td", { style: { padding: "11px 10px", whiteSpace: "nowrap" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#888", fontSize: 11 }, children: c.start_date }), /*#__PURE__*/_jsxs("div", { style: { color: "#555", fontSize: 11 }, children: ["\u2192 ", c.end_date] })] }), /*#__PURE__*/_jsxs("td", { style: { padding: "11px 10px", fontFamily: "monospace", fontSize: 12, color: c.daysRemaining < 14 ? s.text : "#666", fontWeight: c.daysRemaining < 14 ? 700 : 400, whiteSpace: "nowrap" }, children: [c.daysRemaining, "d"] }), /*#__PURE__*/_jsx("td", { style: { padding: "11px 10px", fontFamily: "monospace", fontSize: 12, color: c.roas ? c.roas >= 3 ? "#33cc77" : "#d96800" : "#444", whiteSpace: "nowrap" }, children: c.roas ? `${c.roas.toFixed(1)}x` : "—" }), /*#__PURE__*/_jsx("td", { style: { padding: "11px 10px", fontFamily: "monospace", fontSize: 12, color: c.ctr ? c.ctr >= 0.005 ? "#33cc77" : "#d96800" : "#444", whiteSpace: "nowrap" }, children: c.ctr !== null ? `${(c.ctr * 100).toFixed(2)}%` : "—" }), /*#__PURE__*/_jsx("td", { style: { padding: "11px 10px" }, children: c.dataFlags.length > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#1a1400", border: "1px solid #c9a20040", borderRadius: 4, padding: "2px 6px", fontSize: 9, color: "#c9a200" }, children: ["\u26A0 ", c.dataFlags.length] }) }), /*#__PURE__*/_jsx("td", { style: { padding: "11px 10px" }, children: /*#__PURE__*/_jsx("button", { onClick: () => onExpand(c), style: { background: "#111", border: "1px solid #252525", color: "#888", borderRadius: 5, padding: "4px 10px", fontSize: 11, cursor: "pointer", whiteSpace: "nowrap" }, onMouseEnter: e => { e.currentTarget.style.borderColor = "#444"; e.currentTarget.style.color = "#ccc"; }, onMouseLeave: e => { e.currentTarget.style.borderColor = "#252525"; e.currentTarget.style.color = "#888"; }, children: "See more \u2197" }) })] }); } // ─── FILTER BAR (Campaigns tab) ────────────────────────────────────────────── function FilterBar({ filters, setFilters, counts }) { const [adv, setAdv] = useState(false); const dirty = filters.search || filters.severity !== "all" || filters.budgetMin || filters.budgetMax || filters.startAfter || filters.startBefore || filters.endAfter || filters.endBefore; return /*#__PURE__*/_jsxs("div", { style: { borderBottom: "1px solid #161616", background: "#0a0a0a", padding: "9px 18px", flexShrink: 0 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }, children: [/*#__PURE__*/_jsx("input", { value: filters.search, onChange: e => setFilters(f => ({ ...f, search: e.target.value })), placeholder: "Search campaigns\u2026", style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 6, padding: "6px 12px", color: "#ccc", fontSize: 12.5, outline: "none", width: 210 } }), /*#__PURE__*/_jsx("div", { style: { display: "flex", gap: 4 }, children: [["all", "All", "#888"], ["critical", "Critical", "#d93030"], ["high", "High", "#d96800"], ["medium", "Medium", "#c9a200"], ["low", "Healthy", "#00a855"]].map(([v, l, col]) => /*#__PURE__*/_jsxs("button", { onClick: () => setFilters(f => ({ ...f, severity: f.severity === v && v !== "all" ? "all" : v })), style: { background: filters.severity === v ? col + "22" : "transparent", border: `1px solid ${filters.severity === v ? col : "#1e1e1e"}`, color: filters.severity === v ? col : "#555", borderRadius: 5, padding: "5px 10px", fontSize: 11, cursor: "pointer", fontWeight: 600 }, children: [l, " ", /*#__PURE__*/_jsx("span", { style: { opacity: .55 }, children: counts[v] })] }, v)) }), /*#__PURE__*/_jsx("div", { style: { flex: 1 } }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#505050", fontSize: 11 }, children: "Sort:" }), /*#__PURE__*/_jsxs("select", { value: filters.sort, onChange: e => setFilters(f => ({ ...f, sort: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 8px", outline: "none", cursor: "pointer" }, children: [/*#__PURE__*/_jsx("option", { value: "severity", children: "Risk Level" }), /*#__PURE__*/_jsx("option", { value: "end_date_asc", children: "End Date \u2191 soonest" }), /*#__PURE__*/_jsx("option", { value: "end_date_desc", children: "End Date \u2193 latest" }), /*#__PURE__*/_jsx("option", { value: "start_date_asc", children: "Start Date \u2191" }), /*#__PURE__*/_jsx("option", { value: "start_date_desc", children: "Start Date \u2193" }), /*#__PURE__*/_jsx("option", { value: "budget_desc", children: "Budget \u2193" }), /*#__PURE__*/_jsx("option", { value: "budget_asc", children: "Budget \u2191" }), /*#__PURE__*/_jsx("option", { value: "pacing", children: "Pacing \u2191 worst first" }), /*#__PURE__*/_jsx("option", { value: "days_left", children: "Days Left" }), /*#__PURE__*/_jsx("option", { value: "roas_desc", children: "ROAS \u2193" })] })] }), /*#__PURE__*/_jsx("button", { onClick: () => setAdv(v => !v), style: { background: adv ? "#1a1a2a" : "transparent", border: `1px solid ${adv ? "#5555aa" : "#1e1e1e"}`, color: adv ? "#9999cc" : "#555", borderRadius: 5, padding: "5px 12px", fontSize: 11, cursor: "pointer" }, children: adv ? "▲ Filters" : "▼ More Filters" }), dirty && /*#__PURE__*/_jsx("button", { onClick: () => setFilters({ search: "", severity: "all", sort: "severity", budgetMin: "", budgetMax: "", startAfter: "", startBefore: "", endAfter: "", endBefore: "" }), style: { background: "#1a0808", border: "1px solid #d9303030", color: "#d05050", borderRadius: 5, padding: "5px 10px", fontSize: 11, cursor: "pointer" }, children: "Clear \u2715" })] }), adv && /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 18, alignItems: "flex-end", marginTop: 9, paddingTop: 9, borderTop: "1px solid #161616", flexWrap: "wrap" }, children: [/*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Budget Range" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 5, alignItems: "center" }, children: [/*#__PURE__*/_jsx("input", { placeholder: "Min $", value: filters.budgetMin, onChange: e => setFilters(f => ({ ...f, budgetMin: e.target.value })), style: { width: 74, background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#ccc", fontSize: 11, padding: "5px 8px", outline: "none" } }), /*#__PURE__*/_jsx("span", { style: { color: "#333", fontSize: 11 }, children: "\u2013" }), /*#__PURE__*/_jsx("input", { placeholder: "Max $", value: filters.budgetMax, onChange: e => setFilters(f => ({ ...f, budgetMax: e.target.value })), style: { width: 74, background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#ccc", fontSize: 11, padding: "5px 8px", outline: "none" } })] })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Start Date Range" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 5, alignItems: "center" }, children: [/*#__PURE__*/_jsx("input", { type: "date", value: filters.startAfter, onChange: e => setFilters(f => ({ ...f, startAfter: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 8px", outline: "none", colorScheme: "dark" } }), /*#__PURE__*/_jsx("span", { style: { color: "#333", fontSize: 11 }, children: "\u2013" }), /*#__PURE__*/_jsx("input", { type: "date", value: filters.startBefore, onChange: e => setFilters(f => ({ ...f, startBefore: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 8px", outline: "none", colorScheme: "dark" } })] })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "End Date Range" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 5, alignItems: "center" }, children: [/*#__PURE__*/_jsx("input", { type: "date", value: filters.endAfter, onChange: e => setFilters(f => ({ ...f, endAfter: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 8px", outline: "none", colorScheme: "dark" } }), /*#__PURE__*/_jsx("span", { style: { color: "#333", fontSize: 11 }, children: "\u2013" }), /*#__PURE__*/_jsx("input", { type: "date", value: filters.endBefore, onChange: e => setFilters(f => ({ ...f, endBefore: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 8px", outline: "none", colorScheme: "dark" } })] })] })] })] }); } // ─── DASHBOARD ─────────────────────────────────────────────────────────────── function Dashboard({ campaigns, onSelect, onFilterAndNavigate }) { // Refine view state const [refine, setRefine] = useState(false); const [rf, setRf] = useState({ search: "", severity: "all", budgetMin: "", budgetMax: "", startAfter: "", startBefore: "", endAfter: "", endBefore: "", sort: "severity" }); const totalBudget = campaigns.reduce((s, c) => s + c.budget, 0); const totalSpend = campaigns.reduce((s, c) => s + c.spend_to_date, 0); const bySev = { critical: campaigns.filter(c => c.signal.severity === "critical"), high: campaigns.filter(c => c.signal.severity === "high"), medium: campaigns.filter(c => c.signal.severity === "medium"), low: campaigns.filter(c => c.signal.severity === "low") }; const atRisk = bySev.critical.length + bySev.high.length; const budgetAtRisk = [...bySev.critical, ...bySev.high].reduce((s, c) => s + c.budget, 0); const avgPacing = totalSpend / totalBudget; const archetypeCounts = {}; campaigns.forEach(c => { if (c.archetype) archetypeCounts[c.archetype.label] = (archetypeCounts[c.archetype.label] || 0) + 1; }); // Actions by team — aggregate action log, count by handle, sort by overdue > pending > in_progress > done const statusOrder = { overdue: 0, pending: 1, in_progress: 2, done: 3 }; const teamActions = TEAM.map(tm => { const actions = ACTION_LOG.filter(a => a.teamHandle === tm.handle).map(a => ({ ...a, campaign: campaigns.find(c => c.id === a.campaignId) })); const overdue = actions.filter(a => a.status === "overdue").length; const pending = actions.filter(a => a.status === "pending").length; const inprog = actions.filter(a => a.status === "in_progress").length; const done = actions.filter(a => a.status === "done").length; const urgency = overdue * 100 + pending * 10 + inprog; return { ...tm, actions, overdue, pending, inprog, done, urgency }; }).filter(t => t.actions.length > 0).sort((a, b) => b.urgency - a.urgency); // Refine view filtered/sorted list const refined = useMemo(() => { let list = [...campaigns]; if (rf.severity !== "all") list = list.filter(c => c.signal.severity === rf.severity); if (rf.search) { const q = rf.search.toLowerCase(); list = list.filter(c => c.name.toLowerCase().includes(q) || c.advertiser.toLowerCase().includes(q)); } if (rf.budgetMin) list = list.filter(c => c.budget >= parseInt(rf.budgetMin)); if (rf.budgetMax) list = list.filter(c => c.budget <= parseInt(rf.budgetMax)); if (rf.startAfter) list = list.filter(c => c.start_date >= rf.startAfter); if (rf.startBefore) list = list.filter(c => c.start_date <= rf.startBefore); if (rf.endAfter) list = list.filter(c => c.end_date >= rf.endAfter); if (rf.endBefore) list = list.filter(c => c.end_date <= rf.endBefore); const sevOrder = { critical: 0, high: 1, medium: 2, low: 3 }; switch (rf.sort) { case "severity": list.sort((a, b) => sevOrder[a.signal.severity] - sevOrder[b.signal.severity]); break; case "budget_desc": list.sort((a, b) => b.budget - a.budget); break; case "budget_asc": list.sort((a, b) => a.budget - b.budget); break; case "end_date_asc": list.sort((a, b) => a.end_date.localeCompare(b.end_date)); break; case "end_date_desc": list.sort((a, b) => b.end_date.localeCompare(a.end_date)); break; case "start_date_asc": list.sort((a, b) => a.start_date.localeCompare(b.start_date)); break; case "pacing": list.sort((a, b) => a.pacingPct - b.pacingPct); break; case "days_left": list.sort((a, b) => a.daysRemaining - b.daysRemaining); break; } return list; }, [campaigns, rf]); const rfDirty = rf.search || rf.severity !== "all" || rf.budgetMin || rf.budgetMax || rf.startAfter || rf.startBefore || rf.endAfter || rf.endBefore; return /*#__PURE__*/_jsxs("div", { style: { flex: 1, overflowY: "auto", padding: "26px 32px" }, children: [/*#__PURE__*/_jsxs("div", { style: { marginBottom: 22 }, children: [/*#__PURE__*/_jsx("h1", { style: { color: "#f0f0f0", fontSize: 22, fontWeight: 800, letterSpacing: "-0.03em", margin: 0, marginBottom: 3 }, children: "Portfolio Overview" }), /*#__PURE__*/_jsxs("p", { style: { color: "#505050", fontSize: 13, margin: 0 }, children: ["As of June 12, 2025 \xB7 ", campaigns.length, " active campaigns"] })] }), /*#__PURE__*/_jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, marginBottom: 20 }, children: [{ label: "At Risk", val: atRisk, sub: `of ${campaigns.length} total`, color: "#e05050", bg: "#1c0404", border: "#d9303030" }, { label: "Budget Exposed", val: moneyK(budgetAtRisk), sub: "critical & high", color: "#ff9944", bg: "#1a0c00", border: "#d9680030" }, { label: "Portfolio Spend", val: moneyK(totalSpend), sub: `of ${moneyK(totalBudget)}`, color: "#e0e0e0", bg: "#0e0e0e", border: "#252525" }, { label: "Avg Pacing", val: pct(avgPacing), sub: avgPacing < 0.7 ? "⚠ Below 70%" : "On target", color: avgPacing < 0.7 ? "#ff9944" : "#33cc77", bg: avgPacing < 0.7 ? "#1a0c00" : "#001508", border: avgPacing < 0.7 ? "#d9680030" : "#00a85530" }].map((k, i) => /*#__PURE__*/_jsxs("div", { style: { background: k.bg, border: `1px solid ${k.border}`, borderRadius: 10, padding: "16px 18px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 6 }, children: k.label }), /*#__PURE__*/_jsx("div", { style: { color: k.color, fontSize: 26, fontWeight: 800, letterSpacing: "-0.04em", marginBottom: 3 }, children: k.val }), /*#__PURE__*/_jsx("div", { style: { color: "#404040", fontSize: 11 }, children: k.sub })] }, i)) }), /*#__PURE__*/_jsxs("div", { style: { display: "grid", gridTemplateColumns: "280px 1fr", gap: 12, marginBottom: 20 }, children: [/*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #1e1e1e", borderRadius: 10, padding: "16px 18px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 3 }, children: "Risk Distribution" }), /*#__PURE__*/_jsx("div", { style: { color: "#333", fontSize: 10, marginBottom: 12 }, children: "Click to filter \u2192" }), [{ sev: "critical", label: "Critical", count: bySev.critical.length, color: "#d93030" }, { sev: "high", label: "High Risk", count: bySev.high.length, color: "#d96800" }, { sev: "medium", label: "Medium", count: bySev.medium.length, color: "#c9a200" }, { sev: "low", label: "Healthy", count: bySev.low.length, color: "#00a855" }].map(row => /*#__PURE__*/_jsxs("div", { onClick: () => onFilterAndNavigate(row.sev), style: { marginBottom: 9, cursor: "pointer", padding: "6px 8px", borderRadius: 6, border: "1px solid transparent", transition: "all .12s" }, onMouseEnter: e => { e.currentTarget.style.background = row.color + "10"; e.currentTarget.style.borderColor = row.color + "30"; }, onMouseLeave: e => { e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 5 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [/*#__PURE__*/_jsx("span", { style: { width: 7, height: 7, borderRadius: "50%", background: row.color, display: "inline-block" } }), /*#__PURE__*/_jsx("span", { style: { color: "#ccc", fontSize: 12 }, children: row.label })] }), /*#__PURE__*/_jsx("span", { style: { color: row.color, fontSize: 12, fontWeight: 700 }, children: row.count })] }), /*#__PURE__*/_jsx(Bar, { value: row.count / campaigns.length, color: row.color, h: 6 })] }, row.sev))] }), /*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #1e1e1e", borderRadius: 10, padding: "16px 18px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 12 }, children: "Pacing Snapshot \xB7 click to open" }), /*#__PURE__*/_jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: campaigns.slice(0, 10).map(c => { const s = SEV[c.signal.severity]; return /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, cursor: "pointer" }, onClick: () => onSelect(c), children: [/*#__PURE__*/_jsx("span", { style: { width: 7, height: 7, borderRadius: "50%", background: s.accent, flexShrink: 0 } }), /*#__PURE__*/_jsx("div", { style: { color: "#666", fontSize: 11, width: 150, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flexShrink: 0 }, children: c.name }), /*#__PURE__*/_jsxs("div", { style: { flex: 1, position: "relative" }, children: [/*#__PURE__*/_jsx(Bar, { value: c.flightPct, color: "#3a6aaa", h: 8, bg: "#1a1a1a" }), /*#__PURE__*/_jsx("div", { style: { position: "absolute", top: 0, left: 0, width: `${c.spendPct * 100}%`, height: "100%", background: s.accent + "bb", borderRadius: 99 } })] }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 6, alignItems: "center", flexShrink: 0, width: 110 }, children: [/*#__PURE__*/_jsx("span", { style: { color: s.text, fontSize: 10, fontWeight: 700, fontFamily: "monospace" }, children: pct(c.spendPct) }), /*#__PURE__*/_jsxs("span", { style: { color: "#444", fontSize: 10, fontFamily: "monospace" }, children: [moneyK(c.spend_to_date), "/", moneyK(c.budget)] })] })] }, c.id); }) })] })] }), /*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #1e1e1e", borderRadius: 10, padding: "18px 20px", marginBottom: 20 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, marginBottom: 16 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#e0e0e0", fontSize: 14, fontWeight: 700 }, children: "Actions by Team" }), /*#__PURE__*/_jsx("span", { style: { color: "#505050", fontSize: 11 }, children: "sorted highest priority first" }), /*#__PURE__*/_jsxs("span", { style: { marginLeft: "auto", background: "#1a0808", border: "1px solid #d9303030", borderRadius: 4, padding: "2px 9px", fontSize: 10, color: "#d05050" }, children: [ACTION_LOG.filter(a => a.status === "overdue").length, " overdue"] })] }), /*#__PURE__*/_jsx("div", { style: { display: "flex", flexDirection: "column", gap: 0 }, children: teamActions.map((tm, ti) => /*#__PURE__*/_jsx("div", { style: { borderBottom: ti < teamActions.length - 1 ? "1px solid #161616" : "none", padding: "11px 0" }, children: /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: 12 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, width: 150, flexShrink: 0 }, children: [/*#__PURE__*/_jsx("span", { style: { width: 28, height: 28, borderRadius: "50%", background: tm.color, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 10, fontWeight: 800, color: "#fff", flexShrink: 0 }, children: tm.avatar }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsxs("div", { style: { color: "#ccc", fontSize: 12, fontWeight: 600 }, children: ["@", tm.handle] }), /*#__PURE__*/_jsx("div", { style: { color: "#555", fontSize: 10 }, children: tm.name })] })] }), /*#__PURE__*/_jsx("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 5 }, children: tm.actions.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]).map((act, ai) => { const ss = STATUS_STYLE[act.status]; const camp = act.campaign; const cs = camp ? SEV[camp.signal.severity] : null; return /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, background: "#111", borderRadius: 6, padding: "7px 10px", border: `1px solid #1e1e1e`, borderLeft: `2px solid ${ss.color}` }, children: [/*#__PURE__*/_jsx("span", { style: { background: ss.bg, border: `1px solid ${ss.border}`, borderRadius: 4, padding: "1px 7px", fontSize: 9, color: ss.color, fontWeight: 700, textTransform: "uppercase", whiteSpace: "nowrap", width: 80, textAlign: "center" }, children: ss.label }), /*#__PURE__*/_jsx("span", { style: { color: "#bbb", fontSize: 12, flex: 1 }, children: act.action }), camp && /*#__PURE__*/_jsx("span", { onClick: () => onSelect(camp), style: { color: "#5b8dd9", fontSize: 10, cursor: "pointer", whiteSpace: "nowrap", textDecoration: "underline", textDecorationStyle: "dotted" }, children: camp.name.split(" ").slice(0, 2).join(" ") }), /*#__PURE__*/_jsx("span", { style: { color: "#444", fontSize: 10, whiteSpace: "nowrap", fontFamily: "monospace" }, children: act.dueDate })] }, ai); }) }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 4, flexShrink: 0, flexWrap: "wrap", width: 120, justifyContent: "flex-end" }, children: [tm.overdue > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#1c0404", border: "1px solid #d9303035", borderRadius: 4, padding: "2px 7px", fontSize: 10, color: "#d93030", fontWeight: 700 }, children: [tm.overdue, " overdue"] }), tm.pending > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#1a0c00", border: "1px solid #d9680035", borderRadius: 4, padding: "2px 7px", fontSize: 10, color: "#d96800", fontWeight: 700 }, children: [tm.pending, " pending"] }), tm.inprog > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#141200", border: "1px solid #c9a20035", borderRadius: 4, padding: "2px 7px", fontSize: 10, color: "#c9a200", fontWeight: 700 }, children: [tm.inprog, " in progress"] }), tm.done > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#001508", border: "1px solid #00a85535", borderRadius: 4, padding: "2px 7px", fontSize: 10, color: "#00a855", fontWeight: 700 }, children: [tm.done, " done"] })] })] }) }, tm.handle)) })] }), /*#__PURE__*/_jsxs("div", { style: { background: "#0e0e0e", border: "1px solid #1e1e1e", borderRadius: 10, marginBottom: 20, overflow: "hidden" }, children: [/*#__PURE__*/_jsxs("div", { style: { padding: "14px 18px", borderBottom: refine ? "1px solid #1e1e1e" : "none", display: "flex", alignItems: "center", justifyContent: "space-between", cursor: "pointer" }, onClick: () => setRefine(v => !v), children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#e0e0e0", fontSize: 14, fontWeight: 700 }, children: "Refine View" }), /*#__PURE__*/_jsx("span", { style: { color: "#505050", fontSize: 11 }, children: "filter & sort all campaigns" }), rfDirty && /*#__PURE__*/_jsx("span", { style: { background: "#1a1a2a", border: "1px solid #5555aa35", borderRadius: 4, padding: "2px 8px", fontSize: 10, color: "#9999cc" }, children: "filters active" })] }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [rfDirty && /*#__PURE__*/_jsx("button", { onClick: e => { e.stopPropagation(); setRf({ search: "", severity: "all", budgetMin: "", budgetMax: "", startAfter: "", startBefore: "", endAfter: "", endBefore: "", sort: "severity" }); }, style: { background: "#1a0808", border: "1px solid #d9303030", color: "#d05050", borderRadius: 4, padding: "3px 9px", fontSize: 10, cursor: "pointer" }, children: "Clear \u2715" }), /*#__PURE__*/_jsx("span", { style: { color: "#505050", fontSize: 13 }, children: refine ? "▲" : "▼" })] })] }), refine && /*#__PURE__*/_jsxs("div", { style: { padding: "16px 18px" }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 10, flexWrap: "wrap", marginBottom: 12, alignItems: "flex-end" }, children: [/*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Search" }), /*#__PURE__*/_jsx("input", { value: rf.search, onChange: e => setRf(f => ({ ...f, search: e.target.value })), placeholder: "Campaign or advertiser\u2026", style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, padding: "6px 10px", color: "#ccc", fontSize: 12, outline: "none", width: 180 } })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Risk Level" }), /*#__PURE__*/_jsx("div", { style: { display: "flex", gap: 4 }, children: [["all", "All", "#888"], ["critical", "●", "#d93030"], ["high", "●", "#d96800"], ["medium", "●", "#c9a200"], ["low", "●", "#00a855"]].map(([v, l, col]) => /*#__PURE__*/_jsx("button", { onClick: () => setRf(f => ({ ...f, severity: f.severity === v && v !== "all" ? "all" : v })), style: { background: rf.severity === v ? col + "22" : "transparent", border: `1px solid ${rf.severity === v ? col : "#1e1e1e"}`, color: rf.severity === v ? col : "#555", borderRadius: 5, padding: "5px 9px", fontSize: 11, cursor: "pointer", fontWeight: 600 }, children: v === "all" ? l : /*#__PURE__*/_jsxs("span", { style: { color: col }, children: ["\u25CF ", v] }) }, v)) })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Budget" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 4, alignItems: "center" }, children: [/*#__PURE__*/_jsx("input", { placeholder: "Min $", value: rf.budgetMin, onChange: e => setRf(f => ({ ...f, budgetMin: e.target.value })), style: { width: 70, background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#ccc", fontSize: 11, padding: "5px 7px", outline: "none" } }), /*#__PURE__*/_jsx("span", { style: { color: "#333" }, children: "\u2013" }), /*#__PURE__*/_jsx("input", { placeholder: "Max $", value: rf.budgetMax, onChange: e => setRf(f => ({ ...f, budgetMax: e.target.value })), style: { width: 70, background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#ccc", fontSize: 11, padding: "5px 7px", outline: "none" } })] })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Start Date" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 4, alignItems: "center" }, children: [/*#__PURE__*/_jsx("input", { type: "date", value: rf.startAfter, onChange: e => setRf(f => ({ ...f, startAfter: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 7px", outline: "none", colorScheme: "dark" } }), /*#__PURE__*/_jsx("span", { style: { color: "#333" }, children: "\u2013" }), /*#__PURE__*/_jsx("input", { type: "date", value: rf.startBefore, onChange: e => setRf(f => ({ ...f, startBefore: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 7px", outline: "none", colorScheme: "dark" } })] })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "End Date" }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", gap: 4, alignItems: "center" }, children: [/*#__PURE__*/_jsx("input", { type: "date", value: rf.endAfter, onChange: e => setRf(f => ({ ...f, endAfter: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 7px", outline: "none", colorScheme: "dark" } }), /*#__PURE__*/_jsx("span", { style: { color: "#333" }, children: "\u2013" }), /*#__PURE__*/_jsx("input", { type: "date", value: rf.endBefore, onChange: e => setRf(f => ({ ...f, endBefore: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 7px", outline: "none", colorScheme: "dark" } })] })] }), /*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 5 }, children: "Sort By" }), /*#__PURE__*/_jsxs("select", { value: rf.sort, onChange: e => setRf(f => ({ ...f, sort: e.target.value })), style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 5, color: "#aaa", fontSize: 11, padding: "5px 8px", outline: "none", cursor: "pointer" }, children: [/*#__PURE__*/_jsx("option", { value: "severity", children: "Risk Level" }), /*#__PURE__*/_jsx("option", { value: "end_date_asc", children: "End Date \u2191" }), /*#__PURE__*/_jsx("option", { value: "end_date_desc", children: "End Date \u2193" }), /*#__PURE__*/_jsx("option", { value: "start_date_asc", children: "Start Date \u2191" }), /*#__PURE__*/_jsx("option", { value: "budget_desc", children: "Budget \u2193" }), /*#__PURE__*/_jsx("option", { value: "budget_asc", children: "Budget \u2191" }), /*#__PURE__*/_jsx("option", { value: "pacing", children: "Pacing worst first" }), /*#__PURE__*/_jsx("option", { value: "days_left", children: "Days Left" })] })] })] }), /*#__PURE__*/_jsxs("div", { style: { color: "#505050", fontSize: 10, textTransform: "uppercase", marginBottom: 8 }, children: [refined.length, " campaign", refined.length !== 1 ? "s" : "", " shown"] }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 5, maxHeight: 380, overflowY: "auto" }, children: [refined.map(c => { const s = SEV[c.signal.severity]; return /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, background: "#111", border: `1px solid #1e1e1e`, borderLeft: `3px solid ${s.accent}`, borderRadius: 7, padding: "9px 12px", cursor: "pointer" }, onClick: () => onSelect(c), children: [/*#__PURE__*/_jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#e0e0e0", fontSize: 12.5, fontWeight: 600, marginBottom: 1, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: c.name }), /*#__PURE__*/_jsx("div", { style: { color: "#555", fontSize: 11 }, children: c.advertiser })] }), /*#__PURE__*/_jsx(Chip, { label: c.signal.label, color: s.accent }), /*#__PURE__*/_jsxs("div", { style: { width: 120, flexShrink: 0 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 3 }, children: [/*#__PURE__*/_jsxs("span", { style: { color: "#666", fontSize: 10 }, children: [moneyK(c.spend_to_date), "/", moneyK(c.budget)] }), /*#__PURE__*/_jsx("span", { style: { color: s.text, fontSize: 10, fontWeight: 700 }, children: pct(c.spendPct) })] }), /*#__PURE__*/_jsx(Bar, { value: c.spendPct, color: s.accent, h: 4 })] }), /*#__PURE__*/_jsxs("div", { style: { color: "#555", fontSize: 11, whiteSpace: "nowrap", width: 110, flexShrink: 0, textAlign: "right" }, children: [c.start_date, " \u2192 ", c.end_date] }), /*#__PURE__*/_jsxs("div", { style: { color: c.daysRemaining < 14 ? s.text : "#555", fontSize: 11, fontFamily: "monospace", width: 32, textAlign: "right", flexShrink: 0 }, children: [c.daysRemaining, "d"] }), /*#__PURE__*/_jsx("span", { style: { color: "#5b8dd9", fontSize: 10, textDecoration: "underline dotted", flexShrink: 0 }, children: "open \u2197" })] }, c.id); }), refined.length === 0 && /*#__PURE__*/_jsx("div", { style: { color: "#333", fontSize: 12, textAlign: "center", padding: "20px 0" }, children: "No campaigns match these filters" })] })] })] }), atRisk > 0 && /*#__PURE__*/_jsxs("div", { style: { marginBottom: 20 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 12 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#606060", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.1em" }, children: "Needs Immediate Attention" }), /*#__PURE__*/_jsx(Chip, { label: `${atRisk} campaigns`, color: "#e05050", bg: "#1c0404" })] }), /*#__PURE__*/_jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 10 }, children: [...bySev.critical, ...bySev.high].map(c => { const s = SEV[c.signal.severity]; return /*#__PURE__*/_jsxs("div", { onClick: () => onSelect(c), style: { background: s.bg, border: `1px solid ${s.border}`, borderRadius: 10, padding: "13px 16px", cursor: "pointer" }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 8 }, children: [/*#__PURE__*/_jsxs("div", { children: [/*#__PURE__*/_jsx("div", { style: { color: "#eee", fontSize: 12.5, fontWeight: 600, marginBottom: 2 }, children: c.name }), /*#__PURE__*/_jsx("div", { style: { color: "#505050", fontSize: 11 }, children: c.advertiser })] }), /*#__PURE__*/_jsx(Chip, { label: s.label, color: s.accent })] }), /*#__PURE__*/_jsx("div", { style: { borderLeft: `2px solid ${s.accent}`, paddingLeft: 8, marginBottom: 7 }, children: /*#__PURE__*/_jsx("div", { style: { color: "#999", fontSize: 11.5, lineHeight: 1.6 }, children: c.signal.reason(c) }) }), /*#__PURE__*/_jsxs("div", { style: { background: "#001a0a", border: "1px solid #00a85530", borderRadius: 6, padding: "7px 10px", display: "flex", gap: 6 }, children: [/*#__PURE__*/_jsx("span", { style: { color: "#00a855", flexShrink: 0 }, children: "\u2192" }), /*#__PURE__*/_jsx("div", { style: { color: "#d4ffd4", fontSize: 11.5, lineHeight: 1.55, fontWeight: 500 }, children: c.signal.action })] })] }, c.id); }) })] }), Object.keys(archetypeCounts).length > 0 && /*#__PURE__*/_jsxs("div", { style: { background: "#0a0a14", border: "1px solid #22224a", borderRadius: 10, padding: "14px 18px" }, children: [/*#__PURE__*/_jsx("div", { style: { color: "#6060aa", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 10 }, children: "Detected Campaign Patterns" }), /*#__PURE__*/_jsx("div", { style: { display: "flex", gap: 10, flexWrap: "wrap" }, children: Object.entries(archetypeCounts).map(([label, count]) => { const arch = ARCHETYPES.find(a => a.label === label); return /*#__PURE__*/_jsxs("div", { style: { background: "#12121e", border: "1px solid #2a2a55", borderRadius: 8, padding: "10px 14px", minWidth: 140 }, children: [/*#__PURE__*/_jsx("div", { style: { fontSize: 20, marginBottom: 5 }, children: arch === null || arch === void 0 ? void 0 : arch.icon }), /*#__PURE__*/_jsx("div", { style: { color: "#aaaee", fontSize: 12, fontWeight: 600, marginBottom: 2 }, children: label }), /*#__PURE__*/_jsxs("div", { style: { color: "#6066aa", fontSize: 11 }, children: [count, " campaign", count !== 1 ? "s" : ""] })] }, label); }) })] })] }); } // ─── EXPORT CSV ────────────────────────────────────────────────────────────── function exportCSV(campaigns) { const headers = ["ID", "Name", "Advertiser", "Budget", "Spend to Date", "Spend %", "Start Date", "End Date", "Days Remaining", "CTR", "ROAS", "Pacing Ratio", "Risk Level", "Risk Label", "Archetype", "Notes", "Impressions", "Clicks", "Attributed Sales", "Attributed Units", "CPC", "NTB Sales", "NTB %", "Conversions"]; const rows = campaigns.map(c => { var _c$metrics$impression, _c$metrics$clicks, _c$metrics$attributed, _c$metrics$attributed2, _c$metrics$cpc, _c$metrics$ntb_sales, _c$metrics$ntb_pct, _c$metrics$conversion; return [c.id, `"${c.name}"`, `"${c.advertiser}"`, c.budget, c.spend_to_date, Math.round(c.spendPct * 100) + "%", c.start_date, c.end_date, c.daysRemaining, c.ctr != null ? c.ctr : "", c.roas != null ? c.roas.toFixed(2) : "", c.pacingPct != null ? c.pacingPct.toFixed(2) : "", c.signal.severity, `"${c.signal.label}"`, c.archetype ? `"${c.archetype.label}"` : "", `"${c.notes || ""}"`, (_c$metrics$impression = c.metrics.impressions) !== null && _c$metrics$impression !== void 0 ? _c$metrics$impression : "", (_c$metrics$clicks = c.metrics.clicks) !== null && _c$metrics$clicks !== void 0 ? _c$metrics$clicks : "", (_c$metrics$attributed = c.metrics.attributed_sales) !== null && _c$metrics$attributed !== void 0 ? _c$metrics$attributed : "", (_c$metrics$attributed2 = c.metrics.attributed_units) !== null && _c$metrics$attributed2 !== void 0 ? _c$metrics$attributed2 : "", (_c$metrics$cpc = c.metrics.cpc) !== null && _c$metrics$cpc !== void 0 ? _c$metrics$cpc : "", (_c$metrics$ntb_sales = c.metrics.ntb_sales) !== null && _c$metrics$ntb_sales !== void 0 ? _c$metrics$ntb_sales : "", (_c$metrics$ntb_pct = c.metrics.ntb_pct) !== null && _c$metrics$ntb_pct !== void 0 ? _c$metrics$ntb_pct : "", (_c$metrics$conversion = c.metrics.conversions) !== null && _c$metrics$conversion !== void 0 ? _c$metrics$conversion : ""]; }); const csv = [headers, ...rows].map(r => r.join(",")).join("\n"); const blob = new Blob([csv], { type: "text/csv" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "hts-campaigns.csv"; a.click(); URL.revokeObjectURL(url); } // ─── APP ───────────────────────────────────────────────────────────────────── const DEFAULT_FILTERS = { search: "", severity: "all", sort: "severity", budgetMin: "", budgetMax: "", startAfter: "", startBefore: "", endAfter: "", endBefore: "" }; export default function App() { const [view, setView] = useState("dashboard"); const [modal, setModal] = useState(null); const [showNew, setShowNew] = useState(false); const [filters, setFilters] = useState(DEFAULT_FILTERS); const [campaigns, setCampaigns] = useState(() => SEED_CAMPAIGNS.map(evaluateOne)); const counts = useMemo(() => ({ all: campaigns.length, critical: campaigns.filter(c => c.signal.severity === "critical").length, high: campaigns.filter(c => c.signal.severity === "high").length, medium: campaigns.filter(c => c.signal.severity === "medium").length, low: campaigns.filter(c => c.signal.severity === "low").length }), [campaigns]); const filtered = useMemo(() => { let list = [...campaigns]; if (filters.severity !== "all") list = list.filter(c => c.signal.severity === filters.severity); if (filters.search) { const q = filters.search.toLowerCase(); list = list.filter(c => c.name.toLowerCase().includes(q) || c.advertiser.toLowerCase().includes(q)); } if (filters.budgetMin) list = list.filter(c => c.budget >= parseInt(filters.budgetMin)); if (filters.budgetMax) list = list.filter(c => c.budget <= parseInt(filters.budgetMax)); if (filters.startAfter) list = list.filter(c => c.start_date >= filters.startAfter); if (filters.startBefore) list = list.filter(c => c.start_date <= filters.startBefore); if (filters.endAfter) list = list.filter(c => c.end_date >= filters.endAfter); if (filters.endBefore) list = list.filter(c => c.end_date <= filters.endBefore); const sevOrder = { critical: 0, high: 1, medium: 2, low: 3 }; switch (filters.sort) { case "severity": list.sort((a, b) => sevOrder[a.signal.severity] - sevOrder[b.signal.severity]); break; case "budget_desc": list.sort((a, b) => b.budget - a.budget); break; case "budget_asc": list.sort((a, b) => a.budget - b.budget); break; case "end_date_asc": list.sort((a, b) => a.end_date.localeCompare(b.end_date)); break; case "end_date_desc": list.sort((a, b) => b.end_date.localeCompare(a.end_date)); break; case "start_date_asc": list.sort((a, b) => a.start_date.localeCompare(b.start_date)); break; case "start_date_desc": list.sort((a, b) => b.start_date.localeCompare(a.start_date)); break; case "pacing": list.sort((a, b) => a.pacingPct - b.pacingPct); break; case "days_left": list.sort((a, b) => a.daysRemaining - b.daysRemaining); break; case "roas_desc": list.sort((a, b) => (b.roas || 0) - (a.roas || 0)); break; } return list; }, [campaigns, filters]); const handleSelectFromDashboard = c => { setModal(c); }; const handleFilterAndNavigate = sev => { setFilters(f => ({ ...f, severity: sev })); setView("campaigns"); }; const handleCreate = c => { setCampaigns(prev => [c, ...prev]); }; return /*#__PURE__*/_jsxs("div", { style: { fontFamily: "'Inter',system-ui,sans-serif", background: "#0b0b0b", height: "100vh", color: "#fff", display: "flex", flexDirection: "column", overflow: "hidden" }, children: [/*#__PURE__*/_jsx("link", { href: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap", rel: "stylesheet" }), /*#__PURE__*/_jsx("style", { children: `*{box-sizing:border-box;}::-webkit-scrollbar{width:5px;height:5px;}::-webkit-scrollbar-track{background:#0b0b0b;}::-webkit-scrollbar-thumb{background:#2a2a2a;border-radius:3px;}::-webkit-scrollbar-thumb:hover{background:#3a3a3a;}select option{background:#111;}textarea,input{font-family:'Inter',system-ui,sans-serif;}` }), /*#__PURE__*/_jsxs("nav", { style: { borderBottom: "1px solid #161616", padding: "0 22px", display: "flex", alignItems: "center", justifyContent: "space-between", background: "#0a0a0a", height: 48, flexShrink: 0 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 14 }, children: [/*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [/*#__PURE__*/_jsx("div", { style: { width: 24, height: 24, background: "linear-gradient(135deg,#d93030,#d96800)", borderRadius: 5, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 10, fontWeight: 800 }, children: "H" }), /*#__PURE__*/_jsx("span", { style: { fontWeight: 700, fontSize: 13.5, letterSpacing: "-0.02em", color: "#e8e8e8" }, children: "HTS Media" })] }), /*#__PURE__*/_jsx("span", { style: { color: "#222" }, children: "|" }), [["dashboard", "Overview"], ["campaigns", "Campaigns"]].map(([v, label]) => /*#__PURE__*/_jsxs("button", { onClick: () => setView(v), style: { background: "none", border: "none", cursor: "pointer", color: view === v ? "#fff" : "#505050", fontSize: 13, fontWeight: view === v ? 600 : 400, padding: "0 4px", borderBottom: view === v ? "2px solid #fff" : "2px solid transparent", height: 48, transition: "color .12s" }, children: [label, v === "campaigns" && /*#__PURE__*/_jsx("span", { style: { color: "#404040", fontSize: 10, marginLeft: 5 }, children: campaigns.length })] }, v))] }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [counts.critical > 0 && /*#__PURE__*/_jsxs("span", { style: { background: "#d9303018", border: "1px solid #d9303030", borderRadius: 4, padding: "3px 9px", fontSize: 11, color: "#e07070" }, children: ["\u26A0 ", counts.critical, " critical"] }), /*#__PURE__*/_jsx("span", { style: { color: "#3a3a3a", fontSize: 11 }, children: "Jun 12, 2025" }), /*#__PURE__*/_jsx("span", { style: { background: "#111", border: "1px solid #1e1e1e", borderRadius: 4, padding: "3px 9px", fontSize: 11, color: "#444" }, children: "Internal \xB7 v0.1" })] })] }), /*#__PURE__*/_jsx("div", { style: { display: "flex", flex: 1, overflow: "hidden" }, children: view === "dashboard" ? /*#__PURE__*/_jsx(Dashboard, { campaigns: campaigns, onSelect: handleSelectFromDashboard, onFilterAndNavigate: handleFilterAndNavigate }) : /*#__PURE__*/_jsxs("div", { style: { display: "flex", flexDirection: "column", flex: 1, overflow: "hidden" }, children: [/*#__PURE__*/_jsx(FilterBar, { filters: filters, setFilters: setFilters, counts: counts }), /*#__PURE__*/_jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 8, padding: "8px 18px", borderBottom: "1px solid #161616", background: "#0a0a0a", flexShrink: 0 }, children: [/*#__PURE__*/_jsxs("button", { onClick: () => exportCSV(filtered), style: { display: "flex", alignItems: "center", gap: 5, background: "#0e1a0e", border: "1px solid #00a85540", color: "#00a855", borderRadius: 6, padding: "6px 14px", fontSize: 12, fontWeight: 600, cursor: "pointer" }, onMouseEnter: e => { e.currentTarget.style.background = "#162a16"; }, onMouseLeave: e => { e.currentTarget.style.background = "#0e1a0e"; }, children: ["\u2193 Export CSV ", /*#__PURE__*/_jsxs("span", { style: { color: "#2a5a3a", fontSize: 10 }, children: ["(", filtered.length, " rows)"] })] }), /*#__PURE__*/_jsx("button", { onClick: () => setShowNew(true), style: { display: "flex", alignItems: "center", gap: 5, background: "#5b8dd9", border: "none", color: "#fff", borderRadius: 6, padding: "6px 14px", fontSize: 12, fontWeight: 700, cursor: "pointer" }, onMouseEnter: e => e.currentTarget.style.background = "#4a7ac8", onMouseLeave: e => e.currentTarget.style.background = "#5b8dd9", children: "+ New Campaign" })] }), /*#__PURE__*/_jsx("div", { style: { flex: 1, overflowY: "auto" }, children: /*#__PURE__*/_jsxs("table", { style: { width: "100%", borderCollapse: "collapse", tableLayout: "fixed" }, children: [/*#__PURE__*/_jsxs("colgroup", { children: [/*#__PURE__*/_jsx("col", { style: { width: 4 } }), /*#__PURE__*/_jsx("col", { style: { width: "20%" } }), /*#__PURE__*/_jsx("col", { style: { width: "13%" } }), /*#__PURE__*/_jsx("col", { style: { width: "16%" } }), /*#__PURE__*/_jsx("col", { style: { width: "13%" } }), /*#__PURE__*/_jsx("col", { style: { width: "6%" } }), /*#__PURE__*/_jsx("col", { style: { width: "7%" } }), /*#__PURE__*/_jsx("col", { style: { width: "7%" } }), /*#__PURE__*/_jsx("col", { style: { width: "5%" } }), /*#__PURE__*/_jsx("col", { style: { width: "8%" } })] }), /*#__PURE__*/_jsx("thead", { children: /*#__PURE__*/_jsxs("tr", { style: { borderBottom: "2px solid #1e1e1e", background: "#0a0a0a", position: "sticky", top: 0, zIndex: 10 }, children: [/*#__PURE__*/_jsx("th", { style: { width: 4, padding: 0 } }), [["Campaign", "left"], ["Risk", "left"], ["Budget & Spend", "left"], ["Dates", "left"], ["Left", "left"], ["ROAS", "left"], ["CTR", "left"], ["Flags", "left"], ["", "left"]].map(([h, a]) => /*#__PURE__*/_jsx("th", { style: { padding: "9px 10px", color: "#505050", fontSize: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.08em", textAlign: a }, children: h }, h))] }) }), /*#__PURE__*/_jsx("tbody", { children: filtered.length === 0 ? /*#__PURE__*/_jsx("tr", { children: /*#__PURE__*/_jsx("td", { colSpan: 10, style: { textAlign: "center", padding: 40, color: "#333", fontSize: 13 }, children: "No campaigns match current filters" }) }) : filtered.map(c => /*#__PURE__*/_jsx(CampaignRow, { c: c, onExpand: setModal }, c.id)) })] }) }), /*#__PURE__*/_jsxs("div", { style: { height: 30, borderTop: "1px solid #161616", background: "#0a0a0a", display: "flex", alignItems: "center", padding: "0 18px", gap: 14, flexShrink: 0 }, children: [/*#__PURE__*/_jsxs("span", { style: { color: "#404040", fontSize: 11 }, children: [filtered.length, " of ", campaigns.length, " campaigns"] }), /*#__PURE__*/_jsx("div", { style: { flex: 1 } }), ["critical", "high", "medium", "low"].map(sev => { const s = SEV[sev]; const n = campaigns.filter(c => c.signal.severity === sev).length; return /*#__PURE__*/_jsxs("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [/*#__PURE__*/_jsx("span", { style: { width: 6, height: 6, borderRadius: "50%", background: s.dot } }), /*#__PURE__*/_jsxs("span", { style: { color: "#404040", fontSize: 11 }, children: [n, " ", sev] })] }, sev); })] })] }) }), modal && /*#__PURE__*/_jsx(CampaignModal, { c: modal, onClose: () => setModal(null) }), showNew && /*#__PURE__*/_jsx(NewCampaignModal, { onClose: () => setShowNew(false), onCreate: handleCreate })] }); }