"use client"; import { useEffect, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { getUserFromSession } from "@/lib/auth/get-user"; interface SubscriptionInfo { status: "trialing" | "active" | "expired" | "canceled" | "canceling"; isActive: boolean; daysRemainingInTrial: number | null; trialEndsAt: string | null; subscriptionEndsAt: string | null; } export default function BillingPage() { 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" && (
{subscriptionInfo.daysRemainingInTrial} days free trial remaining
)} {subscriptionInfo.status === "expired" && (
Trial Expired
)} {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" || subscriptionInfo.status === "canceling") && (

{subscriptionInfo.status === "canceling" ? "You can reactivate your subscription anytime. " : "Manage your subscription: "}

)}
)} {/* Pricing Card */} {!subscriptionInfo?.isActive && (

Upgrade to Pro

Continue using Stripe to Invoice after your free trial ends.

£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. Just click "Manage subscription" in the Current Status section above.

What happens after the trial?

After your 14-day trial ends, your access will be limited until you upgrade to a paid subscription.

Is my payment information secure?

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

); }