80 lines
3.4 KiB
TypeScript
80 lines
3.4 KiB
TypeScript
'use client';
|
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { DashboardShell } from '@/components/layouts/dashboard-shell';
|
|
import { Card, CardContent, CardHeader, CardTitle, SortableHeader } from '@horux/shared-ui';
|
|
import { apiClient } from '@/lib/api/client';
|
|
import { formatCurrency } from '@/lib/utils';
|
|
import { useTableSort } from '@horux/shared-ui';
|
|
|
|
export default function ConcentracionClientesPage() {
|
|
const { data, isLoading } = useQuery({
|
|
queryKey: ['drilldown-concentracion-clientes'],
|
|
queryFn: async () => {
|
|
const res = await apiClient.get<any[]>('/alertas/drilldown/concentracion-clientes');
|
|
return res.data;
|
|
},
|
|
});
|
|
|
|
const { sortedData, toggleSort, getSortIndicator } = useTableSort<any, 'cfdis' | 'total'>(
|
|
data,
|
|
{
|
|
cfdis: (d) => Number(d.cantidad || 0),
|
|
total: (d) => Number(d.total || 0),
|
|
},
|
|
'total',
|
|
);
|
|
|
|
return (
|
|
<DashboardShell title="Concentracion de Clientes">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-base">Participacion por Cliente (Facturas Emitidas)</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{isLoading ? (
|
|
<div className="text-center py-8 text-muted-foreground">Cargando...</div>
|
|
) : !data || data.length === 0 ? (
|
|
<div className="text-center py-8 text-muted-foreground">No hay datos</div>
|
|
) : (
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="border-b text-left text-muted-foreground">
|
|
<th className="pb-3 font-medium">RFC</th>
|
|
<th className="pb-3 font-medium">Nombre</th>
|
|
<SortableHeader label="CFDIs" align="right" active={getSortIndicator('cfdis')} onClick={() => toggleSort('cfdis')} />
|
|
<SortableHeader label="Total Facturado" align="right" active={getSortIndicator('total')} onClick={() => toggleSort('total')} />
|
|
<th className="pb-3 font-medium text-right">Participacion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{(sortedData || []).map((d: any) => (
|
|
<tr key={d.rfc} className="border-b hover:bg-muted/50">
|
|
<td className="py-3 font-mono text-xs">{d.rfc}</td>
|
|
<td className="py-3 truncate max-w-[200px]">{d.nombre}</td>
|
|
<td className="py-3 text-right">{d.cantidad}</td>
|
|
<td className="py-3 text-right font-medium">{formatCurrency(d.total)}</td>
|
|
<td className="py-3 text-right">
|
|
<div className="flex items-center justify-end gap-2">
|
|
<div className="w-16 bg-muted rounded-full h-2">
|
|
<div
|
|
className="bg-primary rounded-full h-2"
|
|
style={{ width: `${Math.min(d.participacion, 100)}%` }}
|
|
/>
|
|
</div>
|
|
<span className="font-medium w-14 text-right">{d.participacion}%</span>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</DashboardShell>
|
|
);
|
|
}
|