import { useEffect, useState } from 'react'; import { pageProgressMessage } from '../../stores/page'; import { useToast } from '../../hooks/use-toast'; import { useMutation, useQuery } from '@tanstack/react-query'; import { billingDetailsOptions, USER_SUBSCRIPTION_PLAN_PRICES, } from '../../queries/billing'; import { queryClient } from '../../stores/query-client'; import { httpPost } from '../../lib/query-http'; import { UpgradeAccountModal } from './UpgradeAccountModal'; import { getUrlParams } from '../../lib/browser'; import { VerifyUpgrade } from './VerifyUpgrade'; import { EmptyBillingScreen } from './EmptyBillingScreen'; import { Calendar, RefreshCw, Loader2, CreditCard, ArrowRightLeft, CircleX, } from 'lucide-react'; import { BillingWarning } from './BillingWarning'; export type CreateCustomerPortalBody = {}; export type CreateCustomerPortalResponse = { url: string; }; export function BillingPage() { const toast = useToast(); const [showUpgradeModal, setShowUpgradeModal] = useState(false); const [showVerifyUpgradeModal, setShowVerifyUpgradeModal] = useState(false); const { data: billingDetails, isPending: isLoadingBillingDetails } = useQuery( billingDetailsOptions(), queryClient, ); const isCanceled = billingDetails?.status === 'canceled' || billingDetails?.cancelAtPeriodEnd; const isPastDue = billingDetails?.status === 'past_due'; const { mutate: createCustomerPortal, isSuccess: isCreatingCustomerPortalSuccess, isPending: isCreatingCustomerPortal, } = useMutation( { mutationFn: (body: CreateCustomerPortalBody) => { return httpPost( '/v1-create-customer-portal', body, ); }, onSuccess: (data) => { window.location.href = data.url; }, onError: (error) => { console.error(error); toast.error(error?.message || 'Failed to Create Customer Portal'); }, }, queryClient, ); useEffect(() => { if (isLoadingBillingDetails) { return; } pageProgressMessage.set(''); const shouldVerifyUpgrade = getUrlParams()?.s === '1'; if (shouldVerifyUpgrade) { setShowVerifyUpgradeModal(true); } }, [isLoadingBillingDetails]); if (isLoadingBillingDetails || !billingDetails) { return null; } const selectedPlanDetails = USER_SUBSCRIPTION_PLAN_PRICES.find( (plan) => plan.priceId === billingDetails?.priceId, ); const priceDetails = selectedPlanDetails; const formattedNextBillDate = new Date( billingDetails?.currentPeriodEnd || '', ).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); return ( <> {showUpgradeModal && ( { setShowUpgradeModal(false); }} success="/account/billing?s=1" cancel="/account/billing" /> )} {showVerifyUpgradeModal && } {billingDetails?.status === 'none' && !isLoadingBillingDetails && ( setShowUpgradeModal(true)} /> )} {billingDetails?.status !== 'none' && !isLoadingBillingDetails && priceDetails && (
{isCanceled && ( { createCustomerPortal({}); }} isLoading={ isCreatingCustomerPortal || isCreatingCustomerPortalSuccess } /> )} {isPastDue && ( { createCustomerPortal({}); }} isLoading={ isCreatingCustomerPortal || isCreatingCustomerPortalSuccess } /> )}

Current Subscription

Thank you for being a pro member. Your plan details are below.

Payment

${priceDetails.amount} / {priceDetails.interval}

{billingDetails?.cancelAtPeriodEnd ? 'Expires On' : 'Renews On'}

{formattedNextBillDate}

{!isCanceled && ( )}
)} ); }