import { useState } from 'react'; import { Container, Title, Text, SimpleGrid, Card, Stack, Group, Badge, Button, List, ThemeIcon, TextInput, Center, Alert, SegmentedControl, Box, } from '@mantine/core'; import { IconCheck, IconX, IconRocket, IconStar, IconCrown, IconAlertCircle } from '@tabler/icons-react'; import { useNavigate } from 'react-router-dom'; import api from '../../services/api'; import logoSrc from '../../assets/logo.png'; type BillingInterval = 'month' | 'year'; const plans = [ { id: 'starter', name: 'Starter', monthlyPrice: 29, annualPrice: 261, // 29 * 12 * 0.75 description: 'For small communities getting started', icon: IconRocket, color: 'blue', features: [ { text: 'Up to 50 units', included: true }, { text: 'Chart of Accounts', included: true }, { text: 'Assessment Tracking', included: true }, { text: 'Basic Reports', included: true }, { text: 'Board Planning', included: false }, { text: 'AI Investment Advisor', included: false }, ], }, { id: 'professional', name: 'Professional', monthlyPrice: 79, annualPrice: 711, // 79 * 12 * 0.75 description: 'For growing HOAs that need full features', icon: IconStar, color: 'violet', popular: true, features: [ { text: 'Up to 200 units', included: true }, { text: 'Everything in Starter', included: true }, { text: 'Board Planning & Scenarios', included: true }, { text: 'AI Investment Advisor', included: true }, { text: 'Advanced Reports', included: true }, { text: 'Priority Support', included: false }, ], }, { id: 'enterprise', name: 'Enterprise', monthlyPrice: 0, annualPrice: 0, description: 'For large communities and management firms', icon: IconCrown, color: 'orange', externalUrl: 'https://www.hoaledgeriq.com/#preview-signup', features: [ { text: 'Unlimited units', included: true }, { text: 'Everything in Professional', included: true }, { text: 'Priority Support', included: true }, { text: 'Custom Integrations', included: true }, { text: 'Dedicated Account Manager', included: true }, { text: 'SLA Guarantee', included: true }, ], }, ]; function formatPrice(plan: typeof plans[0], interval: BillingInterval) { if (plan.externalUrl) return { display: 'Custom', sub: '' }; if (interval === 'year') { const monthly = (plan.annualPrice / 12).toFixed(2); return { display: `$${monthly}`, sub: `/mo billed annually ($${plan.annualPrice}/yr)`, }; } return { display: `$${plan.monthlyPrice}`, sub: '/month' }; } export function PricingPage() { const navigate = useNavigate(); const [loading, setLoading] = useState(null); const [error, setError] = useState(''); const [email, setEmail] = useState(''); const [businessName, setBusinessName] = useState(''); const [billingInterval, setBillingInterval] = useState('month'); const handleStartTrial = async (planId: string) => { if (!email.trim()) { setError('Email address is required to start a trial'); return; } if (!businessName.trim()) { setError('HOA / Business name is required to start a trial'); return; } setLoading(planId); setError(''); try { const { data } = await api.post('/billing/start-trial', { planId, billingInterval, email: email.trim(), businessName: businessName.trim(), }); if (data.subscriptionId) { // Navigate to pending page with subscription ID for polling navigate(`/onboarding/pending?session_id=${data.subscriptionId}`); } else { setError('Unable to start trial'); } } catch (err: any) { setError(err.response?.data?.message || 'Failed to start trial'); } finally { setLoading(null); } }; return ( HOA LedgerIQ Simple, transparent pricing Choose the plan that fits your community. All plans include a 14-day free trial. {/* Monthly / Annual Toggle */}
setBillingInterval(val as BillingInterval)} data={[ { label: 'Monthly', value: 'month' }, { label: 'Annual', value: 'year' }, ]} size="md" radius="xl" /> {billingInterval === 'year' && ( Save 25% )}
{/* Pre-capture fields (required for trial) */}
setEmail(e.currentTarget.value)} style={{ width: 220 }} required /> setBusinessName(e.currentTarget.value)} style={{ width: 220 }} required />
{error && ( } color="red" mb="lg" variant="light"> {error} )} {plans.map((plan) => { const price = formatPrice(plan, billingInterval); return ( {plan.popular && ( Most Popular )}
{plan.name} {plan.description}
{plan.externalUrl ? 'Request Quote' : price.display} {price.sub && ( {price.sub} )} {!plan.externalUrl && billingInterval === 'year' && ( ${plan.monthlyPrice}/mo without annual discount )}
{plan.features.map((f, i) => ( {f.included ? : } } > {f.text} ))}
); })}
All plans include a 14-day free trial. No credit card required.
); }