'use client'; import { useMemo } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Header } from '@/components/layouts/header'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@horux/shared-ui'; import { apiClient } from '@/lib/api/client'; import { useContribuyenteStore } from '@/stores/contribuyente-store'; import { Bell, Loader2 } from 'lucide-react'; const EMAIL_LABELS: Record = { documento_subido: { label: 'Documento subido', description: 'Notificación cuando se sube una declaración o documento extra del contribuyente.', status: 'active', }, weekly_update: { label: 'Reporte semanal', description: 'Resumen de KPIs, alertas y discrepancias enviado los lunes 8:00 AM.', status: 'pending', }, subscription_expiring: { label: 'Vencimiento de suscripción', description: 'Aviso cuando la suscripción del despacho está por vencer.', status: 'pending', }, recordatorio_fiscal: { label: 'Recordatorios fiscales', description: 'Avisos de obligaciones próximas a vencer (declaraciones, pagos provisionales).', status: 'pending', }, }; interface ContribuyentePrefs { contribuyenteId: string; rfc: string; nombre: string; preferences: Record; } interface ListResponse { emailTypes: string[]; data: ContribuyentePrefs[]; } export default function NotificacionesPage() { const queryClient = useQueryClient(); const { selectedContribuyenteId } = useContribuyenteStore(); const { data, isLoading } = useQuery({ queryKey: ['notification-preferences'], queryFn: async () => { const res = await apiClient.get('/notificaciones'); return res.data; }, }); // Aplica el filtro del selector global de contribuyente. Si hay uno // seleccionado, solo se muestra esa fila. "Todos" muestra todos. const visibles = useMemo(() => { if (!data) return []; if (!selectedContribuyenteId) return data.data; return data.data.filter(c => c.contribuyenteId === selectedContribuyenteId); }, [data, selectedContribuyenteId]); const mutation = useMutation({ mutationFn: async ({ contribuyenteId, emailType, enabled }: { contribuyenteId: string; emailType: string; enabled: boolean }) => { await apiClient.put('/notificaciones', { contribuyenteId, preferences: { [emailType]: enabled }, }); }, onMutate: async ({ contribuyenteId, emailType, enabled }) => { await queryClient.cancelQueries({ queryKey: ['notification-preferences'] }); const previous = queryClient.getQueryData(['notification-preferences']); if (previous) { queryClient.setQueryData(['notification-preferences'], { ...previous, data: previous.data.map(c => c.contribuyenteId === contribuyenteId ? { ...c, preferences: { ...c.preferences, [emailType]: enabled } } : c, ), }); } return { previous }; }, onError: (_err, _vars, context) => { if (context?.previous) queryClient.setQueryData(['notification-preferences'], context.previous); }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['notification-preferences'] }); }, }); return ( <>
Correos informativos por contribuyente Por default todos los correos están activados. Desactiva los que no quieras recibir para cada cliente. Los correos críticos (welcome, recuperación de contraseña, confirmación de pago) siempre se envían independientemente de esta configuración. {isLoading ? (
Cargando...
) : visibles.length === 0 ? ( {selectedContribuyenteId ? 'El contribuyente seleccionado no tiene preferencias configuradas todavía.' : 'No hay contribuyentes en este despacho.'} ) : ( visibles.map(contrib => ( {contrib.nombre} {contrib.rfc}
{(data?.emailTypes ?? []).map(type => { const meta = EMAIL_LABELS[type]; if (!meta) return null; const checked = contrib.preferences[type] !== false; const isPending = meta.status === 'pending'; return (
{meta.label} {isPending && ( Próximamente )}

{meta.description}

)) )}
); }