'use client'; import { useQuery } from '@tanstack/react-query'; import { Card, CardContent, CardHeader, CardTitle, CardDescription, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@horux/shared-ui'; import { Header } from '@/components/layouts/header'; import { DespachoSubnav } from '@/components/despachos/despacho-subnav'; import { PeriodoSelector } from '@/components/periodo-selector'; import { apiClient } from '@/lib/api/client'; import { useAuthStore } from '@/stores/auth-store'; import { useTenantViewStore } from '@/stores/tenant-view-store'; import { usePeriodoStore, añoMesFromFechaInicio } from '@/stores/periodo-store'; import { Building2, RefreshCw, Loader2, TrendingUp, FileCheck, DollarSign, AlertTriangle } from 'lucide-react'; interface Despacho { id: string; nombre: string; rfc: string; } interface Stats { totalContribuyentes: number; ultimaExtraccion: string | null; progresoDelMes: number; declaracionesPresentadas: number; declaracionesPagadas: number; declaracionesAtrasadas: number; tareasAtrasadas: number; } const PLATFORM_SUPERSET = new Set(['platform_admin', 'platform_ti']); export default function DespachoContribuyentesPage() { const role = useAuthStore(s => s.user?.role); const platformRoles = useAuthStore(s => s.user?.platformRoles); const isPlatformStaff = platformRoles?.some(r => PLATFORM_SUPERSET.has(r)) ?? false; const enabled = role === 'owner' || role === 'cfo' || isPlatformStaff; const { fechaInicio } = usePeriodoStore(); const { año, mes } = añoMesFromFechaInicio(fechaInicio); const { viewingTenantId, setViewingTenant } = useTenantViewStore(); const { data: despachos } = useQuery({ queryKey: ['admin-despachos'], queryFn: async () => { const { data } = await apiClient.get<{ data: Despacho[] }>('/admin/dashboard/despachos'); return data.data; }, enabled: isPlatformStaff, }); const { data, isLoading } = useQuery({ queryKey: ['despacho-contribuyentes-stats', viewingTenantId, año, mes], queryFn: async () => { const { data } = await apiClient.get(`/despachos/contribuyentes-stats?año=${año}&mes=${mes}`); return data; }, enabled, }); if (!enabled) { return ( <>
Esta sección solo está disponible para owner.
); } return ( <>
{isPlatformStaff && despachos && despachos.length > 0 && (
)} {isLoading ? (
Cargando...
) : (
Contribuyentes dados de alta
{data?.totalContribuyentes ?? 0}
Activos en el despacho
Última extracción SAT
{data?.ultimaExtraccion ? new Date(data.ultimaExtraccion).toLocaleDateString('es-MX', { day: 'numeric', month: 'short', year: 'numeric', }) : '—'}
{data?.ultimaExtraccion ? new Date(data.ultimaExtraccion).toLocaleTimeString('es-MX', { hour: '2-digit', minute: '2-digit', }) : 'Sin extracciones registradas'}
Progreso del mes
= 80 ? 'text-success' : (data?.progresoDelMes ?? 0) >= 50 ? 'text-amber-600' : 'text-destructive' }`}> {data?.progresoDelMes ?? 0}%
= 80 ? 'bg-success' : (data?.progresoDelMes ?? 0) >= 50 ? 'bg-amber-500' : 'bg-destructive' }`} style={{ width: `${data?.progresoDelMes ?? 0}%` }} />
Obligaciones y tareas completadas Declaraciones presentadas
{data?.declaracionesPresentadas ?? 0}
Subidas al sistema este mes
Declaraciones pagadas
{data?.declaracionesPagadas ?? 0}
{data?.declaracionesPresentadas ? `${Math.round((data.declaracionesPagadas / data.declaracionesPresentadas) * 100)}% del mes` : 'Con comprobante de pago'}
Declaraciones atrasadas
0 ? 'text-destructive' : ''}`}> {data?.declaracionesAtrasadas ?? 0}
De periodos anteriores sin presentar
Tareas atrasadas
0 ? 'text-destructive' : ''}`}> {data?.tareasAtrasadas ?? 0}
De periodos anteriores sin completar
)}
); }