← back to Govarbitrage
src/app/billing/success/page.tsx
45 lines
import Link from "next/link";
import { getCurrentUser } from "@/lib/current-user";
import { prisma } from "@/lib/db";
import { tierDef } from "@/lib/tiers";
import type { Tier } from "@prisma/client";
export const dynamic = "force-dynamic";
// Post-checkout landing. In MOCK mode (no webhook) we upgrade the user here so
// the flow is demoable end-to-end. In TEST mode the Stripe webhook is the real
// source of truth; this page just confirms.
export default async function BillingSuccess({
searchParams,
}: {
searchParams: Promise<{ tier?: string; mock?: string; session?: string }>;
}) {
const sp = await searchParams;
const tier = (sp.tier === "STANDARD" || sp.tier === "PREMIUM" ? sp.tier : "STANDARD") as Tier;
const user = await getCurrentUser();
let applied = false;
if (user && sp.mock === "1") {
// MOCK upgrade: no real charge occurred. Reflect it so the gate is demoable.
await prisma.user.update({ where: { id: user.sub }, data: { tier } });
applied = true;
}
const def = tierDef(tier);
return (
<main style={{ maxWidth: 560, margin: "80px auto", fontFamily: "system-ui", padding: "0 20px" }}>
<div style={{ fontSize: 40 }}>🎉</div>
<h1 style={{ margin: "8px 0" }}>You're on {def.label}</h1>
<p style={{ color: "#475569" }}>
{sp.mock === "1"
? "(TEST/mock checkout — no real charge.) "
: ""}
{applied ? "Your account is upgraded — the money-math + hot-deal alerts are unlocked." : "Your subscription is confirming; refresh in a moment."}
</p>
<p style={{ marginTop: 24 }}>
<Link href="/" style={{ color: "#2563eb" }}>→ Open the dashboard</Link>
</p>
</main>
);
}