// Funnel Factory client — lists the member's pages and builds new named ones.
(function () {
'use strict';
var $ = function (id) { return document.getElementById(id); };
function esc(s) {
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
});
}
var state = { angles: {}, angle: 'overview', id: null, pages: [] };
function gate(msg) {
$('fGate').style.display = 'block';
$('fGate').innerHTML = msg;
}
function renderAngles() {
var host = $('fAngles');
host.innerHTML = '';
Object.keys(state.angles).forEach(function (k) {
var b = document.createElement('button');
b.type = 'button';
b.className = 'f-chip' + (state.angle === k ? ' on' : '');
b.textContent = state.angles[k].label || k;
b.addEventListener('click', function () { state.angle = k; renderAngles(); });
host.appendChild(b);
});
}
function renderPages() {
var host = $('fPages');
host.innerHTML = '';
if (!state.pages.length) {
host.innerHTML = '
You have no pages yet. Build your main one in the ' +
'
Page Builder first, then add more here.
';
return;
}
state.pages.forEach(function (p) {
var row = document.createElement('div');
row.className = 'f-page' + (p.slug ? '' : ' main');
var left = document.createElement('div');
left.style.minWidth = '210px';
left.innerHTML = '' + esc(p.name || 'Page') +
(p.slug ? '' : ' MAIN') + '
' +
'rmcircle.team' + esc(p.url) + '
' +
'' + esc((state.angles[p.angle] && state.angles[p.angle].label) || p.angle || '') +
(p.updatedAt ? ' · updated ' + esc(String(p.updatedAt).slice(0, 10)) : '') + '
';
row.appendChild(left);
var acts = document.createElement('div');
acts.className = 'f-acts';
var view = document.createElement('a');
view.className = 'btn btn-secondary btn-sm';
view.href = p.url; view.target = '_blank'; view.rel = 'noopener';
view.textContent = 'View';
acts.appendChild(view);
var copy = document.createElement('button');
copy.className = 'btn btn-secondary btn-sm';
copy.textContent = 'Copy link';
copy.addEventListener('click', function () {
var full = 'https://rmcircle.team' + p.url;
if (navigator.clipboard) navigator.clipboard.writeText(full);
copy.textContent = 'Copied';
setTimeout(function () { copy.textContent = 'Copy link'; }, 1400);
});
acts.appendChild(copy);
if (p.slug) {
var del = document.createElement('button');
del.className = 'btn btn-secondary btn-sm';
del.textContent = 'Delete';
del.addEventListener('click', function () { removePage(p.slug, p.name, del); });
acts.appendChild(del);
}
row.appendChild(acts);
host.appendChild(row);
});
}
async function removePage(slug, name, btn) {
if (!window.confirm('Delete "' + name + '"? Anything already pointing at that address will fall back to your main page.')) return;
btn.disabled = true;
try {
var r = await fetch('/api/public/suite-funnel', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ remove: slug })
});
var d = await r.json();
if (r.ok) { state.pages = d.pages || []; renderPages(); }
else { btn.disabled = false; }
} catch (e) { btn.disabled = false; }
}
async function build() {
$('fErr').style.display = 'none';
$('fOk').style.display = 'none';
var name = $('fName').value.trim();
if (name.length < 2) {
$('fErr').textContent = 'Give the page a short name first.';
$('fErr').style.display = 'block';
return;
}
$('fGo').disabled = true;
$('fGo').innerHTML = 'Writing your page…';
try {
var r = await fetch('/api/public/suite-funnel', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: name, angle: state.angle,
audience: $('fAud').value.trim(), story: $('fStory').value.trim()
})
});
var d = await r.json();
if (!r.ok) {
$('fErr').textContent = d.error || 'That did not build — try again.';
$('fErr').style.display = 'block';
} else {
state.pages = d.pages || [];
renderPages();
if (d.meter) $('fMeter').textContent = d.meter.remaining + ' of ' + d.meter.limit + ' page builds left this month';
$('fOk').innerHTML = '✅ Built. It is live at ' + esc(d.url) + '';
$('fOk').style.display = 'block';
$('fName').value = ''; $('fAud').value = ''; $('fStory').value = '';
}
} catch (e) {
$('fErr').textContent = 'Connection hiccup — try again.';
$('fErr').style.display = 'block';
}
$('fGo').disabled = false;
$('fGo').innerHTML = '🏗️ Build this page';
}
async function boot() {
try {
var r = await fetch('/api/public/suite-funnel');
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.'); return; }
if (r.status === 403) {
var g = await r.json();
gate((g.error || 'Not open for this position yet.') + ' See your Suite.');
return;
}
if (!r.ok) return;
var d = await r.json();
state.angles = d.angles || {};
state.pages = d.pages || [];
state.id = d.id;
$('fIdA').textContent = d.id;
if (d.meter) $('fMeter').textContent = d.meter.remaining + ' of ' + d.meter.limit + ' page builds left this month';
$('fBody').style.display = 'block';
renderAngles(); renderPages();
} catch (e) {}
}
document.addEventListener('DOMContentLoaded', function () {
boot();
$('fGo').addEventListener('click', build);
});
})();