update: lifetime discounts based on spent
This commit is contained in:
parent
b014cbf98a
commit
a1d37c6215
|
|
@ -74,7 +74,14 @@ export const routes = new Elysia()
|
|||
// Calculate amount
|
||||
const planDef = PLANS[plan];
|
||||
if (!planDef) { set.status = 400; return { error: `Unknown plan: ${plan}` }; }
|
||||
const amountUsd = planDef.priceUsd ?? (planDef.monthlyUsd! * (months ?? 1));
|
||||
let amountUsd = planDef.priceUsd ?? (planDef.monthlyUsd! * (months ?? 1));
|
||||
|
||||
// Lifetime discount: credit up to 50% of lifetime price from previous payments
|
||||
if (plan === "lifetime" && planDef.priceUsd) {
|
||||
const [{ total }] = await sql`SELECT COALESCE(SUM(amount_usd), 0)::numeric as total FROM payments WHERE account_id = ${accountId} AND status = 'paid'`;
|
||||
const credit = Math.min(Number(total), planDef.priceUsd * 0.5);
|
||||
amountUsd = Math.max(amountUsd - credit, 1);
|
||||
}
|
||||
const rates = await getExchangeRates();
|
||||
const rate = rates[coin];
|
||||
if (!rate) { set.status = 500; return { error: "Could not fetch exchange rate" }; }
|
||||
|
|
|
|||
|
|
@ -273,6 +273,9 @@ export const dashboard = new Elysia()
|
|||
const [acc] = await sql`SELECT plan, plan_expires_at FROM accounts WHERE id = ${resolved.accountId}`;
|
||||
if (acc.plan === "lifetime") return redirect("/dashboard/settings");
|
||||
|
||||
// Total spent on paid invoices (for lifetime discount)
|
||||
const [{ total_spent }] = await sql`SELECT COALESCE(SUM(amount_usd), 0)::numeric as total_spent FROM payments WHERE account_id = ${resolved.accountId} AND status = 'paid'`;
|
||||
|
||||
// Fetch coins server-side for no-JS rendering
|
||||
const payApi = process.env.PAY_API || "https://pay.pingql.com";
|
||||
let coins: any[] = [];
|
||||
|
|
@ -282,7 +285,7 @@ export const dashboard = new Elysia()
|
|||
coins = data.coins || [];
|
||||
} catch {}
|
||||
|
||||
return html("checkout", { nav: "settings", account: acc, payApi, invoiceId: null, coins, invoice: null });
|
||||
return html("checkout", { nav: "settings", account: acc, payApi, invoiceId: null, coins, invoice: null, totalSpent: Number(total_spent) });
|
||||
})
|
||||
|
||||
// Existing invoice by ID — SSR the payment status
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
const coins = it.coins || [];
|
||||
const invoice = it.invoice;
|
||||
const payApi = it.payApi || '';
|
||||
const totalSpent = it.totalSpent || 0;
|
||||
const lifetimeBase = 140;
|
||||
const lifetimeDiscount = Math.min(totalSpent, lifetimeBase * 0.5);
|
||||
const lifetimePrice = lifetimeBase - lifetimeDiscount;
|
||||
%>
|
||||
|
||||
<style>
|
||||
|
|
@ -44,9 +48,18 @@
|
|||
</label>
|
||||
<label for="plan-lifetime"
|
||||
class="cursor-pointer text-left bg-surface border-2 border-border-subtle hover:border-yellow-500/40 rounded-xl p-5 transition-colors relative">
|
||||
<% if (lifetimeDiscount > 0) { %>
|
||||
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-green-500/15 text-green-400 border border-green-500/20">Loyalty Discount</span>
|
||||
<% } else { %>
|
||||
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-yellow-500/15 text-yellow-500 border border-yellow-500/20">Launch Deal</span>
|
||||
<% } %>
|
||||
<div class="text-xs text-yellow-500/70 uppercase tracking-wider font-mono mb-1">Lifetime</div>
|
||||
<div class="text-2xl font-bold text-gray-100">$140</div>
|
||||
<% if (lifetimeDiscount > 0) { %>
|
||||
<div class="text-2xl font-bold text-gray-100">$<%= lifetimePrice.toFixed(0) %> <span class="text-sm font-normal text-gray-600 line-through">$<%= lifetimeBase %></span></div>
|
||||
<div class="text-xs text-green-400/70 mt-1">You've paid us $<%= totalSpent.toFixed(0) %> — we've credited $<%= lifetimeDiscount.toFixed(0) %> toward lifetime</div>
|
||||
<% } else { %>
|
||||
<div class="text-2xl font-bold text-gray-100">$<%= lifetimeBase %></div>
|
||||
<% } %>
|
||||
<div class="text-xs text-gray-500 mt-2">One-time, 200 monitors forever</div>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue