feat(mi-dia): botón Afluencia abre el formulario prellenado y actualiza la oportunidad

- Mis oportunidades: 'Afluencia →' navega a /client/?afluencia=<id> con
  nombre, contacto, desarrollo y modelo prellenados
- Alta Afluencia: con oportunidadId el envío ACTUALIZA la oportunidad en
  Monday (perfil completo + etapa Afluencia) en vez de crear duplicado;
  sin oportunidadId el flujo de captura nueva no cambia
- monday.service: actualizarOportunidadAfluencia (mismo builder de la
  creación + name); moverAGrupoSegunEstado tras actualizar
- Tests: 457 API + 16 mi-dia + 116 alta-clientes, verde
This commit is contained in:
2026-09-04 22:53:21 +00:00
parent cbd50e2066
commit 5d7c6f58cd
9 changed files with 266 additions and 22 deletions

View File

@@ -14,6 +14,7 @@ import {
ORIGENES_LEAD,
SLOTS_DOCS_APARTADO,
textoDiasRestantes,
urlAfluenciaParaOportunidad,
urlCotizadorParaOportunidad,
type ApartadoMiDia,
type FaseApartado,
@@ -139,18 +140,22 @@ function FilaOportunidad({
op,
onEtapa,
onCotizar,
onAfluencia,
onDescartar,
enviando,
}: {
op: OportunidadMiDia
onEtapa: (etapa: string, fecha?: string) => void
onCotizar: () => void
onAfluencia: () => void
onDescartar: () => void
enviando: boolean
}) {
const [conCita, setConCita] = useState(false)
const [fechaCita, setFechaCita] = useState('')
const fases = ['Agendo Cita', 'Afluencia', 'Aparto', 'No Asistio', 'Abandono'] as const
// 'Afluencia' no es un cambio de etapa directo: abre el formulario de
// afluencia prellenado para capturar/actualizar el perfil completo
const fases = ['Agendo Cita', 'Aparto', 'No Asistio', 'Abandono'] as const
return (
<li className="rounded-xl border border-[#E5E7EB] bg-white p-4 shadow-sm">
<div className="flex flex-wrap items-center justify-between gap-3">
@@ -183,6 +188,15 @@ function FilaOportunidad({
>
Cotizar →
</button>
{/* Afluencia: abre el formulario de alta afluencia prellenado */}
<button
type="button"
disabled={enviando}
onClick={onAfluencia}
className="rounded-lg border border-accent bg-white px-3 py-1.5 text-xs font-medium text-accent shadow-sm transition-all duration-100 ease-out hover:bg-accent hover:text-white disabled:opacity-50"
>
Afluencia →
</button>
{fases.map((f) =>
f === 'Agendo Cita' ? (
<span key={f} className="contents">
@@ -771,6 +785,9 @@ export default function MiDiaPage({ accionesSesion }: { accionesSesion: Acciones
void ejecutar(() => cambiarEtapaOportunidad(op.id, etapa, fecha), 'No se pudo actualizar la oportunidad')
}
onCotizar={() => void cotizarOportunidad(op)}
onAfluencia={() => {
window.location.href = urlAfluenciaParaOportunidad(op)
}}
onDescartar={() => setDescartando({ id: op.id, nombre: op.nombre, fuente: 'oportunidad' })}
/>
))}