"use client"; import { useEffect, useState } from "react"; import { AppShell } from "../../../components/app-shell"; import { apiFetch } from "@/lib/api"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; type SubscriptionData = { plan?: string; status?: string; currentPeriodEnd?: string; cancelAtPeriodEnd?: boolean; }; const PLAN_LABELS: Record = { free: "Free", pro: "Pro", elite: "Elite", }; const PLAN_DESCRIPTIONS: Record = { free: "Up to 2 active accounts, no paid exports, and core ledger tools.", pro: "Up to 10 active accounts, secure exports, Google Sheets sync, and public API access.", elite: "Unlimited active accounts with every Pro capability and dedicated support.", }; const PLAN_PRICES: Record<"pro" | "elite", string> = { pro: "$9/mo", elite: "Custom", }; export default function SubscriptionPage() { const [sub, setSub] = useState(null); const [loading, setLoading] = useState(true); const [actionStatus, setActionStatus] = useState(""); const [actionLoading, setActionLoading] = useState(false); useEffect(() => { apiFetch("/api/billing/subscription") .then((res) => { if (!res.error) setSub(res.data); }) .catch(() => {}) .finally(() => setLoading(false)); }, []); const handleUpgrade = async (plan: string) => { setActionLoading(true); setActionStatus("Redirecting to checkout..."); const appUrl = typeof window !== "undefined" ? window.location.origin : ""; const res = await apiFetch<{ url: string }>("/api/billing/checkout", { method: "POST", body: JSON.stringify({ plan, successUrl: `${appUrl}/settings/subscription?upgraded=1`, cancelUrl: `${appUrl}/settings/subscription`, }), }); setActionLoading(false); if (res.error || !res.data?.url) { setActionStatus(res.error?.message ?? "Could not start checkout. Check Stripe configuration."); return; } window.location.href = res.data.url; }; const handlePortal = async () => { setActionLoading(true); setActionStatus("Redirecting to billing portal..."); const appUrl = typeof window !== "undefined" ? window.location.origin : ""; const res = await apiFetch<{ url: string }>("/api/billing/portal", { method: "POST", body: JSON.stringify({ returnUrl: `${appUrl}/settings/subscription` }), }); setActionLoading(false); if (res.error || !res.data?.url) { setActionStatus(res.error?.message ?? "Could not open billing portal. Check Stripe configuration."); return; } window.location.href = res.data.url; }; const currentPlan = sub?.plan ?? "free"; const planLabel = PLAN_LABELS[currentPlan] ?? currentPlan; const planDesc = PLAN_DESCRIPTIONS[currentPlan] ?? ""; return (
{/* Current plan card */}

Current Plan

{loading ? (
) : ( <>
{planLabel} {sub?.status && sub.status !== "active" && sub.status !== "free" && ( {sub.status} )} {(sub?.status === "active" || currentPlan !== "free") && ( Active )}

{planDesc}

{sub?.cancelAtPeriodEnd && (

Cancels at end of billing period.

)} {sub?.currentPeriodEnd && (

Current period ends {new Date(sub.currentPeriodEnd).toLocaleDateString()}.

)} )} {!loading && currentPlan !== "free" && ( )}
{currentPlan !== "elite" && (
{(["pro", "elite"] as const) .filter((plan) => currentPlan === "free" || plan === "elite") .map((plan) => (

{PLAN_LABELS[plan]}

{PLAN_PRICES[plan]}

{currentPlan === plan && ( Current )}

{PLAN_DESCRIPTIONS[plan]}

))}
)} {actionStatus && (

{actionStatus}

)}
); }