← Back to Vault
Dealer Portal

Dealer Portal

Sign in to manage your dealer account, generate receipts, and track customer claims.

`); w.document.close(); const img = w.document.querySelector(".qr img"); const doPrint = () => setTimeout(() => w.print(), 200); if (img && !img.complete) { img.onload = doPrint; img.onerror = doPrint; } else doPrint(); } function copyTrackUrl() { const d = dealerData.dealer; if (!d || !d.dealer_slug) return; const trackUrl = window.location.origin + "/track?dealer=" + encodeURIComponent(d.dealer_slug); navigator.clipboard.writeText(trackUrl).then(() => { const btn = event.target; const orig = btn.textContent; btn.textContent = "✓ Copied!"; setTimeout(() => btn.textContent = orig, 1500); }).catch(() => prompt("Copy this link:", trackUrl)); } // ── Render receipts list ── async function loadReceipts() { try { const data = await apiFetch("/api/dealer_receipt?limit=50"); receipts = data.receipts || []; renderReceipts(); } catch (e) { $("receiptList").innerHTML = `
Could not load receipts.
`; } } function renderReceipts() { if (!receipts.length) { $("receiptList").innerHTML = `
No receipts yet. Generate your first receipt above.
`; return; } let html = ``; for (const r of receipts) { const created = r.created_at ? new Date(r.created_at).toLocaleDateString() : "—"; const statusCls = r.status || "pending"; html += ``; } html += "
CodeItemMetalStatusCreated
${esc(r.claim_code)} ${esc(r.label)} ${r.metal} ${r.status} ${created} ${r.status === "pending" ? `` : ""}
"; $("receiptList").innerHTML = html; } // ── Karat shortcuts ── function initKaratBar() { const bar = $("karatBar"); if (!bar) return; bar.addEventListener("click", e => { const btn = e.target.closest(".kBtn"); if (!btn) return; $("rPurity").value = btn.dataset.val; }); } // ── Signup ── async function doSignup() { const btn = $("btnSignup"); const err = $("signupError"); err.textContent = ""; btn.disabled = true; btn.textContent = "Creating…"; try { const body = { business_name: $("suBizName").value.trim(), business_type: $("suBizType").value, contact_email: $("suEmail").value.trim(), contact_name: $("suName").value.trim(), contact_phone: $("suPhone").value.trim(), address_city: $("suCity").value.trim(), address_state: $("suState").value.trim().toUpperCase(), website_url: $("suWebsite").value.trim(), facebook_url: $("suFacebook").value.trim(), instagram_url: $("suInstagram").value.trim(), referral_code: $("suRefCode").value.trim().toUpperCase(), }; if (!body.business_name) throw new Error("Business name is required"); if (!body.contact_email) throw new Error("Email is required"); await apiFetch("/api/dealer_account", { method: "POST", body: JSON.stringify(body) }); // Reload as dealer const ok = await loadDealer(); if (ok) { $("signupSection").style.display = "none"; $("dashSection").style.display = ""; renderProfile(); renderQR(); loadReceipts(); } } catch (e) { err.textContent = e.message; } finally { btn.disabled = false; btn.textContent = "Create Dealer Account"; } } // ── Generate Receipt ── async function doGenerate() { const btn = $("btnGenerate"); const err = $("genError"); err.textContent = ""; btn.disabled = true; btn.textContent = "Generating…"; try { const label = $("rLabel").value.trim(); const metal = $("rMetal").value; const purity = num($("rPurity").value); const weight = num($("rWeight").value); if (!label) throw new Error("Item name is required"); if (purity <= 0 || purity > 1) throw new Error("Enter purity between 0 and 1 (e.g., 0.585 for 14K)"); if (weight <= 0) throw new Error("Enter a valid weight"); const body = { label, metal, purity, weight_value: weight, weight_unit: $("rUnit").value, item_type: $("rType").value, qty: Math.max(1, parseInt($("rQty").value) || 1), purchase_price: num($("rPrice").value) || null, tax_shipping: num($("rTax").value) || null, notes: $("rNotes").value.trim() || null, }; const data = await apiFetch("/api/dealer_receipt", { method: "POST", body: JSON.stringify(body) }); // Show generated receipt const result = $("receiptResult"); const claimUrl = data.claim_url; const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(claimUrl)}&size=250x250&margin=8`; result.style.display = ""; result.innerHTML = `
${data.claim_code}
QR Code
${claimUrl}
`; // Scroll to result result.scrollIntoView({ behavior: "smooth", block: "center" }); // Clear form $("rLabel").value = ""; $("rPurity").value = ""; $("rWeight").value = ""; $("rPrice").value = ""; $("rTax").value = ""; $("rNotes").value = ""; $("rQty").value = "1"; // Reload receipts loadReceipts(); } catch (e) { err.textContent = e.message; } finally { btn.disabled = false; btn.textContent = "✦ Generate Receipt"; } } // ── Void receipt ── async function voidReceipt(id) { if (!confirm("Void this receipt? The customer will no longer be able to claim it.")) return; try { await apiFetch(`/api/dealer_receipt?id=${id}`, { method: "DELETE" }); loadReceipts(); } catch (e) { alert("Error: " + e.message); } } // ── Copy link ── function copyLink(url) { navigator.clipboard.writeText(url).then(() => { const btn = event.target; const orig = btn.textContent; btn.textContent = "✓ Copied!"; setTimeout(() => btn.textContent = orig, 1500); }).catch(() => { prompt("Copy this link:", url); }); } // ── Print receipt ── function printReceipt(code, label, metal, purity, weight, unit, price) { const dealerName = dealerData?.dealer?.business_name || "MetalMetric Dealer"; const claimUrl = `https://metalmetric.com/claim?code=${code}`; const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(claimUrl)}&size=250x250&margin=8`; const purityStr = (num(purity) * 100).toFixed(1) + "%"; const w = window.open("", "_blank", "width=420,height=640"); w.document.write(`Receipt ${code}
${dealerName}
${code}
QR
Item${label}
Metal${metal} · ${purityStr}
Weight${weight} ${unit === "oz" ? "oz t" : "g"}
${price > 0 ? `
Price$${Number(price).toLocaleString()}
` : ""}
Date${new Date().toLocaleDateString()}
${claimUrl}
Scan the QR code or visit the link above to add this item to your free MetalMetric vault.
Track live value, P&L, and portfolio allocation.
`); w.document.close(); setTimeout(() => w.print(), 400); } function esc(s) { const d = document.createElement("div"); d.textContent = s || ""; return d.innerHTML; } // ── Wire events ── $("btnSignup").addEventListener("click", doSignup); $("btnGenerate").addEventListener("click", doGenerate); initKaratBar(); // ── Expose for inline onclick handlers ── window.MM = { voidReceipt, copyLink, printReceipt, downloadQR: downloadQRFromPortal, printCard: printCardFromPortal, copyTrackUrl }; // ── Boot ── (async function boot() { const clerkOk = await waitForClerk(); if (!clerkOk || !window.Clerk) { $("authGate").classList.add("show"); $("btnSignIn").onclick = () => { window.location.href = "https://accounts.metalmetric.com/sign-in?redirect_url=" + encodeURIComponent(window.location.href); }; return; } try { await window.Clerk.load(); if (!window.Clerk.user) { $("authGate").classList.add("show"); $("btnSignIn").onclick = () => window.Clerk.openSignIn({}); return; } // User is signed in $("mainWrap").style.display = ""; // Pre-fill signup email from Clerk const email = window.Clerk.user.primaryEmailAddress?.emailAddress || ""; if ($("suEmail")) $("suEmail").value = email; const fullName = (window.Clerk.user.firstName || "") + " " + (window.Clerk.user.lastName || ""); if ($("suName") && fullName.trim()) $("suName").value = fullName.trim(); // Try loading existing dealer account const isDealer = await loadDealer(); if (isDealer) { $("dashSection").style.display = ""; renderProfile(); renderQR(); loadReceipts(); } else { $("signupSection").style.display = ""; } } catch (e) { $("authGate").classList.add("show"); } })(); })();