6f28e94abd
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
126 lines
8.5 KiB
JavaScript
126 lines
8.5 KiB
JavaScript
// The Circle Suite — P0 tool wall. Wallet sign-in (same challenge/verify flow
|
||
// as the training gate) -> live level from the contract -> tiles light up.
|
||
// Every tile is always VISIBLE: unlocked at-or-below the member's level,
|
||
// dimmed above it. Future tools carry an honest "in development" tag.
|
||
(function () {
|
||
'use strict';
|
||
var LEVELS = ['Scintilla', 'Ascensus', 'Fabrica', 'Culmen', 'Apex', 'Fastigium', 'Vertex', 'Corona'];
|
||
var TOOLS = [
|
||
{ lv: 1, ico: '🎬', name: 'Promo Center', desc: 'Videos, posts, swipes, emails and the banner kit — every piece pre-personalized with your link.', href: '/tools', live: true },
|
||
{ lv: 1, ico: '🖨️', name: 'Printable Handouts', desc: 'Five full-color designs that print two per page — with YOUR QR code on the paper.', href: '/flyers', live: true },
|
||
{ lv: 1, ico: '✅', name: 'Fast Start + Weekly Rhythm', desc: 'The 48-hour launch checklist and the 20-minute weekly routine, personalized and printable.', href: '/fast-start', live: true },
|
||
{ lv: 1, ico: '📊', name: 'Generation Pay Chart', desc: 'Your personal when-does-each-generation-pay-me chart, read live from the contract.', href: '/generation-pay', live: true },
|
||
{ lv: 1, ico: '🎓', name: 'The Circle Method', desc: 'The 10-lesson recruiting and coaching course. Lessons unlock with this same wallet.', href: '/training', live: true },
|
||
{ lv: 1, ico: '📈', name: 'Live Dashboard', desc: 'Your pipeline, organization bar, coach panel and wallet-verified team messages.', href: '/my', live: true },
|
||
{ lv: 1, ico: '🤖', name: 'AI Coach', desc: '24/7 answers about the system, in 21+ languages — the chat bubble on every page of this site.', href: '#', live: true, coach: true },
|
||
{ lv: 2, ico: '✍️', name: 'Copy Engine', desc: 'An AI copywriter tuned to this business: posts, DMs, follow-ups and objection replies with your link filled in.', live: false },
|
||
{ lv: 2, ico: '🧱', name: 'Page Builder', desc: 'Answer five questions, get your own hosted bridge page — your story, your angle video, your QR.', live: false },
|
||
{ lv: 3, ico: '📧', name: 'Email Engine', desc: 'Follow-up sequences and broadcasts in the team voice, exportable to any autoresponder.', live: false },
|
||
{ lv: 3, ico: '🎥', name: 'Video Maker', desc: 'The team’s master promo videos rendered with your personal end-card — your name, your QR, your link.', live: false },
|
||
{ lv: 4, ico: '🗣️', name: 'Voice Profile + Funnels', desc: 'Output that sounds like YOU, plus multi-page funnels on your own team subdomain.', live: false },
|
||
{ lv: 5, ico: '🚦', name: 'Traffic Desk', desc: 'Monthly ad credits on the team’s networks, co-op rotator priority, and AI campaign packs.', live: false },
|
||
{ lv: 6, ico: '🏭', name: 'Funnel Factory', desc: 'Complete hosted funnels with A/B variants, webinar rooms, and a lead CRM.', live: false },
|
||
{ lv: 7, ico: '🧭', name: 'Leader Ops', desc: 'Team radar, AI coaching digests for your legs, and cohort training rooms.', live: false },
|
||
{ lv: 8, ico: '👑', name: 'Founder Desk', desc: 'Your own AI operator running your promotion, API access, and the inner circle.', live: false }
|
||
];
|
||
|
||
var $ = function (id) { return document.getElementById(id); };
|
||
var me = null; // {id, level, levelName, tierName, directCount, inOrg}
|
||
|
||
function pips() {
|
||
var host = $('suPips');
|
||
host.querySelectorAll('.su-pip').forEach(function (p) { p.remove(); });
|
||
for (var k = 1; k <= 8; k++) {
|
||
var p = document.createElement('span');
|
||
p.className = 'su-pip' + (me && me.inOrg && me.level >= k ? (k === 8 ? ' gold' : ' on') : '');
|
||
p.title = 'Level ' + k + ' · ' + LEVELS[k - 1];
|
||
host.appendChild(p);
|
||
}
|
||
}
|
||
|
||
function render() {
|
||
var grid = $('suGrid');
|
||
grid.innerHTML = '';
|
||
var lastLv = 0;
|
||
TOOLS.forEach(function (t) {
|
||
if (t.lv !== lastLv) {
|
||
lastLv = t.lv;
|
||
var h = document.createElement('div');
|
||
h.className = 'su-lvhead';
|
||
h.innerHTML = '<span class="n">L' + t.lv + '</span><span class="nm">' + LEVELS[t.lv - 1] + '</span><span class="rule"></span>';
|
||
grid.appendChild(h);
|
||
}
|
||
var open = !!(me && me.inOrg && me.level >= t.lv);
|
||
var d = document.createElement('div');
|
||
d.className = 'su-tile ' + (me ? (open ? 'open' : 'locked') : 'locked');
|
||
var badge = me
|
||
? (open ? '✓ YOURS' : 'UNLOCKS AT ' + LEVELS[t.lv - 1].toUpperCase())
|
||
: 'LEVEL ' + t.lv;
|
||
d.innerHTML = '<span class="badge">' + badge + '</span><span class="ico">' + t.ico + '</span><h3>' + t.name + '</h3><p>' + t.desc + '</p>'
|
||
+ (t.live
|
||
? (open || !me ? '<a class="go" href="' + t.href + '"' + (t.coach ? ' data-coach="1"' : '') + '>Open →</a>' : '')
|
||
: '<span class="dev">IN DEVELOPMENT — ships with the Suite build-out</span>');
|
||
grid.appendChild(d);
|
||
});
|
||
var coach = grid.querySelector('[data-coach]');
|
||
if (coach) coach.addEventListener('click', function (ev) { ev.preventDefault(); var f = document.querySelector('.chat-fab'); if (f) f.click(); });
|
||
}
|
||
|
||
async function refreshMe() {
|
||
try {
|
||
var r = await fetch('/api/public/suite-me');
|
||
if (!r.ok) return false;
|
||
me = await r.json();
|
||
if (me.beta && !me.allowed) {
|
||
$('suMe').style.display = 'block';
|
||
$('suMe').innerHTML = '<b>#' + me.id + '</b> — you’re early! The Circle Suite is in <b>team beta</b> right now. Your license is already reserved by your position, and every tool below activates for you the moment we open the doors. Nothing to do — watch the team channel.';
|
||
$('suConnect').style.display = 'none';
|
||
me = null; pips(); render();
|
||
return true;
|
||
}
|
||
$('suMe').style.display = 'block';
|
||
$('suMe').innerHTML = me.inOrg
|
||
? '<b>#' + me.id + '</b> · ' + me.tierName + ' · Level ' + me.level + ' (' + me.levelName + ')' +
|
||
(me.directCount >= 2 ? ' · <span style="color:var(--teal)">✓ qualified</span>' : ' · ' + me.directCount + '/2 directs') +
|
||
'<br>Your license covers <b>Level ' + me.level + '</b> and everything below it' +
|
||
(me.level < 8 ? ' — your next upgrade extends it to ' + LEVELS[me.level] + '.' : ' — full Suite.')
|
||
: '<b>#' + me.id + '</b> — this position isn’t inside our team’s organization. The Suite is a benefit of building with our circle; ask the person who shared this page about joining through the team.';
|
||
$('suConnect').style.display = 'none';
|
||
pips(); render();
|
||
return true;
|
||
} catch (e) { return false; }
|
||
}
|
||
|
||
async function connect() {
|
||
var btn = $('suConnect'), err = $('suErr');
|
||
err.style.display = 'none';
|
||
btn.disabled = true; btn.textContent = 'Connecting…';
|
||
try {
|
||
var eth = await window.RMCWallet.pick();
|
||
if (!eth) { err.textContent = 'No wallet found in this browser. On a phone, open this page inside your wallet app’s browser (the DApps tab) — type rmcircle.team/suite there.'; err.style.display = 'block'; btn.disabled = false; btn.textContent = '🔑 Connect wallet — light up my tools'; return; }
|
||
var accs = await eth.request({ method: 'eth_requestAccounts' });
|
||
var account = accs[0];
|
||
try { await window.RMCWallet.ensureChain(eth); } catch (ce) {}
|
||
var ch = await (await fetch('/api/public/msg-challenge', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: account }) })).json();
|
||
if (!ch.message) throw new Error(ch.error || 'Could not start sign-in.');
|
||
var sig = await eth.request({ method: 'personal_sign', params: [ch.message, account] });
|
||
var vr = await (await fetch('/api/public/msg-verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: account, signature: sig }) })).json();
|
||
if (!vr.ok) throw new Error(vr.error || 'Signature check failed.');
|
||
await refreshMe();
|
||
} catch (e) {
|
||
var m = String((e && e.message) || e);
|
||
err.textContent = /not registered|no position/i.test(m)
|
||
? 'This wallet doesn’t hold a position yet. The Suite comes with one — see the Getting Started page.'
|
||
: 'Sign-in didn’t complete: ' + m + ' — tap the button to try again.';
|
||
err.style.display = 'block';
|
||
}
|
||
btn.disabled = false; btn.textContent = '🔑 Connect wallet — light up my tools';
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
pips(); render();
|
||
$('suConnect').addEventListener('click', connect);
|
||
refreshMe(); // silent: already signed in (training gate / Mini App bridge)
|
||
});
|
||
})();
|