import { useState } from 'react' import { Link } from 'react-router-dom' import { CreditCard, AlertCircle, Loader2, ExternalLink, Crown } from 'lucide-react' import { billingApi } from '@/api/billing' import { Button } from '@/components/ui/Button' import { PageMeta } from '@/components/common/PageMeta' import { useBillingStore } from '@/store/billingStore' import { BillingPortalError } from '@/types/billing' import { toast } from '@/lib/toast' import { cn } from '@/lib/utils' function formatDate(value: string | null | undefined): string { if (!value) return '—' return new Date(value).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', }) } function statusLabel(status: string): string { switch (status) { case 'trialing': return 'Trialing' case 'active': return 'Active' case 'past_due': return 'Past due' case 'canceled': return 'Canceled' case 'incomplete': return 'Incomplete' case 'complimentary': return 'Complimentary' default: return status } } function statusToneClass(status: string): string { switch (status) { case 'active': case 'complimentary': return 'text-success' case 'trialing': return 'text-info' case 'past_due': case 'incomplete': return 'text-warning' case 'canceled': return 'text-danger' default: return 'text-muted-foreground' } } export function BillingPage() { const subscription = useBillingStore((s) => s.subscription) const planBilling = useBillingStore((s) => s.planBilling) const isLoading = useBillingStore((s) => s.isLoading) const [openingPortal, setOpeningPortal] = useState(false) const status = subscription?.status ?? null const isComplimentary = status === 'complimentary' const isTrialing = status === 'trialing' const isPastDue = status === 'past_due' const isCanceled = status === 'canceled' const handleOpenPortal = async () => { setOpeningPortal(true) try { const { url } = await billingApi.getPortalSession() window.location.href = url } catch (err) { if (err instanceof BillingPortalError) { if (err.code === 'no_stripe_customer') { toast.error('Complete checkout first to access billing portal.') } else { toast.error('Billing portal is not available right now.') } } else { toast.error('Failed to open billing portal.') } setOpeningPortal(false) } } if (isLoading && !subscription) { return (
Manage your subscription, payment method, and billing history.
Your last payment failed.
Update your payment method to keep access to ResolutionFlow.