// account-dashboard.el -- Account dashboard: session check, plan card, family. // Handles onAuthStateChange, plan card rendering, family member management. // Compiled with: elc --target=js --bundle --minify --obfuscate // // Required globals: window.NEURON_CFG.supabase_url, window.NEURON_CFG.supabase_anon_key // Required CDN: supabase-js@2 fn main() -> Void { native_js("(function() { 'use strict'; var cfg = window.NEURON_CFG || {}; var sb = supabase.createClient(cfg.supabase_url, cfg.supabase_anon_key, { auth: { flowType: 'implicit' } }); function show(id) { var el = document.getElementById(id); if (el) el.style.display = ''; } function hide(id) { var el = document.getElementById(id); if (el) el.style.display = 'none'; } function setText(id, text) { var el = document.getElementById(id); if (el) el.textContent = text; } function setHtml(id, html) { var el = document.getElementById(id); if (el) el.innerHTML = html; } window.signInWith = async function(provider) { var btn = document.getElementById('btn-' + provider); if (btn) { btn.disabled = true; btn.style.opacity = '0.6'; } try { var result = await sb.auth.signInWithOAuth({ provider: provider, options: { redirectTo: window.location.origin + '/account' } }); if (result.error) { if (btn) { btn.disabled = false; btn.style.opacity = '1'; } } } catch (e) { if (btn) { btn.disabled = false; btn.style.opacity = '1'; } } }; window.signInWithEmail = async function() { var email = document.getElementById('acct-email-input').value.trim(); var pass = document.getElementById('acct-pass-input').value; var msg = document.getElementById('acct-email-msg'); var signinBtn = document.getElementById('acct-signin-btn'); if (!sb) { msg.style.display='block'; msg.style.color='#c44'; msg.textContent='Loading... try again in a moment.'; return; } if (!email || !pass) { msg.style.display='block'; msg.style.color='#c44'; msg.textContent='Please enter your email and password.'; return; } if (signinBtn) { signinBtn.disabled=true; signinBtn.textContent='Signing in...'; } var result = await sb.auth.signInWithPassword({ email: email, password: pass }); if (result.error) { if (result.error.message && result.error.message.toLowerCase().includes('invalid')) { var signupResult = await sb.auth.signUp({ email: email, password: pass, options: { emailRedirectTo: window.location.origin + '/account' } }); if (signupResult.error) { msg.style.display='block'; msg.style.color='#c44'; msg.textContent=signupResult.error.message; return; } msg.style.display='block'; msg.style.color='var(--navy)'; msg.textContent='Check your email to confirm your account.'; return; } if (signinBtn) { signinBtn.disabled=false; signinBtn.textContent='Sign in'; } msg.style.display='block'; msg.style.color='#c44'; msg.textContent=result.error.message; return; } window.location.reload(); }; window.signOut = async function() { var btn = document.getElementById('signout-btn'); var btnTop = document.getElementById('signout-btn-top'); if (btn) { btn.disabled=true; btn.textContent='Signing out...'; } if (btnTop) { btnTop.disabled=true; btnTop.textContent='Signing out...'; } await sb.auth.signOut(); show('signin-section'); hide('dashboard-section'); if (btn) { btn.disabled=false; btn.textContent='Sign out'; } if (btnTop) { btnTop.disabled=false; btnTop.textContent='Sign out'; } }; async function renderPlanCard(row) { var plan = (row && row.plan) ? row.plan : 'free'; var memberNum = (row && row.member_number) ? row.member_number : null; var createdAt = (row && row.created_at) ? row.created_at : null; var planNames = { 'founding': 'Founding Member', 'professional': 'Professional', 'free': 'Free' }; setText('plan-name-el', planNames[plan] || 'Free'); var statusHtml = ''; if (plan === 'founding' || plan === 'professional') { statusHtml = '' + '' + 'Launching within 30 days'; } else { statusHtml = 'Active'; } setHtml('plan-status-el', statusHtml); var billingNote = ''; if (plan === 'founding') { billingNote = '
Lifetime · Never billed again
'; } else if (plan === 'professional') { billingNote = 'Billed monthly ·
'; } else { billingNote = 'On the waitlist
'; } setHtml('plan-billing-note-el', billingNote); var meta = ''; if (createdAt) { var d = new Date(createdAt); var dateStr = d.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); meta += ''; } if (memberNum) { meta += ''; } if (meta) setHtml('plan-meta-el', meta); if (plan === 'founding') { var badgeSection = document.getElementById('badge-section'); var badgeContainer = document.getElementById('badge-html-container'); if (badgeSection) badgeSection.style.display = ''; var badgeN = memberNum || 0; fetch('/api/founding-badge?n=' + badgeN) .then(function(r) { return r.text(); }) .then(function(html) { if (badgeContainer) badgeContainer.innerHTML = html; }) .catch(function() {}); } var roadmapSection = document.getElementById('roadmap-section'); if (plan === 'founding' && roadmapSection) roadmapSection.style.display = ''; if (plan === 'founding') { var famSection = document.getElementById('family-section'); if (famSection) famSection.style.display = 'block'; var session = await sb.auth.getSession(); var userEmail = session.data.session && session.data.session.user ? session.data.session.user.email : ''; if (userEmail) loadFamilyMembers(userEmail); } } async function loadFamilyMembers(parentEmail) { var r = await fetch('/api/family/members?parent_email=' + encodeURIComponent(parentEmail)); var members = await r.json(); var list = document.getElementById('family-list'); if (!list) return; if (!members || !members.length) { list.innerHTML = 'No family members yet.
'; return; } list.innerHTML = members.map(function(m) { return '' + m.child_email + '
' + '' + m.status + '
No active plan
' + 'You have an account but no plan selected yet. Pick one below to preorder.
' + ''; } async function loadWaitlistData() { try { var sess = await sb.auth.getSession(); var token = sess.data && sess.data.session ? sess.data.session.access_token : ''; if (!token) { showNoPlan(); return; } var r = await fetch('/api/my-plan', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({access_token: token}) }); var row = await r.json(); if (!row || !row.plan) { showNoPlan(); return; } renderPlanCard(row); } catch (e) { showNoPlan(); } } function showDashboard(user) { hide('signin-section'); show('dashboard-section'); renderUserChip(user); loadWaitlistData(); } async function init() { var result = await sb.auth.getSession(); var session = result.data && result.data.session; if (session && session.user) { showDashboard(session.user); } else { show('signin-section'); hide('dashboard-section'); } sb.auth.onAuthStateChange(function(event, session) { if (session && session.user) { showDashboard(session.user); } else { show('signin-section'); hide('dashboard-section'); } }); } init(); })()") }