393 lines
24 KiB
TypeScript
393 lines
24 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
import { useRouter } from 'next/navigation';
|
||
import Link from 'next/link';
|
||
import { Button, Input, Label, Card, CardContent, CardHeader, CardTitle, cn } from '@horux/shared-ui';
|
||
import { useAuthStore } from '@/stores/auth-store';
|
||
import { apiClient } from '@/lib/api/client';
|
||
import { CheckCircle2, Server, Cloud, ArrowLeft, Clock, Zap } from 'lucide-react';
|
||
|
||
type VerticalProfile = 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA';
|
||
type PlanType = 'trial' | 'business_control' | 'business_cloud' | 'mi_empresa' | 'mi_empresa_plus';
|
||
type Frequency = 'monthly' | 'annual';
|
||
|
||
export default function RegisterDespachoPage() {
|
||
const router = useRouter();
|
||
const { setUser, setTokens } = useAuthStore();
|
||
const [step, setStep] = useState(1);
|
||
const [verticalProfile, setVerticalProfile] = useState<VerticalProfile | null>(null);
|
||
const [selectedPlan, setSelectedPlan] = useState<PlanType | null>(null);
|
||
const [meFreq, setMeFreq] = useState<Frequency>('monthly');
|
||
const [mePlusFreq, setMePlusFreq] = useState<Frequency>('monthly');
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState('');
|
||
const [form, setForm] = useState({
|
||
despachoNombre: '',
|
||
ownerNombre: '',
|
||
ownerEmail: '',
|
||
ownerPassword: '',
|
||
acceptedTerms: false,
|
||
});
|
||
|
||
const handleChange = (field: string) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
setForm((prev) => ({ ...prev, [field]: e.target.value }));
|
||
setError('');
|
||
};
|
||
|
||
const handleSubmit = async () => {
|
||
if (!form.acceptedTerms) { setError('Debes aceptar los términos y condiciones'); return; }
|
||
if (!verticalProfile || !selectedPlan) { setError('Completa todos los pasos'); return; }
|
||
setLoading(true);
|
||
setError('');
|
||
try {
|
||
const frequency: Frequency | undefined =
|
||
selectedPlan === 'mi_empresa' ? meFreq :
|
||
selectedPlan === 'mi_empresa_plus' ? mePlusFreq :
|
||
undefined;
|
||
const { data } = await apiClient.post('/despachos/signup', {
|
||
despacho: {
|
||
nombre: form.despachoNombre,
|
||
verticalProfile,
|
||
plan: selectedPlan,
|
||
frequency,
|
||
},
|
||
owner: {
|
||
nombre: form.ownerNombre,
|
||
email: form.ownerEmail,
|
||
password: form.ownerPassword,
|
||
},
|
||
});
|
||
setTokens(data.accessToken, data.refreshToken);
|
||
setUser(data.user);
|
||
|
||
// If paid plan with payment URL, redirect to MercadoPago
|
||
if (data.paymentUrl) {
|
||
window.location.href = data.paymentUrl;
|
||
} else {
|
||
router.push('/onboarding');
|
||
}
|
||
} catch (err: any) {
|
||
setError(err.response?.data?.message || 'Error al registrar el despacho');
|
||
setStep(1);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
// =================== STEP 1: Registration Form ===================
|
||
if (step === 1) {
|
||
const canProceed = form.despachoNombre && form.ownerNombre && form.ownerEmail && form.ownerPassword.length >= 10 && form.acceptedTerms;
|
||
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-purple-50 dark:from-gray-900 dark:to-gray-800 p-4">
|
||
<Card className="w-full max-w-lg">
|
||
<CardHeader className="text-center">
|
||
<div className="flex items-center justify-center gap-2 text-xs text-muted-foreground mb-4">
|
||
<span className="bg-primary text-primary-foreground rounded-full w-6 h-6 flex items-center justify-center font-bold">1</span>
|
||
<span className="w-8 h-px bg-muted" />
|
||
<span className="bg-muted text-muted-foreground rounded-full w-6 h-6 flex items-center justify-center">2</span>
|
||
<span className="w-8 h-px bg-muted" />
|
||
<span className="bg-muted text-muted-foreground rounded-full w-6 h-6 flex items-center justify-center">3</span>
|
||
</div>
|
||
<CardTitle className="text-2xl font-bold">Crea tu cuenta</CardTitle>
|
||
<p className="text-sm text-muted-foreground mt-1">Plataforma para despachos profesionales</p>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
<div className="space-y-3">
|
||
<div><Label htmlFor="dn">Nombre del despacho</Label><Input id="dn" value={form.despachoNombre} onChange={handleChange('despachoNombre')} placeholder="Despacho Pérez y Asociados" required /></div>
|
||
</div>
|
||
<div className="space-y-3">
|
||
<div><Label htmlFor="on">Tu nombre completo</Label><Input id="on" value={form.ownerNombre} onChange={handleChange('ownerNombre')} placeholder="Juan Pérez" required /></div>
|
||
<div><Label htmlFor="oe">Email</Label><Input id="oe" type="email" value={form.ownerEmail} onChange={handleChange('ownerEmail')} placeholder="juan@despacho.com" required /></div>
|
||
<div><Label htmlFor="op">Contraseña</Label><Input id="op" type="password" value={form.ownerPassword} onChange={handleChange('ownerPassword')} placeholder="Mínimo 10 caracteres" minLength={10} required /></div>
|
||
</div>
|
||
<div className="flex items-start gap-2">
|
||
<input type="checkbox" id="terms" checked={form.acceptedTerms} onChange={(e) => setForm((p) => ({ ...p, acceptedTerms: e.target.checked }))} className="mt-1" />
|
||
<label htmlFor="terms" className="text-sm text-muted-foreground">Acepto los <Link href="/terminos" target="_blank" className="underline text-primary">términos y condiciones</Link></label>
|
||
</div>
|
||
{error && <p className="text-sm text-destructive bg-destructive/10 p-3 rounded-md">{error}</p>}
|
||
<Button onClick={() => canProceed && setStep(2)} className="w-full" disabled={!canProceed}>
|
||
Continuar
|
||
</Button>
|
||
<p className="text-center text-sm text-muted-foreground">
|
||
¿Ya tienes cuenta? <Link href="/login" className="text-primary underline">Inicia sesión</Link>
|
||
</p>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// =================== STEP 2: Vertical Selection ===================
|
||
if (step === 2) {
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-purple-50 dark:from-gray-900 dark:to-gray-800 p-4">
|
||
<div className="w-full max-w-3xl space-y-8 text-center">
|
||
<div>
|
||
<div className="flex items-center justify-center gap-2 text-xs text-muted-foreground mb-4">
|
||
<span className="bg-green-500 text-white rounded-full w-6 h-6 flex items-center justify-center"><CheckCircle2 className="h-4 w-4" /></span>
|
||
<span className="w-8 h-px bg-primary" />
|
||
<span className="bg-primary text-primary-foreground rounded-full w-6 h-6 flex items-center justify-center font-bold">2</span>
|
||
<span className="w-8 h-px bg-muted" />
|
||
<span className="bg-muted text-muted-foreground rounded-full w-6 h-6 flex items-center justify-center">3</span>
|
||
</div>
|
||
<h1 className="text-3xl font-bold">¿Qué tipo de despacho eres?</h1>
|
||
<p className="text-muted-foreground mt-2">Selecciona tu área profesional</p>
|
||
</div>
|
||
<div className="grid md:grid-cols-3 gap-4">
|
||
<button
|
||
onClick={() => { setVerticalProfile('CONTABLE'); setStep(3); }}
|
||
className="p-8 rounded-xl border-2 border-primary bg-card hover:bg-accent transition-all text-center space-y-3"
|
||
>
|
||
<div className="text-4xl">📊</div>
|
||
<h3 className="text-lg font-semibold">Contable</h3>
|
||
<p className="text-sm text-muted-foreground">Gestión fiscal, CFDI, IVA/ISR, SAT sync</p>
|
||
</button>
|
||
<div className="p-8 rounded-xl border-2 border-dashed border-muted bg-muted/30 text-center space-y-3 opacity-50 cursor-not-allowed">
|
||
<div className="text-4xl">⚖️</div>
|
||
<h3 className="text-lg font-semibold">Jurídico</h3>
|
||
<p className="text-sm text-muted-foreground">Próximamente</p>
|
||
</div>
|
||
<div className="p-8 rounded-xl border-2 border-dashed border-muted bg-muted/30 text-center space-y-3 opacity-50 cursor-not-allowed">
|
||
<div className="text-4xl">🏗️</div>
|
||
<h3 className="text-lg font-semibold">Arquitectura</h3>
|
||
<p className="text-sm text-muted-foreground">Próximamente</p>
|
||
</div>
|
||
</div>
|
||
<button onClick={() => setStep(1)} className="text-sm text-muted-foreground underline">
|
||
<ArrowLeft className="h-3 w-3 inline mr-1" />Volver al formulario
|
||
</button>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// =================== STEP 3: Subscription Selection ===================
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-purple-50 dark:from-gray-900 dark:to-gray-800 py-8 px-4">
|
||
<div className="w-full max-w-7xl space-y-8">
|
||
<div className="text-center">
|
||
<div className="flex items-center justify-center gap-2 text-xs text-muted-foreground mb-4">
|
||
<span className="bg-green-500 text-white rounded-full w-6 h-6 flex items-center justify-center"><CheckCircle2 className="h-4 w-4" /></span>
|
||
<span className="w-8 h-px bg-green-500" />
|
||
<span className="bg-green-500 text-white rounded-full w-6 h-6 flex items-center justify-center"><CheckCircle2 className="h-4 w-4" /></span>
|
||
<span className="w-8 h-px bg-primary" />
|
||
<span className="bg-primary text-primary-foreground rounded-full w-6 h-6 flex items-center justify-center font-bold">3</span>
|
||
</div>
|
||
<h1 className="text-3xl font-bold">Elige tu plan</h1>
|
||
<p className="text-muted-foreground mt-2">Mi Empresa para individuales, Business para despachos.</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-6">
|
||
{/* Trial Gratuito */}
|
||
<Card
|
||
className={cn(
|
||
'cursor-pointer transition-all hover:shadow-lg',
|
||
selectedPlan === 'trial' && 'border-primary ring-2 ring-primary/20'
|
||
)}
|
||
onClick={() => setSelectedPlan('trial')}
|
||
>
|
||
<CardHeader className="text-center pb-2">
|
||
<div className="mx-auto bg-green-100 dark:bg-green-900 rounded-full p-3 w-fit mb-2">
|
||
<Clock className="h-6 w-6 text-green-600 dark:text-green-400" />
|
||
</div>
|
||
<CardTitle className="text-xl">Trial Gratuito</CardTitle>
|
||
<p className="text-sm text-muted-foreground">Prueba sin compromiso</p>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="text-center">
|
||
<div className="text-3xl font-bold">$0</div>
|
||
<p className="text-sm text-muted-foreground">por 30 días</p>
|
||
<p className="text-xs text-muted-foreground mt-1">Sin tarjeta de crédito</p>
|
||
</div>
|
||
<div className="space-y-2 text-sm">
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 3 RFCs</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>20 timbres incluidos</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Todas las funcionalidades</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Base de datos en la nube</span></div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Mi Empresa */}
|
||
<Card
|
||
className={cn(
|
||
'cursor-pointer transition-all hover:shadow-lg',
|
||
selectedPlan === 'mi_empresa' && 'border-primary ring-2 ring-primary/20'
|
||
)}
|
||
onClick={() => setSelectedPlan('mi_empresa')}
|
||
>
|
||
<CardHeader className="text-center pb-2">
|
||
<div className="mx-auto bg-emerald-100 dark:bg-emerald-900 rounded-full p-3 w-fit mb-2">
|
||
<Cloud className="h-6 w-6 text-emerald-600 dark:text-emerald-400" />
|
||
</div>
|
||
<CardTitle className="text-xl">Mi Empresa</CardTitle>
|
||
<p className="text-sm text-muted-foreground">Para una sola empresa</p>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="flex bg-muted rounded-lg p-1 text-xs font-medium">
|
||
<button
|
||
type="button"
|
||
onClick={(e) => { e.stopPropagation(); setMeFreq('monthly'); }}
|
||
className={`flex-1 py-1.5 rounded-md transition-colors ${meFreq === 'monthly' ? 'bg-background shadow-sm text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
|
||
>Mensual</button>
|
||
<button
|
||
type="button"
|
||
onClick={(e) => { e.stopPropagation(); setMeFreq('annual'); }}
|
||
className={`flex-1 py-1.5 rounded-md transition-colors flex items-center justify-center gap-1 ${meFreq === 'annual' ? 'bg-background shadow-sm text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
|
||
>Anual <span className="text-emerald-600 dark:text-emerald-400 text-[10px] font-bold">−17%</span></button>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className="text-3xl font-bold">${meFreq === 'monthly' ? '580' : '5,800'}</div>
|
||
<p className="text-sm text-muted-foreground">{meFreq === 'monthly' ? 'por mes (IVA incluido)' : 'por año (IVA incluido)'}</p>
|
||
{meFreq === 'monthly' && <p className="text-xs text-muted-foreground mt-1">o $5,800/año (ahorras 17%)</p>}
|
||
</div>
|
||
<div className="space-y-2 text-sm">
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>1 RFC</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>3 usuarios</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 1,000,000 CFDIs</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Base de datos en la nube</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Dashboard, CFDI, IVA/ISR, alertas</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>50 timbres/mes incluidos</span></div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Mi Empresa + */}
|
||
<Card
|
||
className={cn(
|
||
'cursor-pointer transition-all hover:shadow-lg relative',
|
||
selectedPlan === 'mi_empresa_plus' && 'border-primary ring-2 ring-primary/20'
|
||
)}
|
||
onClick={() => setSelectedPlan('mi_empresa_plus')}
|
||
>
|
||
<div className="absolute -top-3 left-1/2 -translate-x-1/2 bg-primary text-primary-foreground text-xs px-3 py-1 rounded-full">
|
||
Más popular
|
||
</div>
|
||
<CardHeader className="text-center pb-2">
|
||
<div className="mx-auto bg-teal-100 dark:bg-teal-900 rounded-full p-3 w-fit mb-2">
|
||
<Zap className="h-6 w-6 text-teal-600 dark:text-teal-400" />
|
||
</div>
|
||
<CardTitle className="text-xl">Mi Empresa +</CardTitle>
|
||
<p className="text-sm text-muted-foreground">Con API y Lolita IA</p>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="flex bg-muted rounded-lg p-1 text-xs font-medium">
|
||
<button
|
||
type="button"
|
||
onClick={(e) => { e.stopPropagation(); setMePlusFreq('monthly'); }}
|
||
className={`flex-1 py-1.5 rounded-md transition-colors ${mePlusFreq === 'monthly' ? 'bg-background shadow-sm text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
|
||
>Mensual</button>
|
||
<button
|
||
type="button"
|
||
onClick={(e) => { e.stopPropagation(); setMePlusFreq('annual'); }}
|
||
className={`flex-1 py-1.5 rounded-md transition-colors flex items-center justify-center gap-1 ${mePlusFreq === 'annual' ? 'bg-background shadow-sm text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
|
||
>Anual <span className="text-emerald-600 dark:text-emerald-400 text-[10px] font-bold">−17%</span></button>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className="text-3xl font-bold">${mePlusFreq === 'monthly' ? '900' : '9,000'}</div>
|
||
<p className="text-sm text-muted-foreground">{mePlusFreq === 'monthly' ? 'por mes (IVA incluido)' : 'por año (IVA incluido)'}</p>
|
||
{mePlusFreq === 'monthly' && <p className="text-xs text-muted-foreground mt-1">o $9,000/año (ahorras 17%)</p>}
|
||
</div>
|
||
<div className="space-y-2 text-sm">
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>1 RFC</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>3 usuarios</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 1,000,000 CFDIs</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Base de datos en la nube</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Dashboard, CFDI, IVA/ISR, alertas</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>50 timbres/mes incluidos</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span><strong>API REST</strong> incluida</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span><strong>Lolita IA</strong> agente fiscal</span></div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Business Control */}
|
||
<Card
|
||
className={cn(
|
||
'cursor-pointer transition-all hover:shadow-lg',
|
||
selectedPlan === 'business_control' && 'border-primary ring-2 ring-primary/20'
|
||
)}
|
||
onClick={() => setSelectedPlan('business_control')}
|
||
>
|
||
<CardHeader className="text-center pb-2">
|
||
<div className="mx-auto bg-blue-100 dark:bg-blue-900 rounded-full p-3 w-fit mb-2">
|
||
<Server className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||
</div>
|
||
<CardTitle className="text-xl">Business Control</CardTitle>
|
||
<p className="text-sm text-muted-foreground">Tu servidor, tus datos</p>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="text-center">
|
||
<div className="text-3xl font-bold">$25,850</div>
|
||
<p className="text-sm text-muted-foreground">por año (IVA incluido)</p>
|
||
<p className="text-xs text-muted-foreground mt-1">+ $45/mes por cada RFC adicional sobre 100</p>
|
||
</div>
|
||
<div className="space-y-2 text-sm">
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 100 RFCs</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Usuarios ilimitados</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 1,000,000 CFDIs por contribuyente</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Servidor local con backup</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Control total de tus datos</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Dashboard, CFDI, IVA/ISR, alertas, calendario</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Reportes, conciliación, documentos, facturación, API</span></div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Enterprise (business_cloud) */}
|
||
<Card
|
||
className={cn(
|
||
'cursor-pointer transition-all hover:shadow-lg relative',
|
||
selectedPlan === 'business_cloud' && 'border-primary ring-2 ring-primary/20'
|
||
)}
|
||
onClick={() => setSelectedPlan('business_cloud')}
|
||
>
|
||
<CardHeader className="text-center pb-2">
|
||
<div className="mx-auto bg-purple-100 dark:bg-purple-900 rounded-full p-3 w-fit mb-2">
|
||
<Cloud className="h-6 w-6 text-purple-600 dark:text-purple-400" />
|
||
</div>
|
||
<CardTitle className="text-xl">Enterprise</CardTitle>
|
||
<p className="text-sm text-muted-foreground">Despachos grandes con alto volumen</p>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="text-center">
|
||
<div className="text-3xl font-bold">$43,000</div>
|
||
<p className="text-sm text-muted-foreground">por año (IVA incluido)</p>
|
||
<p className="text-xs text-muted-foreground mt-1">+ $45/mes por cada RFC adicional sobre 100</p>
|
||
</div>
|
||
<div className="space-y-2 text-sm">
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 100 RFCs</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Usuarios ilimitados</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Hasta 3,000,000 CFDIs por contribuyente</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Servidor local con backup</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Backups automáticos en la nube</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Dashboard, CFDI, IVA/ISR, alertas, calendario</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Reportes, conciliación, documentos, facturación, API</span></div>
|
||
<div className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-green-500 flex-shrink-0" /><span>Soporte prioritario</span></div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
|
||
{error && <p className="text-sm text-destructive bg-destructive/10 p-3 rounded-md text-center max-w-lg mx-auto">{error}</p>}
|
||
|
||
<div className="flex flex-col items-center gap-3">
|
||
<Button
|
||
onClick={handleSubmit}
|
||
disabled={!selectedPlan || loading}
|
||
size="lg"
|
||
className="px-12"
|
||
>
|
||
{loading ? 'Creando tu despacho...' : selectedPlan === 'trial' ? 'Comenzar trial gratuito' : 'Continuar al pago'}
|
||
</Button>
|
||
<button onClick={() => setStep(2)} className="text-sm text-muted-foreground underline">
|
||
<ArrowLeft className="h-3 w-3 inline mr-1" />Volver
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|