feat(mejoras): 25 mejoras UX en todos los módulos + purga Monday

Backend: mi-dia siempre local, vocabulario canónico, AplicacionPago con usuario
Mi día: modal español real, cita desde modal, score falso eliminado
Cotizador: barra sticky, persistencia local con folio
Alta Clientes: redirect eliminado, foto conectada, asesor desde sesión, refs dinámicas
Cobranza: contrato Mora arreglado, link a Plan, abono próximo pago, WhatsApp
Landing: contactos locales, ModalContacto eliminado, ModoTrabajo eliminado
Dashboards: MiTablero unificado, funnel con descartados, drill-down, rango fechas
Chat FRASA: corpus 5 desarrollos, 6 herramientas, historial conversaciones

69 archivos, 7 apps construidas
This commit is contained in:
2026-09-11 06:52:37 +00:00
parent 075d47c304
commit 64b01246d6
69 changed files with 1600 additions and 1133 deletions

View File

@@ -13,6 +13,9 @@ import {
type StorageLike,
} from './repository'
import { ErrorApi } from './api'
// Misma resolución de base que api.ts: el test no depende de la VITE_API_URL local
const API_URL = import.meta.env.VITE_API_URL || '/api'
import type { PlanPago } from '../types'
/** Stub sencillo de localStorage para correr en entorno node */
@@ -120,7 +123,7 @@ describe('repository async (API primero, fallback localStorage)', () => {
expect(plan.tasaMoraMensual).toBeUndefined()
expect(plan).not.toHaveProperty('saldo')
expect(fetchMock).toHaveBeenCalledWith(
'http://192.168.10.123:3000/api/planes',
`${API_URL}/planes`,
expect.objectContaining({ headers: { 'Content-Type': 'application/json' } }),
)
})
@@ -205,7 +208,7 @@ describe('repository async (API primero, fallback localStorage)', () => {
expect(r.plan.id).toBe('api-nuevo')
expect(storage.getItem(CLAVE_STORAGE)).toBeNull()
const [url, init] = fetchMock.mock.calls[0]
expect(url).toBe('http://192.168.10.123:3000/api/planes')
expect(url).toBe(`${API_URL}/planes`)
expect(init?.method).toBe('POST')
const body = JSON.parse(String(init?.body)) as Record<string, unknown>
expect(body.clienteNombre).toBe('Cliente Prueba')
@@ -239,7 +242,7 @@ describe('repository async (API primero, fallback localStorage)', () => {
expect(r.origen).toBe('api')
const [url, init] = fetchMock.mock.calls[0]
expect(url).toBe('http://192.168.10.123:3000/api/planes/api-1/abonos')
expect(url).toBe(`${API_URL}/planes/api-1/abonos`)
const body = JSON.parse(String(init?.body)) as Record<string, unknown>
expect(body).toEqual({ pagoId: 'pago-1', fechaPago: '2026-09-02', monto: 10000, referencia: 'SPEI-1' })
})
@@ -291,7 +294,7 @@ describe('repository async (API primero, fallback localStorage)', () => {
texto: 'Se habló con el cliente',
})
const [url] = fetchMock.mock.calls[0]
expect(url).toBe('http://192.168.10.123:3000/api/planes/api-1/notas')
expect(url).toBe(`${API_URL}/planes/api-1/notas`)
})
it('agregarNotaAsync cae a localStorage cuando falla la red (conserva la validación local)', async () => {
@@ -317,7 +320,7 @@ describe('repository async (API primero, fallback localStorage)', () => {
expect(r.origen).toBe('api')
expect(r.plan.status).toBe('CANCELADO')
const [url, init] = fetchMock.mock.calls[0]
expect(url).toBe('http://192.168.10.123:3000/api/planes/api-1/cancelar')
expect(url).toBe(`${API_URL}/planes/api-1/cancelar`)
expect(init?.method).toBe('POST')
})
@@ -361,7 +364,7 @@ describe('mis cobranzas (toggle Mis planes / Todos)', () => {
expect(r.origen).toBe('api')
expect(fetchMock).toHaveBeenCalledWith(
'http://192.168.10.123:3000/api/planes?mios=1',
`${API_URL}/planes?mios=1`,
expect.objectContaining({ headers: { 'Content-Type': 'application/json' } }),
)
})