diff --git a/app.js b/app.js index 424bfcf..20bbfec 100644 --- a/app.js +++ b/app.js @@ -1012,21 +1012,65 @@ async function savePassword() { ACCOUNT / USER PANEL ═══════════════════════════════════════════════════════════════ */ function toggleUserPanel() { - console.log("[account] toggleUserPanel called"); const backdrop = document.getElementById("account-backdrop"); - if (!backdrop) { - console.error("[account] backdrop not found"); - return; - } - // Open first — before anything else can throw + if (!backdrop) return; backdrop.classList.add("open"); const emailEl = document.getElementById("acct-email-display"); if (emailEl) emailEl.textContent = currentEmail || "—"; - const invInput = document.getElementById("invoice-email-input"); - if (invInput) invInput.value = localStorage.getItem("al_invoice_email") || ""; + loadUserData(); loadInvoices(); } +async function loadUserData() { + try { + const res = await apiFetch( + `${INVOICE_EMAIL_URL}?email=${encodeURIComponent(currentEmail || "")}`, + ); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + let data = await res.json(); + dbg("\u2190 User data", data); + // unwrap envelope + if (data && !Array.isArray(data) && Array.isArray(data.data)) { + data = data.data[0]; + } else if (Array.isArray(data)) { + const first = data[0]; + data = + first && typeof first === "object" && "json" in first + ? first.json + : first; + } + if (!data) return; + + const invoiceEmail = stripQuotes( + data.invoice_email || data.invoiceEmail || "", + ); + const invInput = document.getElementById("invoice-email-input"); + if (invInput && invoiceEmail) invInput.value = invoiceEmail; + + const code = stripQuotes( + data.affiliate_code || + data.affiliateCode || + data.referral_code || + data.referralCode || + "", + ); + const codeEl = document.getElementById("acct-affiliate-code"); + const copyBtn = document.getElementById("acct-affiliate-copy-btn"); + if (codeEl) codeEl.textContent = code || "—"; + if (copyBtn) copyBtn.style.display = code ? "inline-flex" : "none"; + } catch (err) { + dbg("\u2190 User data error", err.message); + } +} + +function copyAffiliateCode() { + const code = document.getElementById("acct-affiliate-code")?.textContent; + if (!code || code === "—") return; + navigator.clipboard + .writeText(code) + .then(() => toast("Affiliate code copied!", "success")); +} + function closeUserPanel() { document.getElementById("account-backdrop").classList.remove("open"); const inp = document.getElementById("acct-pw-input"); @@ -1035,6 +1079,10 @@ function closeUserPanel() { if (btn) btn.style.display = "none"; const invBtn = document.getElementById("invoice-email-save-btn"); if (invBtn) invBtn.style.display = "none"; + const codeEl = document.getElementById("acct-affiliate-code"); + if (codeEl) codeEl.textContent = "—"; + const copyBtn = document.getElementById("acct-affiliate-copy-btn"); + if (copyBtn) copyBtn.style.display = "none"; } function toggleAccountPwSave(value) { diff --git a/index.html b/index.html index a49e198..8d91520 100644 --- a/index.html +++ b/index.html @@ -912,6 +912,26 @@ +
+
+
Affiliate Code
+
+ + +
+
diff --git a/styles.css b/styles.css index 45a115f..2fd32c8 100644 --- a/styles.css +++ b/styles.css @@ -1520,6 +1520,21 @@ body::after { white-space: nowrap; } +.acct-affiliate-row { + display: flex; + align-items: center; + gap: 10px; + margin-top: 4px; +} + +.acct-affiliate-code { + font-size: 13px; + font-weight: 600; + color: var(--accent); + letter-spacing: 0.06em; + font-family: "Courier New", monospace; +} + .acct-invoices-title { font-size: 11px; color: var(--text-muted);