/* JustVitamin × QuikCue — Live AI Demos Demo A renders as a real conversion-optimised PDP page */ const $ = s => document.querySelector(s); const esc = s => { if (!s) return ''; const d = document.createElement('div'); d.textContent = s; return d.innerHTML; }; function setStep(id, cls, text) { const el = $(id); if (!el) return; el.parentElement.className = `step ${cls}`; el.innerHTML = text; } function setBtn(id, loading, text) { const btn = $(id); btn.disabled = loading; btn.classList.toggle('loading', loading); btn.textContent = text; } // ═══════════════════════════════════════════════════════════════ // DEMO A — Product URL → Full PDP + Real Product Images // ═══════════════════════════════════════════════════════════════ let demoA_product = null; let demoA_pack = null; let demoA_imgs = null; async function runDemoA() { const url = $('#demoA-url').value.trim(); if (!url) return; setBtn('#demoA-btn', true, 'Working...'); $('#demoA-output').classList.add('hidden'); ['#a-s1','#a-s2','#a-s3'].forEach(s => setStep(s, '', 'Waiting')); // Step 1: Scrape setStep('#a-s1', 'active', 'Scraping product page...'); try { const r = await fetch('/api/scrape', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({url}) }); const product = await r.json(); if (product.error) throw new Error(product.error); demoA_product = product; setStep('#a-s1', 'done', `✓ ${esc(product.title.substring(0,40))}...`); } catch(e) { setStep('#a-s1', 'error', `✗ ${esc(e.message)}`); setBtn('#demoA-btn', false, '🔴 Generate the Whole Pack'); return; } // Step 2 + 3: AI copy + images in parallel setStep('#a-s2', 'active', 'Gemini generating PDP copy...'); setStep('#a-s3', 'active', 'Generating product images from real photo...'); const packP = fetch('/api/generate-pack', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify(demoA_product) }).then(r => r.json()); const imgP = fetch('/api/generate-images', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify(demoA_product) }).then(r => r.json()); let packOk = false, imgsOk = false; try { demoA_pack = await packP; if (demoA_pack.error) throw new Error(demoA_pack.error); packOk = true; setStep('#a-s2', 'done', `✓ PDP + assets generated (${demoA_pack._generation_time})`); } catch(e) { setStep('#a-s2', 'error', `✗ ${esc(e.message)}`); } try { demoA_imgs = await imgP; if (demoA_imgs.error && !demoA_imgs.original) throw new Error(demoA_imgs.error); imgsOk = true; setStep('#a-s3', 'done', `✓ Product images generated (${demoA_imgs._generation_time || ''})`); } catch(e) { setStep('#a-s3', 'error', `✗ ${esc(e.message)}`); } if (packOk) { renderPDP(demoA_product, demoA_pack, demoA_imgs); $('#demoA-output').classList.remove('hidden'); } setBtn('#demoA-btn', false, '✓ Done — Run Again'); } // ── Render as a real PDP page ─────────────────────────────── function renderPDP(product, pack, imgs) { const pdp = pack.pdp || {}; const out = $('#demoA-pdp'); if (!out) return; // Build gallery images const gallery = buildGallery(product, imgs); const bullets = (pdp.benefit_bullets || []).map(b => `
${esc(b.icon||'✓')}
${esc(b.headline)}
${esc(b.detail)} ${b.proof ? `${esc(b.proof)}` : ''}
` ).join(''); const trustBar = (pdp.trust_signals || []).map(t => `
${esc(t.icon)}${esc(t.text)}
` ).join(''); const whyParas = (pdp.why_paragraphs || []).map(p => `

${esc(p)}

`).join(''); const statsBar = (pdp.stats_bar || []).map(s => `
${esc(s.number)}${esc(s.label)}
` ).join(''); const faq = (pdp.faq || []).map((f,i) => `
${esc(f.q)}

${esc(f.a)}

` ).join(''); const priceInfo = pdp.price_display || {}; const review = pdp.review_quote || {}; // Ad hooks section const hooks = (pack.ad_hooks || []).map(h => `
"${esc(h.hook || h)}"
${h.angle ? `${esc(h.angle)} · ${esc(h.platform||'')}` : ''}
` ).join(''); // Email subjects const emails = (pack.email_subjects || []).map(e => `
${esc(e.flow||'')} ${esc(e.subject)} ${esc(e.preview)}
` ).join(''); // Meta SEO const meta = pack.meta_seo || {}; out.innerHTML = `
${esc(product.category)} › ${esc(product.title.split(' ').slice(0,4).join(' '))}...

${esc(pdp.hero_headline || product.title)}

${esc(pdp.hero_subhead || product.subtitle)}

${(pdp.value_props||[]).map(v=>`✓ ${esc(v)}`).join('')}
${esc(priceInfo.main_price || product.price)} ${esc(product.quantity)}
${esc(priceInfo.price_per_day || '')}
${esc(priceInfo.comparison || '')}
${trustBar}
${pdp.urgency_note ? `
⚡ ${esc(pdp.urgency_note)}
` : ''}
${esc(pdp.usage_instructions || '')}

Key Benefits

${bullets}
${statsBar}

${esc(pdp.why_section_title || 'Why This Formula')}

${whyParas}
${'★'.repeat(review.stars||5)}

"${esc(review.text || '')}"

— ${esc(review.author || 'Verified Buyer')}

Frequently Asked Questions

${faq}
📦 Additional Generated Assets
${meta.title ? `

🔍 Meta SEO

${esc(meta.title)}
justvitamins.co.uk › ${esc(meta.primary_keyword || '')}
${esc(meta.description)}
` : ''} ${hooks ? `

📢 Ad Hooks

${hooks}
` : ''} ${emails ? `

📧 Email Sequences

${emails}
` : ''}
`; } function buildGallery(product, imgs) { const items = []; // Original product images first (product.images || []).forEach((src, i) => { items.push({src: src, label: i === 0 ? 'Original — Main' : `Original — ${i+1}`, isOriginal: true}); }); // AI-generated images if (imgs) { const aiSlots = [ {key:'hero', label:'AI — Clean Studio'}, {key:'lifestyle', label:'AI — Lifestyle'}, {key:'scale', label:'AI — Scale'}, {key:'ingredients', label:'AI — Detail'}, {key:'banner', label:'AI — Banner', wide: true}, ]; aiSlots.forEach(slot => { const d = imgs[slot.key]; if (d && d.filename) { items.push({src: `/generated/${d.filename}`, label: slot.label, caption: d.caption || '', model: d.model || '', wide: slot.wide}); } }); } if (!items.length) return ''; const mainImg = items[0]; const thumbs = items.map((item, i) => `
${esc(item.label)} ${esc(item.label)}
` ).join(''); return `
${thumbs}
`; } window.switchGallery = function(idx, el) { const src = el.dataset.src; const mainImg = $('#pdpMainImg'); if (mainImg) mainImg.src = src; document.querySelectorAll('.pdp-thumb').forEach(t => t.classList.remove('active')); el.classList.add('active'); const badge = $('.pdp-gallery-badge'); if (badge) { const label = el.querySelector('.pdp-thumb-label'); badge.textContent = label?.classList.contains('orig') ? '📷 Original' : '🤖 AI Generated'; } }; // ═══════════════════════════════════════════════════════════════ // DEMO B — Competitor X-Ray (unchanged logic, same render) // ═══════════════════════════════════════════════════════════════ async function runDemoB() { const url = $('#demoB-url').value.trim(); if (!url) return; setBtn('#demoB-btn', true, 'Scanning...'); $('#demoB-output').classList.add('hidden'); setStep('#b-s1', 'active', 'Scraping competitor...'); setStep('#b-s2', '', 'Waiting'); try { const r = await fetch('/api/competitor-xray', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({url}) }); const data = await r.json(); if (data.error) throw new Error(data.error); setStep('#b-s1', 'done', `✓ ${esc((data._scrape_data?.title||'').substring(0,30))}...`); setStep('#b-s2', 'done', `✓ Analysis (${data._generation_time})`); renderXray(data); $('#demoB-output').classList.remove('hidden'); setBtn('#demoB-btn', false, '✓ Done — Try Another'); } catch(e) { setStep('#b-s1', 'error', `✗ ${esc(e.message)}`); setBtn('#demoB-btn', false, '🔍 X-Ray This Competitor'); } } function renderXray(data) { const tactics = (data.top_5_tactics||[]).map(t => `
  • ${esc(t.tactic)} — ${esc(t.explanation)}
  • `).join(''); $('#demoB-left').innerHTML = ` ❌ ${esc(data.competitor_name || 'Competitor')}
    What they're really selling
    ${esc(data.what_theyre_selling)}
    Top 5 Persuasion Tactics
      ${tactics}
    Weakest Claim / Gap
    ⚠️ ${esc(data.weakest_claim)}
    `; const hero = data.jv_hero_section || {}; const diffs = (data.differentiators||[]).map(d => `
  • 🎯${esc(d.point)} — ${esc(d.proof_idea)}
  • `).join(''); const donts = (data.do_not_say||[]).map(d => `
  • ${esc(d)}
  • `).join(''); $('#demoB-right').innerHTML = ` ✓ Just Vitamins — Upgraded

    ${esc(hero.headline)}

    ${esc(hero.body)}

    ${esc(hero.value_prop)}

    3 Differentiators
    ⚠️ Do Not Say
    `; } // ═══════════════════════════════════════════════════════════════ // DEMO C — PDP Surgeon // ═══════════════════════════════════════════════════════════════ let demoC_product = null, demoC_cache = {}; async function runDemoC() { const url = $('#demoC-url').value.trim(); if (!url) return; setBtn('#demoC-btn', true, 'Working...'); $('#demoC-output').classList.add('hidden'); demoC_cache = {}; setStep('#c-s1', 'active', 'Scraping product...'); setStep('#c-s2', '', 'Waiting'); try { const r = await fetch('/api/scrape', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url})}); const product = await r.json(); if (product.error) throw new Error(product.error); demoC_product = product; setStep('#c-s1', 'done', `✓ ${esc(product.title.substring(0,35))}...`); } catch(e) { setStep('#c-s1', 'error', `✗ ${esc(e.message)}`); setBtn('#demoC-btn', false, '🎨 Scrape & Rewrite'); return; } const active = document.querySelector('#demoC-toggles .toggle.active'); await rewriteStyle(active?.dataset.style || 'balanced'); setBtn('#demoC-btn', false, '✓ Done — Change URL'); } async function switchDemoC(style, btn) { document.querySelectorAll('#demoC-toggles .toggle').forEach(t => t.classList.remove('active')); btn.classList.add('active'); if (!demoC_product) return; await rewriteStyle(style); } async function rewriteStyle(style) { if (demoC_cache[style]) { renderSurgeon(demoC_product, demoC_cache[style]); return; } setStep('#c-s2', 'active', `Gemini rewriting as ${style}...`); try { const r = await fetch('/api/pdp-surgeon', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({product:demoC_product,style})}); const result = await r.json(); if (result.error) throw new Error(result.error); demoC_cache[style] = result; setStep('#c-s2', 'done', `✓ ${style} (${result._generation_time})`); renderSurgeon(demoC_product, result); $('#demoC-output').classList.remove('hidden'); } catch(e) { setStep('#c-s2', 'error', `✗ ${esc(e.message)}`); } } function renderSurgeon(product, result) { const bullets = (product.benefits||[]).map(b => `
  • ${esc(b)}
  • `).join(''); $('#demoC-left').innerHTML = ` ✕ Current PDP ${product.images?.[0] ? `Current` : ''}

    ${esc(product.title)}

    ${esc(product.subtitle)}

    ${esc(product.price)} ${esc(product.quantity)}

    `; const rBullets = (result.bullets||[]).map(b => `
    ${esc(b.text)}
    ↑ ${esc(b.annotation)}`).join(''); $('#demoC-right').innerHTML = ` ✓ ${esc(result.style||'balanced').toUpperCase()}

    ${esc(result.title)}

    ↑ SEO title

    ${esc(result.subtitle)}

    ${esc(result.hero_copy)}
    ↑ ${esc(result.hero_annotation)}
    ${rBullets}
    ⭐ ${esc(result.social_proof)}
    ↑ ${esc(result.social_proof_annotation)}
    ${esc(result.price_reframe)}
    ↑ ${esc(result.price_annotation)}

    ${esc(result.usage_instruction)}

    ↑ ${esc(result.usage_annotation)}
    ${result.cta_annotation ? `↑ ${esc(result.cta_annotation)}` : ''}`; } // Smooth scroll document.querySelectorAll('a[href^="#"]').forEach(a => { a.addEventListener('click', e => { const t = document.querySelector(a.getAttribute('href')); if (t) { e.preventDefault(); t.scrollIntoView({behavior:'smooth'}); } }); });