feat(mejoras): 22 mejoras UX en todos los módulos

Mi día: cancelación con motivo, conteo escrituración real, cita sin retroceder, calendario completo
Cobranza: MoraDashboard respeta alcance, hoy dinámico, cancelar con motivo
Landing: contactos paginados, error vs vacío diferenciado
Dashboards: KPI renombrado, drill-down planes activos
Chat: historial recarga, preguntas rotativas, error solo toast
Transversal: shadow-sm corrupto corregido en 9 archivos

553 API tests + 7 apps construidas
This commit is contained in:
2026-09-11 12:48:47 +00:00
parent 89d95eb53b
commit 1ba7aa49da
28 changed files with 518 additions and 160 deletions

View File

@@ -85,7 +85,7 @@ describe('listarContactosLocal', () => {
capturaFake({ leadId: 'loc_1', nombreLead: 'ANA DEMO', telefono: '6649998877', etapa: 'Pago Apartado', board: 'APARTADO' }),
])
const lista = await listarContactosLocal()
const lista = (await listarContactosLocal()).contactos
expect(lista).toHaveLength(2)
expect(lista[0]).toMatchObject({
@@ -113,10 +113,34 @@ describe('listarContactosLocal', () => {
capturaFake({ leadId: 'loc_1', telefono: '4771234567' }),
])
const lista = await listarContactosLocal()
const lista = (await listarContactosLocal()).contactos
expect(lista).toHaveLength(1)
expect(lista[0]?.id).toBe('c1')
})
it('pagina de 100 en 100 con hayMas (la página 2 trae el siguiente bloque)', async () => {
// 101 clientes: la página 1 llena 100 y detecta que hay más
prismaMock.cliente.findMany.mockResolvedValue(
Array.from({ length: 101 }, (_, i) =>
clienteFake({ id: `c${i + 1}`, celular: `4770000${String(i).padStart(3, '0')}`, createdAt: new Date(2026, 8, 1, 0, 0, 0, i * 1000) }),
),
)
const pagina1 = await listarContactosLocal(undefined, 1)
expect(pagina1.pagina).toBe(1)
expect(pagina1.porPagina).toBe(100)
expect(pagina1.contactos).toHaveLength(100)
expect(pagina1.hayMas).toBe(true)
// La página 2 recibe el siguiente bloque (skip=100, take=101)
prismaMock.cliente.findMany.mockResolvedValue([
clienteFake({ id: 'c101', celular: '4770000100' }),
])
const pagina2 = await listarContactosLocal(undefined, 2)
expect(pagina2.pagina).toBe(2)
expect(pagina2.contactos).toHaveLength(1)
expect(pagina2.hayMas).toBe(false)
})
})
describe('detalleContactoLocal', () => {