feat(9-mejoras): limpieza leads + admin CRUD + calendario + CRM360 FRASA
1. Leads limpiados (207 eliminados, 18 apartados conservados) 2. Round-robin desactivado (config round_robin_habilitado=false) 3. Admin puede borrar/reasignar/mover leads (DELETE/PATCH/POST) 4. Calendario: fechaCita guardada y pasada correctamente 5. Avisos Monday eliminados (BannerModoLocal, ChipPendienteSync, vinculación) 6. Contactos filtrados por usuario asignado 7. Modal bitácora: notas persisten entre fases 8. Fases oportunidades: Agendo→Afluencia→Cotizar→Aparto 9. Toast de nota eliminado en cambios de status 10. Branding: CRM360 FRASA + logo en todas las apps 11. 7 apps construidas
This commit is contained in:
@@ -117,6 +117,8 @@ export interface OportunidadMiDia {
|
||||
updatedAt: string
|
||||
/** Último evento del activity log del board; null si el item no tiene eventos */
|
||||
ultimoCambio: { fechaISO: string; usuario: string | null; detalle: string } | null
|
||||
/** Fecha y hora de la cita agendada (ej. '2026-09-10T14:30' o '2026-09-10') */
|
||||
fechaCita?: string | undefined
|
||||
/** true = captura local aún no sincronizada a Monday (badge ⏳ del front; aditivo) */
|
||||
pendienteSync?: boolean
|
||||
}
|
||||
@@ -319,6 +321,7 @@ export async function resumenMiDia(
|
||||
unidadCodigo: o.unidadCodigo,
|
||||
updatedAt: o.updatedAt,
|
||||
ultimoCambio: null,
|
||||
fechaCita: o.fechaCita,
|
||||
}))
|
||||
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
||||
|
||||
@@ -681,11 +684,13 @@ export function resumenMiDiaLocal(
|
||||
.filter((c) => !esEtapaTerminal(c.etapa))
|
||||
.map((c) => {
|
||||
let unidadCodigo = ''
|
||||
let fechaCita: string | undefined
|
||||
if (c.datosJson) {
|
||||
try {
|
||||
const datos = JSON.parse(c.datosJson) as Record<string, unknown>
|
||||
if (typeof datos.unidadCodigo === 'string' && datos.unidadCodigo !== '') unidadCodigo = datos.unidadCodigo
|
||||
else if (typeof datos.desarrollo === 'string' && datos.desarrollo !== '') unidadCodigo = datos.desarrollo
|
||||
if (typeof datos.fechaCita === 'string') fechaCita = datos.fechaCita
|
||||
} catch { /* datosJson corrupto: ignorar */ }
|
||||
}
|
||||
return {
|
||||
@@ -699,6 +704,7 @@ export function resumenMiDiaLocal(
|
||||
unidadCodigo,
|
||||
updatedAt: c.updatedAt.toISOString(),
|
||||
ultimoCambio: ultimoCambioLocal(c, usuario.nombre),
|
||||
fechaCita,
|
||||
pendienteSync: c.pendienteSync,
|
||||
}
|
||||
})
|
||||
@@ -962,6 +968,7 @@ export function unirPendientesLocales(
|
||||
unidadCodigo: '',
|
||||
updatedAt: p.updatedAt.toISOString(),
|
||||
ultimoCambio: ultimoCambioLocal(p, nombreUsuario),
|
||||
fechaCita: (() => { try { const d = JSON.parse(p.datosJson ?? '{}') as Record<string, unknown>; return typeof d.fechaCita === 'string' ? d.fechaCita : undefined } catch { return undefined } })(),
|
||||
pendienteSync: true,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user