window.SelectionBar = function SelectionBar({ count, total, ctaLabel, onCTA, onClear, onSelectAll, icon, secondaryLabel, onSecondary, secondaryIcon, // Optional destructive action (e.g. bulk delete on the Research tab). // Rendered as a left-aligned ghost button styled in red. dangerLabel, onDanger, dangerIcon, }) { if (count === 0) return null; return (
{count} of {total} ads selected {dangerLabel && ( )}
{secondaryLabel && ( )}
); }; window.TranscriptCard = function TranscriptCard({ ad, script, selected, onToggle, // Edit support: when ``editable`` is true the card surfaces an Edit button. // ``rawText`` is the unparsed response_text used as the initial textarea // value; ``onSave(newText)`` is called with the user's edits. editable, rawText, onSave, onRegenerate, onDiscard, onPromote, promotedAt, }) { const p = PLATFORMS[ad.platform] || PLATFORMS.foreplay; const [editing, setEditing] = React.useState(false); const [draft, setDraft] = React.useState(''); const [saving, setSaving] = React.useState(false); const transcriptText = ad.transcriptRaw || (Array.isArray(ad.transcript) ? ad.transcript.map(seg => seg.body || seg.t || '').filter(Boolean).join('\n') : (ad.transcript || '')); const startEdit = () => { setDraft(rawText || script.map(l => l.body).join('\n\n')); setEditing(true); }; const cancelEdit = () => { setEditing(false); setDraft(''); }; const saveEdit = async () => { if (!onSave) return; setSaving(true); try { await onSave(draft); setEditing(false); } finally { setSaving(false); } }; return (
{selected && }
{ad.brand} {p.label} {ad.id} · remodeled just now
{editable && !editing && ( )} {editable && !editing && onRegenerate && ( )} {editable && !editing && onDiscard && ( )} {editable && !editing && onPromote && ( )} {editing && ( <> )}
{typeof ad.score === 'number' && Score {ad.score.toFixed ? ad.score.toFixed(1) : ad.score}} {ad.daysRunning ? {ad.daysRunning}d running : null} {ad.directionLabel ? {ad.directionLabel} : null} {promotedAt ? Promoted {String(promotedAt).slice(0, 16)} : null}
{(transcriptText || ad.reasoning) && (
Original transcript and scoring notes {ad.reasoning &&

{ad.reasoning}

} {transcriptText &&
{transcriptText}
}
)} {editing ? (