// Page Builder client. Loads the member's existing page (if any), takes a // four-question brief, and rebuilds at the same /p/ URL so shared links // never break. (function () { 'use strict'; var $ = function (id) { return document.getElementById(id); }; var angle = 'overview', busy = false, myId = null; function renderAngles(angles) { var host = $('pgAngles'); host.innerHTML = ''; Object.keys(angles).forEach(function (k) { var b = document.createElement('button'); b.type = 'button'; b.className = 'pg-angle' + (k === angle ? ' on' : ''); b.textContent = angles[k].label; b.addEventListener('click', function () { angle = k; renderAngles(angles); }); host.appendChild(b); }); } function showMeter(m) { if (!m || !m.limit) { $('pgMeter').textContent = ''; return; } $('pgMeter').innerHTML = '' + m.remaining + ' of ' + m.limit + ' page builds left this month'; } var built = false; function showLive(url) { built = true; $('pgUrl').textContent = url.replace(/^https:\/\//, ''); $('pgOpen').href = url; $('pgLive').style.display = 'block'; // cache-bust so a rebuild always shows the NEW page, not the old one $('pgFrame').src = url + '?preview=' + Date.now(); $('pgPrev').style.display = 'block'; $('pgGo').textContent = 'šŸ” Rebuild my page'; } // Live status under the button. A silent 40-second wait reads as "frozen", // so we narrate it and count the seconds. var progTimer = null; function startProgress() { var el = $('pgProg'), t0 = Date.now(); var steps = [ 'Reading your notes…', 'Writing your headline and story…', 'Choosing your angle video…', 'Laying out your page…', 'Almost there — finishing up…' ]; el.style.display = 'block'; var tick = function () { var s = Math.round((Date.now() - t0) / 1000); var i = Math.min(steps.length - 1, Math.floor(s / 9)); el.innerHTML = '' + steps[i] + ' (' + s + 's)'; }; tick(); progTimer = setInterval(tick, 1000); } function stopProgress() { if (progTimer) clearInterval(progTimer); progTimer = null; $('pgProg').style.display = 'none'; } function gate(msg) { var g = $('pgGate'); g.style.display = 'block'; g.innerHTML = msg; $('pgCard').style.opacity = '.55'; $('pgGo').disabled = true; } async function boot() { try { var r = await fetch('/api/public/suite-page'); if (r.status === 401) { gate('You’re not signed in yet. Open the Suite and connect the wallet that holds your position, then come back.'); renderAngles({ overview: { label: 'General overview' } }); return; } if (r.status === 403) { gate('The Page Builder isn’t open for this position yet. See your Suite.'); return; } if (!r.ok) return; var d = await r.json(); myId = d.id; renderAngles(d.angles || {}); if (d.meter && d.meter.reason === 'locked') { gate('The Page Builder unlocks at Ascensus (level 2). You’re at level ' + d.level + ' — your next upgrade opens it, along with the Copy Engine. See what an upgrade costs →'); return; } showMeter(d.meter); if (d.page) { if (d.page.name) $('pgName').value = d.page.name; if (d.page.audience) $('pgAudience').value = d.page.audience; if (d.page.story) $('pgStory').value = d.page.story; if (d.page.angle) { angle = d.page.angle; renderAngles(d.angles || {}); } showLive('https://rmcircle.team/p/' + d.id); } } catch (e) {} } async function run() { if (busy) return; busy = true; $('pgErr').style.display = 'none'; $('pgGo').disabled = true; // Hide any previous preview while the new one is being written, so a stale // or half-loaded frame can't look like a broken result. $('pgPrev').style.display = 'none'; $('pgFrame').removeAttribute('src'); $('pgGo').innerHTML = 'Writing your page…'; startProgress(); try { var r = await fetch('/api/public/suite-page', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: $('pgName').value.trim(), audience: $('pgAudience').value.trim(), story: $('pgStory').value.trim(), angle: angle }) }); var d = await r.json(); if (!r.ok) { $('pgErr').textContent = d.error || 'That didn’t go through — try again.'; $('pgErr').style.display = 'block'; if (d.meter) showMeter(d.meter); } else { showMeter(d.meter); showLive(d.url); $('pgLive').scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } } catch (e) { $('pgErr').textContent = 'Connection hiccup — try again.'; $('pgErr').style.display = 'block'; } stopProgress(); busy = false; $('pgGo').disabled = false; $('pgGo').textContent = built ? 'šŸ” Rebuild my page' : '🧱 Build my page'; } document.addEventListener('DOMContentLoaded', function () { boot(); $('pgGo').addEventListener('click', run); $('pgCopyUrl').addEventListener('click', function () { navigator.clipboard.writeText($('pgOpen').href).then(function () { $('pgCopied').style.display = ''; setTimeout(function () { $('pgCopied').style.display = 'none'; }, 2500); }); }); }); })();