feat: add plan stacking
This commit is contained in:
@@ -57,6 +57,7 @@ export async function migrate() {
|
||||
|
||||
await sql`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS plan TEXT NOT NULL DEFAULT 'free'`;
|
||||
await sql`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS plan_expires_at TIMESTAMPTZ`;
|
||||
await sql`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS plan_stack JSONB NOT NULL DEFAULT '[]'`;
|
||||
|
||||
await sql`CREATE INDEX IF NOT EXISTS idx_pings_monitor ON pings(monitor_id, checked_at DESC)`;
|
||||
await sql`CREATE INDEX IF NOT EXISTS idx_pings_checked_at ON pings(checked_at)`;
|
||||
|
||||
@@ -244,7 +244,7 @@ export const dashboard = new Elysia()
|
||||
const keyId = resolved?.keyId ?? null;
|
||||
if (!accountId) return redirect("/dashboard");
|
||||
|
||||
const [acc] = await sql`SELECT id, email_hash, plan, plan_expires_at, created_at FROM accounts WHERE id = ${accountId}`;
|
||||
const [acc] = await sql`SELECT id, email_hash, plan, plan_expires_at, plan_stack, created_at FROM accounts WHERE id = ${accountId}`;
|
||||
const isSubKey = !!keyId;
|
||||
const apiKeys = isSubKey ? [] : await sql`SELECT id, key, label, created_at, last_used_at FROM api_keys WHERE account_id = ${accountId} ORDER BY created_at DESC`;
|
||||
const loginKey = isSubKey ? null : (cookie?.pingql_key?.value ?? null);
|
||||
|
||||
@@ -51,8 +51,18 @@
|
||||
</div>
|
||||
<% } else if ((plan === 'pro' || plan === 'pro2x' || plan === 'pro4x') && it.account.plan_expires_at) { %>
|
||||
<div class="mt-4 pt-4 border-t divider text-xs text-gray-500">
|
||||
Pro plan expires <%= new Date(it.account.plan_expires_at).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) %>.
|
||||
<%= planLabel %> expires <%= new Date(it.account.plan_expires_at).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) %>.
|
||||
<a href="/dashboard/checkout" class="text-blue-400 hover:text-blue-300 ml-1">Extend or upgrade to Lifetime</a>
|
||||
<% const stack = it.account.plan_stack || [];
|
||||
if (stack.length > 0) {
|
||||
const planNames = { free: 'Free', pro: 'Pro', pro2x: 'Pro 2x', pro4x: 'Pro 4x', lifetime: 'Lifetime' };
|
||||
const parts = stack.map(function(s) {
|
||||
const name = planNames[s.plan] || s.plan;
|
||||
return s.remaining_days == null ? name : name + ' (' + s.remaining_days + 'd)';
|
||||
});
|
||||
%>
|
||||
<div class="mt-1 text-gray-600">Then: <%= parts.join(' → ') %></div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user