← 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&apos;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>
  );
}