@@ -6,10 +6,11 @@ import Link from 'next/link';
import { Button , Input , Label , Card , CardContent , CardHeader , CardTitle , cn } from '@horux/shared-ui' ;
import { Button , Input , Label , Card , CardContent , CardHeader , CardTitle , cn } from '@horux/shared-ui' ;
import { useAuthStore } from '@/stores/auth-store' ;
import { useAuthStore } from '@/stores/auth-store' ;
import { apiClient } from '@/lib/api/client' ;
import { apiClient } from '@/lib/api/client' ;
import { CheckCircle2 , Server , Cloud , ArrowLeft , Clock } from 'lucide-react' ;
import { CheckCircle2 , Server , Cloud , ArrowLeft , Clock , Zap } from 'lucide-react' ;
type VerticalProfile = 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA' ;
type VerticalProfile = 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA' ;
type PlanType = 'trial' | 'business_control' | 'business_cloud' ;
type PlanType = 'trial' | 'business_control' | 'business_cloud' | 'mi_empresa' | 'mi_empresa_plus' ;
type Frequency = 'monthly' | 'annual' ;
export default function RegisterDespachoPage() {
export default function RegisterDespachoPage() {
const router = useRouter ( ) ;
const router = useRouter ( ) ;
@@ -17,6 +18,8 @@ export default function RegisterDespachoPage() {
const [ step , setStep ] = useState ( 1 ) ;
const [ step , setStep ] = useState ( 1 ) ;
const [ verticalProfile , setVerticalProfile ] = useState < VerticalProfile | null > ( null ) ;
const [ verticalProfile , setVerticalProfile ] = useState < VerticalProfile | null > ( null ) ;
const [ selectedPlan , setSelectedPlan ] = useState < PlanType | 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 [ loading , setLoading ] = useState ( false ) ;
const [ error , setError ] = useState ( '' ) ;
const [ error , setError ] = useState ( '' ) ;
const [ form , setForm ] = useState ( {
const [ form , setForm ] = useState ( {
@@ -38,11 +41,16 @@ export default function RegisterDespachoPage() {
setLoading ( true ) ;
setLoading ( true ) ;
setError ( '' ) ;
setError ( '' ) ;
try {
try {
const frequency : Frequency | undefined =
selectedPlan === 'mi_empresa' ? meFreq :
selectedPlan === 'mi_empresa_plus' ? mePlusFreq :
undefined ;
const { data } = await apiClient . post ( '/despachos/signup' , {
const { data } = await apiClient . post ( '/despachos/signup' , {
despacho : {
despacho : {
nombre : form.despachoNombre ,
nombre : form.despachoNombre ,
verticalProfile ,
verticalProfile ,
plan : selectedPlan ,
plan : selectedPlan ,
frequency ,
} ,
} ,
owner : {
owner : {
nombre : form.ownerNombre ,
nombre : form.ownerNombre ,
@@ -168,10 +176,10 @@ export default function RegisterDespachoPage() {
< span className = "bg-primary text-primary-foreground rounded-full w-6 h-6 flex items-center justify-center font-bold" > 3 < / span >
< span className = "bg-primary text-primary-foreground rounded-full w-6 h-6 flex items-center justify-center font-bold" > 3 < / span >
< / div >
< / div >
< h1 className = "text-3xl font-bold" > Elige tu plan < / h1 >
< h1 className = "text-3xl font-bold" > Elige tu plan < / h1 >
< p className = "text-muted-foreground mt-2" > Todos los planes incluyen las mismas funcionalidade s. < / p >
< p className = "text-muted-foreground mt-2" > Mi Empresa para individuales , Business para despacho s. < / p >
< / div >
< / div >
< div className = "grid grid-cols-1 md:grid-cols-3 gap-6" >
< div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-6" >
{ /* Trial Gratuito */ }
{ /* Trial Gratuito */ }
< Card
< Card
className = { cn (
className = { cn (
@@ -202,6 +210,99 @@ export default function RegisterDespachoPage() {
< / CardContent >
< / CardContent >
< / Card >
< / 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 */ }
{ /* Business Control */ }
< Card
< Card
className = { cn (
className = { cn (
@@ -219,21 +320,23 @@ export default function RegisterDespachoPage() {
< / CardHeader >
< / CardHeader >
< CardContent className = "space-y-4" >
< CardContent className = "space-y-4" >
< div className = "text-center" >
< div className = "text-center" >
< div className = "text-3xl font-bold" > $21 , 00 0< / div >
< div className = "text-3xl font-bold" > $25 , 85 0< / div >
< p className = "text-sm text-muted-foreground" > prime r año ( IVA incluido ) < / p >
< p className = "text-sm text-muted-foreground" > po r año ( IVA incluido ) < / p >
< p className = "text-xs text-muted-foreground mt-1" > $1 5 , 000 / año a partir del 2 do año < / p >
< p className = "text-xs text-muted-foreground mt-1" > + $4 5 / mes por cada RFC adicional sobre 100 < / p >
< / div >
< / div >
< div className = "space-y-2 text-sm" >
< 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 > B ase de datos en tu servidor < / span > < / div >
< div className = "flex items-center gap-2" > < CheckCircle2 className = "h-4 w-4 text-green-500 flex-shrink-0" / > < span > H asta 100 RFCs < / span > < / div >
< div className = "flex items-center gap-2" > < CheckCircle2 className = "h-4 w-4 text-green-500 flex-shrink-0" / > < span > RFCs ilimitados < / 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 > 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 > 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 > Requiere Docker en tu servidor < / 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 >
< / div >
< / CardContent >
< / CardContent >
< / Card >
< / Card >
{ /* B usiness C loud */ }
{ /* Enterprise (b usiness_c loud) */ }
< Card
< Card
className = { cn (
className = { cn (
'cursor-pointer transition-all hover:shadow-lg relative' ,
'cursor-pointer transition-all hover:shadow-lg relative' ,
@@ -241,27 +344,27 @@ export default function RegisterDespachoPage() {
) }
) }
onClick = { ( ) = > setSelectedPlan ( 'business_cloud' ) }
onClick = { ( ) = > setSelectedPlan ( 'business_cloud' ) }
>
>
< 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" >
< 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" >
< 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" / >
< Cloud className = "h-6 w-6 text-purple-600 dark:text-purple-400" / >
< / div >
< / div >
< CardTitle className = "text-xl" > Business Cloud < / CardTitle >
< CardTitle className = "text-xl" > Enterprise < / CardTitle >
< p className = "text-sm text-muted-foreground" > Nosotros lo operamos por ti < / p >
< p className = "text-sm text-muted-foreground" > Despachos grandes con alto volumen < / p >
< / CardHeader >
< / CardHeader >
< CardContent className = "space-y-4" >
< CardContent className = "space-y-4" >
< div className = "text-center" >
< div className = "text-center" >
< div className = "text-3xl font-bold" > $15 , 000 < / div >
< div className = "text-3xl font-bold" > $43 , 000 < / div >
< p className = "text-sm text-muted-foreground" > por año ( fij o) < / p >
< p className = "text-sm text-muted-foreground" > por año ( IVA incluid o) < / p >
< p className = "text-xs text-muted-foreground mt-1" > + $45 / mes por cada RFC gestionado < / p >
< p className = "text-xs text-muted-foreground mt-1" > + $45 / mes por cada RFC adicional sobre 100 < / p >
< / div >
< / div >
< div className = "space-y-2 text-sm" >
< 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 > B ase de datos en la nube ( Horux ) < / span > < / div >
< div className = "flex items-center gap-2" > < CheckCircle2 className = "h-4 w-4 text-green-500 flex-shrink-0" / > < span > H asta 100 RFCs < / span > < / div >
< div className = "flex items-center gap-2" > < CheckCircle2 className = "h-4 w-4 text-green-500 flex-shrink-0" / > < span > Sin infraestructura propia < / 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 > Usuarios ilimitados < / 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 < / 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 className = "flex items-center gap-2" > < CheckCircle2 className = "h-4 w-4 text-green-500 flex-shrink-0" / > < span > Soporte prioritario < / span > < / div >
< / div >
< / div >
< / CardContent >
< / CardContent >