// Co-Branded Pages client. Everything previews live, because the whole value of // this tool is seeing what your pages will look like before you commit. (function () { 'use strict'; var $ = function (id) { return document.getElementById(id); }; var state = { accents: [], accent: 'gold' }; function gate(msg) { $('bGate').style.display = 'block'; $('bGate').innerHTML = msg; } function hexFor(key) { var a = state.accents.filter(function (x) { return x.key === key; })[0]; return a ? a.hex : '#f3be43'; } // Same rule the server uses, so the preview cannot disagree with what gets // saved: initials of the first two words, or the first two characters. function monogram(name) { var clean = String(name || '').replace(/[^A-Za-z0-9 ]+/g, ' ').trim(); if (!clean) return ''; var w = clean.split(/\s+/).filter(Boolean); if (w.length >= 2) return (w[0][0] + w[1][0]).toUpperCase(); return w[0].slice(0, 2).toUpperCase(); } function renderSwatches() { var host = $('bSwatches'); host.innerHTML = ''; state.accents.forEach(function (a) { var b = document.createElement('button'); b.type = 'button'; b.className = 'b-sw' + (a.key === state.accent ? ' on' : ''); b.style.background = a.hex; b.title = a.label; b.setAttribute('aria-label', a.label); b.addEventListener('click', function () { state.accent = a.key; renderSwatches(); preview(); }); host.appendChild(b); }); } function preview() { var name = $('bName').value.trim(); var tag = $('bTag').value.trim(); var hex = hexFor(state.accent); var mono = monogram(name); $('bMono').textContent = mono || '—'; $('bMono').style.color = hex; $('bMono').style.border = '2px solid ' + hex; $('bMono').style.background = hex + '22'; $('bPrevName').textContent = name || 'Your brand'; $('bPrevTag').textContent = tag || 'A personal invitation'; $('bPrevGold').style.color = hex; var btn = $('bPrevBtn'); btn.style.background = hex; btn.style.borderColor = hex; btn.style.color = '#071421'; } async function save() { $('bErr').style.display = 'none'; $('bOk').style.display = 'none'; var name = $('bName').value.trim(); if (name.length < 2) { $('bErr').textContent = 'Give your brand a name — two characters or more.'; $('bErr').style.display = 'block'; return; } $('bSave').disabled = true; try { var r = await fetch('/api/public/suite-brand', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ brandName: name, tagline: $('bTag').value.trim(), accent: state.accent }) }); var d = await r.json(); if (!r.ok) { $('bErr').textContent = d.error || 'That did not save.'; $('bErr').style.display = 'block'; } else { $('bOk').innerHTML = '✅ Saved. Every page you have built now carries your branding — ' + 'go and look at one.'; $('bOk').style.display = 'block'; } } catch (e) { $('bErr').textContent = 'Connection hiccup — try again.'; $('bErr').style.display = 'block'; } $('bSave').disabled = false; } async function clearBrand() { if (!window.confirm('Go back to team branding on all your pages?')) return; try { var r = await fetch('/api/public/suite-brand', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clear: true }) }); var d = await r.json(); if (r.ok) { $('bName').value = ''; $('bTag').value = ''; state.accent = 'gold'; renderSwatches(); preview(); $('bOk').innerHTML = 'Back to team branding on all your pages.'; $('bOk').style.display = 'block'; } } catch (e) {} } async function boot() { try { var r = await fetch('/api/public/suite-brand'); 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.accents = d.accents || []; var b = d.brand || {}; state.accent = b.accent || 'gold'; $('bName').value = b.brandName || ''; $('bTag').value = b.tagline || ''; $('bBody').style.display = 'block'; renderSwatches(); preview(); if (!(d.pages || []).length) { $('bOk').innerHTML = 'You have no pages yet — build one and your branding will be on it.'; $('bOk').style.display = 'block'; } } catch (e) {} } document.addEventListener('DOMContentLoaded', function () { boot(); $('bName').addEventListener('input', preview); $('bTag').addEventListener('input', preview); $('bSave').addEventListener('click', save); $('bClear').addEventListener('click', clearBrand); }); })();