'use client'; import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@horux/shared-ui'; import { Sparkles, Check, ExternalLink } from 'lucide-react'; import { useMyAddons, useSubscribeAddon, useCancelAddon } from '@/lib/hooks/use-addons'; /** * Catálogo de add-ons disponibles **por contribuyente**. No se ofrecen aquí * los add-ons tenant-level (maxRfcs, timbres, etc.) — esos viven en la * pantalla de suscripción del despacho. */ const ADDONS_POR_CONTRIBUYENTE: Array<{ codename: string; nombre: string; descripcion: string; precio: number; frecuencia: 'mensual'; }> = [ { codename: 'lolita_ia_contribuyente', nombre: 'Lolita IA', descripcion: 'Agente IA fiscal dedicado al RFC. Responde dudas, sugiere optimizaciones, prepara resúmenes.', precio: 250, frecuencia: 'mensual', }, ]; export function AddonsDialog({ target, onClose, }: { target: { id: string; nombre: string } | null; onClose: () => void; }) { const { data, isLoading } = useMyAddons(target?.id); const subscribeMut = useSubscribeAddon(); const cancelMut = useCancelAddon(); const handleSubscribe = async (codename: string) => { if (!target) return; try { const result = await subscribeMut.mutateAsync({ addonCodename: codename, contribuyenteId: target.id, }); if (result.paymentUrl) { window.open(result.paymentUrl, '_blank'); } } catch (err: any) { alert(err.response?.data?.message || err.message || 'Error al contratar add-on'); } }; const handleCancel = async (addonId: string, nombre: string) => { if (!confirm(`¿Cancelar ${nombre}? Se deja de cobrar al final del período actual.`)) return; try { await cancelMut.mutateAsync(addonId); } catch (err: any) { alert(err.response?.data?.message || err.message || 'Error al cancelar'); } }; const fmtMoney = (n: number) => n.toLocaleString('es-MX', { style: 'currency', currency: 'MXN', minimumFractionDigits: 0 }); const fmtDate = (iso: string | null) => iso ? new Date(iso).toLocaleDateString('es-MX', { day: '2-digit', month: 'short', year: 'numeric' }) : '—'; const activeAddons = data?.addons ?? []; return ( !o && onClose()}> Add-ons — {target?.nombre}

Servicios adicionales de cobro mensual que se contratan por contribuyente. El cobro va en un preapproval MercadoPago independiente — se puede cancelar sin afectar la licencia anual del despacho.

{isLoading ? (

Cargando add-ons activos...

) : (
{ADDONS_POR_CONTRIBUYENTE.map((a) => { const active = activeAddons.find((x) => x.codename === a.codename); const isActive = active && (active.status === 'authorized' || active.status === 'pending'); return (

{a.nombre}

{isActive && ( {active.status === 'authorized' ? <>Activo : 'Pendiente de pago'} )}

{a.descripcion}

{fmtMoney(a.precio)} / mes

{isActive && active.currentPeriodEnd && (

Próximo cobro: {fmtDate(active.currentPeriodEnd)}

)}
{isActive ? ( ) : ( )}
); })}
)}

Al contratar abre una pestaña de MercadoPago para autorizar el cobro recurrente. Si no tienes una suscripción activa del despacho, el add-on no podrá crearse.

); }