4.2 KiB
Drill-down genérica — sort por nombre emisor/receptor
Contexto
La tabla de la página /drill-down (apps/web/app/(dashboard)/drill-down/page.tsx)
actualmente permite ordenar por Fecha, Total MXN, Monto Pago e IVA Trasl.
mediante el hook useTableSort y el componente SortableHeader de
@horux/shared-ui. Las columnas Nombre Emisor y Nombre Receptor se
renderizan como <th> planos no ordenables.
Objetivo
Permitir ordenar también por nombre del emisor y por nombre del receptor, sin remover ninguna de las columnas ordenables existentes.
Alcance limitado a la drill-down genérica. Las 9 páginas de /alertas/* quedan
fuera de este cambio (decisión del owner — se evaluarán después).
Cambios
Archivo único: apps/web/app/(dashboard)/drill-down/page.tsx.
-
Extender el segundo parámetro de tipo de
useTableSortpara incluir las nuevas keys:useTableSort<Cfdi, 'fecha' | 'total' | 'pago' | 'iva' | 'emisor' | 'receptor'> -
Agregar dos accesores al objeto pasado al hook:
emisor: (c) => c.nombreEmisor || '', receptor: (c) => c.nombreReceptor || '',useTableSortya soporta accesores de tipostring— usaString.prototype.localeComparecuando ambos valores son strings, lo cual maneja la collation del español correctamente. -
Reemplazar los dos
<th>planos porSortableHeader:// antes <th className="pb-3 font-medium">Nombre Emisor</th> <th className="pb-3 font-medium">Nombre Receptor</th> // después <SortableHeader label="Nombre Emisor" active={getSortIndicator('emisor')} onClick={() => toggleSort('emisor')} /> <SortableHeader label="Nombre Receptor" active={getSortIndicator('receptor')} onClick={() => toggleSort('receptor')} /> -
Mantener el
initialKey = 'fecha'yinitialDir = 'desc'(default actual).
No-cambios
- No se tocan:
useTableSort,SortableHeader, ni cualquier otro archivo en@horux/shared-ui. - No se tocan controllers ni services del API. El sort es 100% client-side.
- No se tocan las columnas RFC Emisor, RFC Receptor, UUID, Comp., M. Pago,
Reg. E ni Reg. R — siguen siendo
<th>planos no ordenables. - No se modifica el export a Excel: ya consume
sortedData, así que el orden vigente del usuario se respeta automáticamente.
Comportamiento esperado
- Click sobre "Nombre Emisor": ordena ascendente por nombre. Re-click: descendente. Cambia el sort activo (un solo sort a la vez, ya es el contrato del hook).
- Click sobre "Nombre Receptor": idéntico, reemplaza al sort previo.
- Filas con
nombreEmisoronombreReceptornull/undefined: el accesor retorna string vacío'', así que enascaparecen primero. Es el comportamiento estándar delocaleComparey se considera aceptable (un CFDI sin nombre emisor/receptor es raro y debería ser visible al ordenar por nombre).
Riesgo
Mínimo:
- Cambio puramente client-side, una sola página, ~6 líneas netas.
- No introduce dependencias nuevas.
pnpm typecheckdebería seguir limpio (las nuevas keys están dentro del union genérico, los accesores cumplen el contrato(row: T) => number | string).
Plan de pruebas (smoke)
pnpm typecheckdebe seguir en 0 errores.- Abrir
/drill-downdesde cualquier KPI del dashboard. - Click en "Nombre Emisor" → verificar orden alfabético ascendente y flecha en el header. Re-click → descendente.
- Click en "Nombre Receptor" → mismo comportamiento.
- Click en "Fecha" / "Total MXN" → confirmar que los sorts pre-existentes siguen funcionando.
- Exportar a Excel después de ordenar por "Nombre Emisor" → confirmar que el archivo descargado mantiene el mismo orden.
Pendientes derivados
- Replicar el patrón en las 9 páginas de
/alertas/*(cancelaciones, cancelaciones-periodo-anterior, efectivo, tipo-relacion-sospechosa, concentracion-clientes, concentracion-proveedores, discrepancia-regimen, lista-negra-clientes, lista-negra-proveedores). Decisión del owner cuándo abordarlas. Paralista-negra-*además habrá que introduciruseTableSortdesde cero (hoy no lo usan).