"use client"; import { Suspense, useEffect, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; interface SubscriptionInfo { status: "trialing" | "active" | "expired" | "canceled" | "canceling"; isActive: boolean; daysRemainingInTrial: number | null; trialEndsAt: string | null; subscriptionEndsAt: string | null; } function BillingPageContent() { const router = useRouter(); const searchParams = useSearchParams(); const [subscriptionInfo, setSubscriptionInfo] = useState(null); const [loading, setLoading] = useState(true); const [checkoutLoading, setCheckoutLoading] = useState(false); const [cancelLoading, setCancelLoading] = useState(false); const [error, setError] = useState(null); const canceled = searchParams.get("canceled"); useEffect(() => { async function loadSubscriptionStatus() { try { const res = await fetch("/api/subscription/status"); if (!res.ok) { throw new Error("Failed to load subscription status"); } const data = await res.json(); setSubscriptionInfo(data); setLoading(false); } catch (err: any) { setError(err.message); setLoading(false); } } loadSubscriptionStatus(); }, [searchParams]); const handleCheckout = async () => { setCheckoutLoading(true); setError(null); try { const res = await fetch("/api/stripe/subscription/checkout", { method: "POST", }); if (!res.ok) { const error = await res.json(); throw new Error(error.error || "Failed to create checkout session"); } const { url } = await res.json(); if (url) { window.location.href = url; } } catch (err: any) { setError(err.message); setCheckoutLoading(false); } }; const handleCancel = async () => { setCancelLoading(true); setError(null); try { const res = await fetch("/api/stripe/subscription/portal", { method: "POST", }); if (!res.ok) { const error = await res.json(); throw new Error(error.error || "Failed to open billing portal"); } const { url } = await res.json(); if (url) { window.location.href = url; } } catch (err: any) { setError(err.message); setCancelLoading(false); } }; if (loading) { return (

Loading billing information…

); } return (
{/* Navigation */}
{/* Canceled Message */} {canceled && (

Payment was canceled. Please try again or contact support.

)} {/* Header */}

Billing & Subscription

Manage your subscription and billing information.

{/* Error */} {error && (

{error}

)} {/* Status Card */} {subscriptionInfo && (

Current Status

{/* Status Badge */}
{subscriptionInfo.status === "active" && (
Subscription Active
)} {subscriptionInfo.status === "trialing" && (
No subscription yet
)} {subscriptionInfo.status === "expired" && (
No subscription
)} {subscriptionInfo.status === "canceling" && (
Scheduled for Cancellation
{subscriptionInfo.subscriptionEndsAt && (

Ends on {new Date(subscriptionInfo.subscriptionEndsAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}

)}
)} {subscriptionInfo.status === "canceled" && (
Subscription Canceled
)}
{/* Manage Subscription Section */} {subscriptionInfo.status === "active" && (

Manage your subscription:{" "}

)} {subscriptionInfo.status === "canceling" && (

You can reactivate your subscription anytime.{" "}

)}
)} {/* Pricing Card */} {(subscriptionInfo?.status === "expired" || subscriptionInfo?.status === "trialing") && (

Start Your Subscription

Get unlimited invoice creation and real-time Stripe to Xero sync.

£50 /month

✓ Unlimited invoice creation
✓ Real-time Stripe to Xero sync
✓ Priority support
✓ Cancel anytime

Secure payment powered by Stripe

)} {/* FAQ */}

FAQ

Can I cancel anytime?

Yes, you can cancel your subscription anytime through the Billing Portal, accessible from the Current Status section above.

Is my payment information secure?

All payments are processed securely through Stripe. We never see or store your credit card information.

What payment methods do you accept?

We accept all major credit cards and payment methods supported by Stripe.

); } export default function BillingPage() { return (

Loading billing information…

}>
); }