/* Platform sub-tab view ============================================= Campaigns → Ad Sets → Ads level switch · Meta-style column packs (editable) · per-platform signature breakdown panel. Bound entirely to the global Account + Date Range + Platform context. =================================================================== */ /* ---------- Metric cell --------------------------------------------- */ function fmtMetric(val, kind){ if (val == null || Number.isNaN(val)) return '—'; if (kind==='freq') return val.toFixed(2) + 'x'; if (kind==='roasci')return val.toFixed(2) + '×'; return fmt(val, kind); } function MetricCell({ id, m, platform }){ const def = METRIC_BY_ID[id]; const val = m[id]; if (id==='roas'){ return ; } const tone = def.tone; const spark = null; /* synthetic sparklines removed — real values only */ // color cues let cls = 'tabular font-mono'; if (id==='cpa' || id==='cpc' || id==='cpm') cls += ''; if (id==='frequency' && val>4) cls += ' text-rose-600 dark:text-rose-400 font-semibold'; if (id==='hook_rate' && val>30) cls += ' text-emerald-600 dark:text-emerald-400'; return (
{fmtMetric(val, def.fmt)} {spark && }
); } /* ---------- Column-pack bar + customize ----------------------------- */ function ColumnControls({ pack, setPack, cols, setCols, canEdit }){ const [openCustom, setOpenCustom] = useState(false); return (
{PACK_ORDER.map(pk=>( ))}
setOpenCustom(o=>!o)}> Customize{cols.length?` · ${cols.length}`:''} {openCustom && ( <>
setOpenCustom(false)}/>
Choose columns
{METRIC_GROUPS.map(g=>(
{g.label}
{METRIC_CATALOG.filter(mm=>mm.group===g.id).map(mm=>{ const on = cols.includes(mm.id); return ( ); })}
))}
)}
); } /* ---------- The metric table ---------------------------------------- */ function levelMeta(level){ return ({ campaign: { label:'Campaigns', icon:'columns', toggleLabel:'campaign' }, adset: { label:'Ad Sets', icon:'filter', toggleLabel:'ad set' }, ad: { label:'Ads', icon:'sparkles',toggleLabel:'ad' }, })[level]; } function MetricTable({ rows, cols, platform, level, canEdit, statusMap, onToggleStatus, search }){ const [sort, setSort] = useState({ id:'spend', dir:'desc' }); const enriched = useMemo(()=> rows.map(rw=>{ const ov = statusMap[rw.id]; const base = ov ? { ...rw, status:ov } : rw; const m = fullMetrics(base, platform); m._sparkSeed = rw.id; return { row:base, m }; }), [rows, statusMap, platform]); const filtered = useMemo(()=>{ const q = (search||'').trim().toLowerCase(); let list = enriched; if (q) list = list.filter(x => x.row.name.toLowerCase().includes(q) || (x.row._parent||'').toLowerCase().includes(q)); const dir = sort.dir==='asc'?1:-1; return [...list].sort((a,b)=>{ const av = sort.id==='name'? a.row.name : a.m[sort.id]; const bv = sort.id==='name'? b.row.name : b.m[sort.id]; if (typeof av==='string') return av.localeCompare(bv)*dir; return ((av||0)-(bv||0))*dir; }); }, [enriched, sort, search]); const nameW = 'minmax(260px,1.8fr)'; const template = `${nameW} 116px ${cols.map(c=>METRIC_BY_ID[c].w+'px').join(' ')}`; const minW = 260 + 116 + cols.reduce((s,c)=>s+METRIC_BY_ID[c].w,0) + (cols.length+2)*12 + 32; const SortH = ({ id, label, align }) => { const active = sort.id===id; return ( ); }; return (
{/* header */}
Status
{cols.map(c=>(
))}
{/* body */}
{filtered.length===0 &&
No {levelMeta(level).label.toLowerCase()} match.
} {filtered.map(({row,m})=>{ const paused = row.status==='paused'; const tone = (PLATFORMS.find(p=>p.id===row.platform)||PLATFORMS[0]).tone; return (
{level==='ad' ? {row.format==='video'?'▶':row.format==='carousel'?'▦':'▣'} : (!paused ? : )}
{row.name}
{row._parent &&
{row._grandparent?row._grandparent+' · ':''}{row._parent}
}
onToggleStatus(row.id, row.status)} size="sm"/> {paused?'Off':'On'}
{cols.map(c=> )}
); })}
); } /* ---------- Per-platform signature panel ---------------------------- */ /* NOTE: the old SignaturePanel/BreakdownBars (fabricated placement, audience, quality-score and retention panels) were removed — the dashboard shows only real, ingested data. Rebuild them when placement/demographic breakdowns are actually synced from the platform APIs. */ /* ---------- The full platform view ---------------------------------- */ function PlatformView({ platform, accountId, search, canEdit }){ /* per-account metric blocklist (e.g. Al Munawarah: no ROAS anywhere) */ const colFilter = (arr)=> arr.filter(id=>!metricHiddenFor(accountId, id)); const [level, setLevel] = useState('campaign'); const [pack, setPack] = useState('performance'); const [cols, setColsRaw] = useState(colFilter(COLUMN_PACKS.performance.cols.slice())); const setCols = (c)=> setColsRaw(colFilter(typeof c==='function' ? c(cols) : c)); const [statusMap, setStatusMap] = useState({}); useEffect(()=>{ setStatusMap({}); setColsRaw(colFilter(COLUMN_PACKS[pack] ? COLUMN_PACKS[pack].cols.slice() : cols)); }, [accountId, platform]); const campaigns = useMemo(()=>getCampaigns(accountId, platform), [accountId, platform]); const rows = useMemo(()=>rowsForLevel(campaigns, level), [campaigns, level]); const onToggleStatus = (id, cur)=>{ if(!canEdit) return; setStatusMap(s=>({...s,[id]: (s[id]||cur)==='active'?'paused':'active'})); }; const plat = PLATFORMS.find(p=>p.id===platform)||PLATFORMS[0]; const totalSpend = rows.reduce((s,r)=>s+(r.spend||0),0); return (
{/* platform header */}

{plat.label}

{campaigns.length} campaigns · {fmt(totalSpend,'currency')} spend (period)
{/* KPI strip bound to context */} {}}/> {/* table card */}
{['campaign','adset','ad'].map(lv=>( ))}
{/* creative preview for this platform */}
Creatives · {plat.label}
); } Object.assign(window, { PlatformView, MetricTable, ColumnControls, fmtMetric });