diff --git a/app.js b/app.js index 29c2552..cc30b90 100644 --- a/app.js +++ b/app.js @@ -24,6 +24,7 @@ const CREDITS_URL = `${API_BASE}/payment/credits`; // hidden form POST → 302 S const INVOICES_URL = `${API_BASE}/invoices`; // GET ?email= const INVOICE_EMAIL_URL = `${API_BASE}/user`; // POST {email, invoice_email} const PORTAL_URL = `${API_BASE}/account/portal`; // GET ?email= → { url } +const AFFILIATE_LINKS_URL = `${API_BASE}/affiliate/link`; // GET → [{areas:[{area,text,link}]}] const CONTRACT_EXTEND_URL = "https://derez.ai"; // ← replace with Stripe payment link const CONTRACT_CANCEL_URL = "https://derez.ai"; // ← replace with Stripe cancellation link @@ -1116,6 +1117,17 @@ function closeUserPanel() { if (codeEl) codeEl.textContent = "—"; const copyBtn = document.getElementById("acct-affiliate-copy-btn"); if (copyBtn) copyBtn.style.display = "none"; + // reset tab to settings + const settingsTab = document.getElementById("acct-tab-settings"); + const affiliateTab = document.getElementById("acct-tab-affiliate"); + const settingsPane = document.getElementById("acct-pane-settings"); + const affiliatePane = document.getElementById("acct-pane-affiliate"); + if (settingsTab && affiliateTab && settingsPane && affiliatePane) { + affiliateTab.classList.remove("active"); + settingsTab.classList.add("active"); + affiliatePane.style.display = "none"; + settingsPane.style.display = "flex"; + } } function toggleAccountPwSave(value) { @@ -1348,6 +1360,77 @@ function exportInvoicesCSV() { URL.revokeObjectURL(url); } +/* ─── Account Panel Tab Switching ─────────────────────────────── */ +function switchAccountTab(tab) { + const settingsTab = document.getElementById("acct-tab-settings"); + const affiliateTab = document.getElementById("acct-tab-affiliate"); + const settingsPane = document.getElementById("acct-pane-settings"); + const affiliatePane = document.getElementById("acct-pane-affiliate"); + if (!settingsTab || !affiliateTab || !settingsPane || !affiliatePane) return; + + if (tab === "affiliate") { + settingsTab.classList.remove("active"); + affiliateTab.classList.add("active"); + settingsPane.style.display = "none"; + affiliatePane.style.display = "flex"; + loadAffiliateLinks(); + } else { + affiliateTab.classList.remove("active"); + settingsTab.classList.add("active"); + affiliatePane.style.display = "none"; + settingsPane.style.display = "flex"; + } +} + +async function loadAffiliateLinks() { + const body = document.getElementById("affiliate-links-body"); + if (!body) return; + body.innerHTML = '
'; + try { + const res = await fetch(AFFILIATE_LINKS_URL); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const data = await res.json(); + dbg("\u2190 Affiliate links", data); + renderAffiliateLinks(data); + } catch (err) { + dbg("\u2190 Affiliate links error", err.message); + body.innerHTML = + '

Could not load affiliate links.

'; + } +} + +function renderAffiliateLinks(data) { + const body = document.getElementById("affiliate-links-body"); + if (!body) return; + const rows = Array.isArray(data) ? data : data && data.data ? data.data : []; + const areas = + rows.length && Array.isArray(rows[0].areas) ? rows[0].areas : []; + const filtered = areas.filter((a) => a.text && a.link); + if (!filtered.length) { + body.innerHTML = + '

No affiliate links available yet.

'; + return; + } + body.innerHTML = ` +
+
+ Area + Text + Link +
+ ${filtered + .map( + (a) => ` +
+ ${escHtml(a.area || "—")} + ${escHtml(a.text || "")} + ${a.link ? `Open →` : ``} +
`, + ) + .join("")} +
`; +} + /* ═══════════════════════════════════════════════════════════════ RESTART ═══════════════════════════════════════════════════════════════ */ diff --git a/index.html b/index.html index 6c39c85..cb1592c 100644 --- a/index.html +++ b/index.html @@ -812,7 +812,27 @@ >