portal link
This commit is contained in:
@@ -23,6 +23,7 @@ const REFERRAL_URL = `${API_BASE}/etc/referral`; // POST {referrer,friend_name,f
|
|||||||
const CREDITS_URL = `${API_BASE}/payment/credits`; // hidden form POST → 302 Stripe redirect
|
const CREDITS_URL = `${API_BASE}/payment/credits`; // hidden form POST → 302 Stripe redirect
|
||||||
const INVOICES_URL = `${API_BASE}/invoices`; // GET ?email=
|
const INVOICES_URL = `${API_BASE}/invoices`; // GET ?email=
|
||||||
const INVOICE_EMAIL_URL = `${API_BASE}/user`; // POST {email, invoice_email}
|
const INVOICE_EMAIL_URL = `${API_BASE}/user`; // POST {email, invoice_email}
|
||||||
|
const PORTAL_URL = `${API_BASE}/account/portal`; // GET ?email= → { url }
|
||||||
const CONTRACT_EXTEND_URL = "https://derez.ai"; // ← replace with Stripe payment 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
|
const CONTRACT_CANCEL_URL = "https://derez.ai"; // ← replace with Stripe cancellation link
|
||||||
|
|
||||||
@@ -1176,6 +1177,38 @@ async function saveInvoiceEmail() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function openBillingPortal() {
|
||||||
|
const btn = document.getElementById("portal-btn");
|
||||||
|
if (!btn) return;
|
||||||
|
if (!currentEmail) {
|
||||||
|
toast("No email found. Please sign in again.", "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btnLoad(btn, "");
|
||||||
|
try {
|
||||||
|
const res = await apiFetch(
|
||||||
|
`${PORTAL_URL}?email=${encodeURIComponent(currentEmail)}`,
|
||||||
|
);
|
||||||
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
|
const data = await res.json();
|
||||||
|
dbg("\u2190 Portal", data);
|
||||||
|
const portalUrl = data.url || (data.data && data.data.url) || data;
|
||||||
|
if (
|
||||||
|
portalUrl &&
|
||||||
|
typeof portalUrl === "string" &&
|
||||||
|
portalUrl.startsWith("http")
|
||||||
|
) {
|
||||||
|
window.open(portalUrl, "_blank");
|
||||||
|
} else {
|
||||||
|
throw new Error("No portal URL returned.");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
toast(err.message, "error");
|
||||||
|
} finally {
|
||||||
|
btnReset(btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loadInvoices() {
|
async function loadInvoices() {
|
||||||
const body = document.getElementById("invoices-body");
|
const body = document.getElementById("invoices-body");
|
||||||
if (!body) return;
|
if (!body) return;
|
||||||
|
|||||||
+16
@@ -917,6 +917,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="acct-divider"></div>
|
<div class="acct-divider"></div>
|
||||||
|
<div class="acct-section">
|
||||||
|
<div class="acct-field-label">
|
||||||
|
Manage Subscriptions
|
||||||
|
</div>
|
||||||
|
<div class="acct-affiliate-row">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="portal-btn"
|
||||||
|
class="btn btn-ghost btn-sm"
|
||||||
|
onclick="openBillingPortal()"
|
||||||
|
>
|
||||||
|
Portal →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="acct-divider"></div>
|
||||||
<div class="acct-section">
|
<div class="acct-section">
|
||||||
<div class="acct-field-label">Affiliate Code</div>
|
<div class="acct-field-label">Affiliate Code</div>
|
||||||
<div class="acct-affiliate-row">
|
<div class="acct-affiliate-row">
|
||||||
|
|||||||
Reference in New Issue
Block a user