{c.thumb
?

:
}
{/* placeholder marker (subtle) */}
creative · {c.format}
{/* Top row: format chip + status */}
{c.format==='video' && }
{c.format==='carousel' && }
{c.format==='story' && }
{c.format==='image' && }
{c.format}
{/* Headline (ad copy) */}
{/* CTA + brand */}
{c.cta} →
sponsored
{/* Dim overlay if paused/rejected */}
{isDimmed &&
}
);
}
/* ---------- Filter pill with active count ------------------------- */
function FilterPill({ label, count, onClick, active, icon }){
return (
{options.map(opt => {
const checked = selected.includes(opt.id);
return (
);
})}
);
}
/* ---------- Creative card ----------------------------------------- */
function CreativeCard({ c, selectable, selected, onToggleSelect }){
const status = CREATIVE_STATUSES.find(s=>s.id===c.status) || { label:c.status, tone:'neutral' };
return (
{/* Select checkbox */}
{selectable && (
)}
selectable && onToggleSelect()}>
{c.name}
{c.status==='active' && }
{status.label}
{(CREATIVE_OBJECTIVES.find(o=>o.id===c.objective)||{label:c.objective}).label}
·
{c.updated}
Spend
{curPrefix()}{(c.spend/1000).toFixed(1)}k
{!(typeof metricHiddenHere==='function' && metricHiddenHere('roas')) && (
ROAS
=2.5?'text-emerald-600 dark:text-emerald-400':c.roas<1.5?'text-rose-600 dark:text-rose-400':''}`}>{c.roas}×
)}
{(c.imp/1000).toFixed(0)}k imp · {c.conv} conv
);
}
/* ---------- Creative row (list view) ------------------------------ */
function CreativeRow({ c }){
const status = CREATIVE_STATUSES.find(s=>s.id===c.status) || { label:c.status, tone:'neutral' };
return (
{c.headline}
{c.name} · {c.format}
{(CREATIVE_OBJECTIVES.find(o=>o.id===c.objective)||{label:c.objective}).label}
{fmt(c.spend,'currency')}
{c.ctr}%
{!(typeof metricHiddenHere==='function' && metricHiddenHere('roas')) &&
{c.roas}×
}
{(c.imp/1000).toFixed(0)}k
);
}
/* ---------- Filter dropdown popover ------------------------------ */
function FilterDropdown({ label, options, selected, onChange, icon }){
const [open, setOpen] = useState(false);
const ref = useRef(null);
useOutsideClick(ref, ()=>setOpen(false));
const toggle = (id) => {
onChange(selected.includes(id) ? selected.filter(x=>x!==id) : [...selected, id]);
};
return (
{/* Header bar */}
Creative preview
Every running ad across platforms — {filtered.length} of {all.length} matching
{/* Filter row */}
p.id!=='overview').map(p=>({id:p.id, label:p.label}))} selected={platforms} onChange={setPlatforms}/>
Sort: {CREATIVE_SORTS.find(s=>s.id===sort).label.split(' — ')[0]}
}>
{(close)=>(
{creativeSorts().map(s => (
))}
)}
{(platforms.length||objectives.length||statuses.length||formats.length||search) ? (
) : (
No filters applied
)}
{/* Body */}
{filtered.length === 0 ? (
{all.length === 0 ? (<>
No creatives yet
Connect a data source or import data in Admin → Integrations.
>) : (<>
No creatives match your filters
Try clearing one of the filters above.
>)}
) : view === 'grid' ? (
{filtered.map(c => (
toggleSelect(c.id)}/>
))}
) : (
CreativePlatformObjectiveStatus
SpendCTR
{!(typeof metricHiddenHere==='function' && metricHiddenHere('roas')) && ROAS}
Impr.
{filtered.map(c =>
)}
)}
{/* Compare floating bar */}
{compareMode && selected.length > 0 && (
{selectedCreatives.slice(0,4).map(c => (
p.id===c.platform)||PLATFORMS[0]).tone}}>
{c.format[0].toUpperCase()}
))}
{selected.length} creative{selected.length===1?'':'s'} selected
{selected.length<2?'select at least 2 to compare':selected.length>=4?'4 max':''}
setShowCompare(true)}
className={selected.length<2?'opacity-50 pointer-events-none':''}>
Compare →
)}
setShowCompare(false)} creatives={selectedCreatives}/>
);
}
Object.assign(window, { CreativePreview });