import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { captureEvent } from '@/lib/posthog'; import { cn } from '@/lib/utils'; import { checkout } from '@/routes/subscribe'; import { type SharedData } from '@/types'; import { Plan } from '@/types/pricing'; import { formatCurrency } from '@/utils/currency'; import { __ } from '@/utils/i18n'; import { usePage } from '@inertiajs/react'; import { ZapIcon } from 'lucide-react'; import { useState } from 'react'; /** * The upsell entry point a checkout starts from. Mirrors the PHP * App\Enums\UpsellSource so revenue can be attributed per point. */ export type UpsellSource = 'ai_categorization' | 'connections' | 'accounts'; export function PlanCard({ plan, isSelected, onSelect, currency, locale, }: { plan: Plan; isSelected: boolean; onSelect: () => void; currency: string; locale: string; }) { const savingsPercent = plan.original_price && plan.billing_period === 'year' ? Math.round( ((plan.original_price - plan.price) / plan.original_price) * 100, ) : null; const monthlyEquivalent = plan.billing_period === 'year' ? plan.price / 12 : plan.price; return ( ); } /** * A contextual "this is a paid feature" dialog with a plan picker that starts * Stripe checkout. Reused across upsell points (AI categorization, bank * connections, connected accounts); each passes its own copy and `source`. */ export function UpgradeDialog({ open, onOpenChange, title, description, source, }: { open: boolean; onOpenChange: (open: boolean) => void; title: string; description: string; source: UpsellSource; }) { const { pricing, locale } = usePage().props; const planEntries = Object.entries(pricing.plans); const [selectedPlan, setSelectedPlan] = useState(pricing.defaultPlan); return ( {title} {description}
{planEntries.map(([key, plan]) => ( setSelectedPlan(key)} currency={pricing.currency} locale={locale} /> ))}
captureEvent('upgrade_checkout_started', { source, plan: selectedPlan, }) } >
); }