'use client'; import { useEffect, useState } from 'react'; import { Button, Input, Label, Card, CardContent, CardHeader, CardTitle, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@horux/shared-ui'; import { getAllInvitations, createInvitation, cancelInvitation } from '@/lib/api/trial-invitations'; import { getTenants } from '@/lib/api/tenants'; import { Gift, X, Clock, CheckCircle2, AlertTriangle, Loader2 } from 'lucide-react'; interface TenantOption { id: string; nombre: string; rfc: string; } interface Invitation { id: string; tenantId: string; plan: string; durationDays: number; status: string; token: string; sentAt: string; expiresAt: string; acceptedAt: string | null; tenant: { nombre: string; rfc: string; } | null; } export default function InvitacionesTrialPage() { const [tenants, setTenants] = useState([]); const [invitations, setInvitations] = useState([]); const [loading, setLoading] = useState(true); const [creating, setCreating] = useState(false); const [selectedTenantId, setSelectedTenantId] = useState(''); const [durationDays, setDurationDays] = useState('30'); const [plan, setPlan] = useState('business_control'); const [message, setMessage] = useState<{ kind: 'ok' | 'err'; text: string } | null>(null); useEffect(() => { loadData(); }, []); async function loadData() { setLoading(true); try { const [tenantsData, invitationsData] = await Promise.all([ getTenants(), getAllInvitations(), ]); setTenants(tenantsData); setInvitations(invitationsData); } catch (err: any) { setMessage({ kind: 'err', text: err?.response?.data?.message || 'Error al cargar datos' }); } finally { setLoading(false); } } async function handleCreate() { if (!selectedTenantId || !durationDays) { setMessage({ kind: 'err', text: 'Selecciona un despacho y duración' }); return; } setCreating(true); setMessage(null); try { await createInvitation({ tenantId: selectedTenantId, plan, durationDays: parseInt(durationDays, 10), }); setMessage({ kind: 'ok', text: 'Invitación enviada correctamente' }); setSelectedTenantId(''); setDurationDays('30'); loadData(); } catch (err: any) { setMessage({ kind: 'err', text: err?.response?.data?.message || 'Error al crear invitación' }); } finally { setCreating(false); } } async function handleCancel(id: string) { if (!confirm('¿Seguro que quieres cancelar esta invitación?')) return; try { await cancelInvitation(id); setMessage({ kind: 'ok', text: 'Invitación cancelada' }); loadData(); } catch (err: any) { setMessage({ kind: 'err', text: err?.response?.data?.message || 'Error al cancelar' }); } } function statusIcon(status: string) { switch (status) { case 'pending': return ; case 'accepted': return ; case 'expired': return ; case 'cancelled': return ; default: return null; } } function statusLabel(status: string) { switch (status) { case 'pending': return 'Pendiente'; case 'accepted': return 'Aceptada'; case 'expired': return 'Expirada'; case 'cancelled': return 'Cancelada'; default: return status; } } return (

Invitaciones de Trial

Envía invitaciones de prueba a despachos específicos

{/* Toast de resultado */} {message && (
{message.text}
)} {/* Formulario de creación */} Nueva invitación
setDurationDays(e.target.value)} />
{/* Tabla de invitaciones */} Historial de invitaciones {loading ? (
) : invitations.length === 0 ? (

No hay invitaciones enviadas

) : (
{invitations.map((inv) => ( ))}
Despacho Plan Días Estado Enviado Expira
{inv.tenant?.nombre || '—'}
{inv.tenant?.rfc || '—'}
{inv.plan === 'business_control' ? 'Business Control' : inv.plan === 'business_cloud' ? 'Enterprise' : inv.plan} {inv.durationDays} {statusIcon(inv.status)} {statusLabel(inv.status)} {new Date(inv.sentAt).toLocaleDateString('es-MX')} {new Date(inv.expiresAt).toLocaleDateString('es-MX')} {inv.status === 'pending' && ( )}
)}
); }