This commit is contained in:
oliver
2026-06-09 14:38:03 -03:00
parent fc90204d97
commit e48cc6e942
3 changed files with 91 additions and 8 deletions
+56 -8
View File
@@ -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) {
+20
View File
@@ -912,6 +912,26 @@
</div>
</div>
</div>
<div class="acct-divider"></div>
<div class="acct-section">
<div class="acct-field-label">Affiliate Code</div>
<div class="acct-affiliate-row">
<span
class="acct-affiliate-code"
id="acct-affiliate-code"
></span
>
<button
type="button"
id="acct-affiliate-copy-btn"
class="btn btn-ghost btn-sm"
onclick="copyAffiliateCode()"
style="display: none"
>
Copy
</button>
</div>
</div>
</div>
<!-- ── Vertical divider ──────────────────────── -->
<div class="account-col-divider"></div>
+15
View File
@@ -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);