fix(afluencia): dropdowns salarios + lo quiere para + redirect Mi día
- Rango salarial: input → select con 14 rangos (A-0 a M-100001) - Lo quiere para: input → select con 2 opciones (Vivir / Inversión) - Validación labels origen/desarrollo tolerante en backend (omitir si no existe) - Redirect a /hoy/ después de crear afluencia o completar alta cliente
This commit is contained in:
@@ -291,17 +291,23 @@ export async function crearAfluencia(
|
|||||||
if (existente) return { duplicado: { id: existente.id, nombre: existente.nombre } }
|
if (existente) return { duplicado: { id: existente.id, nombre: existente.nombre } }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datos.origen !== undefined) {
|
// Validación tolerante: si el label no existe en el board, se omite en vez
|
||||||
|
// de fallar. Esto evita 400 cuando Monday aún no propagó un label nuevo.
|
||||||
|
let origenSafe = datos.origen
|
||||||
|
if (origenSafe !== undefined) {
|
||||||
const labels = await monday.labelsDeColumna(boardOportunidades, 'Origen del Lead')
|
const labels = await monday.labelsDeColumna(boardOportunidades, 'Origen del Lead')
|
||||||
if (!labels.includes(datos.origen)) {
|
if (!labels.includes(origenSafe)) {
|
||||||
throw new AppError(400, `Origen inválido: "${datos.origen}". Labels válidos: ${labels.join(', ')}`)
|
console.warn(`Origen "${origenSafe}" no es label del board; se omite`)
|
||||||
|
origenSafe = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datos.desarrollo !== undefined) {
|
let desarrolloSafe = datos.desarrollo
|
||||||
|
if (desarrolloSafe !== undefined) {
|
||||||
const labels = await monday.labelsDeColumna(boardOportunidades, 'Desarrollo')
|
const labels = await monday.labelsDeColumna(boardOportunidades, 'Desarrollo')
|
||||||
if (!labels.includes(datos.desarrollo)) {
|
if (!labels.includes(desarrolloSafe)) {
|
||||||
throw new AppError(400, `Desarrollo inválido: "${datos.desarrollo}". Labels válidos: ${labels.join(', ')}`)
|
console.warn(`Desarrollo "${desarrolloSafe}" no es label del board; se omite`)
|
||||||
|
desarrolloSafe = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,8 +315,8 @@ export async function crearAfluencia(
|
|||||||
nombre: datos.nombre,
|
nombre: datos.nombre,
|
||||||
telefono: datos.telefono,
|
telefono: datos.telefono,
|
||||||
email: datos.email,
|
email: datos.email,
|
||||||
desarrolloLabel: datos.desarrollo,
|
desarrolloLabel: desarrolloSafe,
|
||||||
origenLabel: datos.origen,
|
origenLabel: origenSafe,
|
||||||
modeloLabel: datos.modelo,
|
modeloLabel: datos.modelo,
|
||||||
medioContacto: datos.medioContacto,
|
medioContacto: datos.medioContacto,
|
||||||
edad: datos.edad,
|
edad: datos.edad,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, type FormEvent } from 'react'
|
import { useEffect, useState, type FormEvent } from 'react'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { crearAfluencia, type LeadResumen } from '../services/api'
|
import { crearAfluencia, type LeadResumen } from '../services/api'
|
||||||
import BusquedaLead from './BusquedaLead'
|
import BusquedaLead from './BusquedaLead'
|
||||||
@@ -189,6 +189,15 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente, valor
|
|||||||
setAsignacion(null)
|
setAsignacion(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redirigir a Mi día 2 s después de registrar la afluencia
|
||||||
|
useEffect(() => {
|
||||||
|
if (leadCreado === null) return
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
window.location.href = '/hoy/'
|
||||||
|
}, 2000)
|
||||||
|
return () => clearTimeout(timer)
|
||||||
|
}, [leadCreado])
|
||||||
|
|
||||||
if (leadCreado !== null) {
|
if (leadCreado !== null) {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-md">
|
<div className="max-w-md">
|
||||||
@@ -202,6 +211,9 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente, valor
|
|||||||
? 'Registrado en afluencia — asignado a ti'
|
? 'Registrado en afluencia — asignado a ti'
|
||||||
: 'Registrado en afluencia — se asignará por round-robin'}
|
: 'Registrado en afluencia — se asignará por round-robin'}
|
||||||
</p>
|
</p>
|
||||||
|
<p className="mt-2 text-xs text-[#64748B] dark:text-[#94A3B8]">
|
||||||
|
Redirigiendo a Mi día en unos segundos…
|
||||||
|
</p>
|
||||||
<div className="mt-6 flex flex-wrap gap-3">
|
<div className="mt-6 flex flex-wrap gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -427,13 +439,27 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente, valor
|
|||||||
|
|
||||||
<label htmlFor="afluencia-rango-salarial" className="block">
|
<label htmlFor="afluencia-rango-salarial" className="block">
|
||||||
<span className={labelClase}>Rango salarial</span>
|
<span className={labelClase}>Rango salarial</span>
|
||||||
<input
|
<select
|
||||||
id="afluencia-rango-salarial"
|
id="afluencia-rango-salarial"
|
||||||
type="text"
|
|
||||||
value={form.rangoSalarial}
|
value={form.rangoSalarial}
|
||||||
onChange={cambiar('rangoSalarial')}
|
onChange={cambiar('rangoSalarial')}
|
||||||
className={inputClase}
|
className={inputClase}
|
||||||
/>
|
>
|
||||||
|
<option value="">— Selecciona —</option>
|
||||||
|
<option value="A-0-10000.00">A-0-10000.00</option>
|
||||||
|
<option value="B-10000.01-15000.00">B-10000.01-15000.00</option>
|
||||||
|
<option value="C-15000.01-20000.00">C-15000.01-20000.00</option>
|
||||||
|
<option value="D-17000.01-22000.00">D-17000.01-22000.00</option>
|
||||||
|
<option value="E-20001.00-25000.00">E-20001.00-25000.00</option>
|
||||||
|
<option value="F-25001.00-30000.00">F-25001.00-30000.00</option>
|
||||||
|
<option value="G-30001.00-35000.00">G-30001.00-35000.00</option>
|
||||||
|
<option value="H-35001.00-40000.00">H-35001.00-40000.00</option>
|
||||||
|
<option value="I-40001.00-45000.00">I-40001.00-45000.00</option>
|
||||||
|
<option value="J-45001.00-50000.00">J-45001.00-50000.00</option>
|
||||||
|
<option value="K-50001.00-75000.00">K-50001.00-75000.00</option>
|
||||||
|
<option value="L-75001.00-100000.00">L-75001.00-100000.00</option>
|
||||||
|
<option value="M-100001.00-500000.00">M-100001.00-500000.00</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label htmlFor="afluencia-credito" className="block">
|
<label htmlFor="afluencia-credito" className="block">
|
||||||
@@ -489,13 +515,16 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente, valor
|
|||||||
|
|
||||||
<label htmlFor="afluencia-lo-quiere-para" className="block">
|
<label htmlFor="afluencia-lo-quiere-para" className="block">
|
||||||
<span className={labelClase}>Lo quiere para</span>
|
<span className={labelClase}>Lo quiere para</span>
|
||||||
<input
|
<select
|
||||||
id="afluencia-lo-quiere-para"
|
id="afluencia-lo-quiere-para"
|
||||||
type="text"
|
|
||||||
value={form.loQuierePara}
|
value={form.loQuierePara}
|
||||||
onChange={cambiar('loQuierePara')}
|
onChange={cambiar('loQuierePara')}
|
||||||
className={inputClase}
|
className={inputClase}
|
||||||
/>
|
>
|
||||||
|
<option value="">— Selecciona —</option>
|
||||||
|
<option value="Para vivir">Para vivir</option>
|
||||||
|
<option value="Para inversión">Para inversión</option>
|
||||||
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label htmlFor="afluencia-notas" className="block sm:col-span-2">
|
<label htmlFor="afluencia-notas" className="block sm:col-span-2">
|
||||||
|
|||||||
@@ -308,6 +308,15 @@ export default function AltaClientePage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redirigir a Mi día después de completar el alta
|
||||||
|
useEffect(() => {
|
||||||
|
if (!registro) return
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
window.location.href = '/hoy/'
|
||||||
|
}, 2000)
|
||||||
|
return () => clearTimeout(timer)
|
||||||
|
}, [registro])
|
||||||
|
|
||||||
// Genera la liga pública y copia al portapapeles el texto listo para WhatsApp
|
// Genera la liga pública y copia al portapapeles el texto listo para WhatsApp
|
||||||
const generarLiga = async () => {
|
const generarLiga = async () => {
|
||||||
setErrorLiga('')
|
setErrorLiga('')
|
||||||
@@ -635,6 +644,11 @@ export default function AltaClientePage() {
|
|||||||
Alta registrada en el servidor: {registro}
|
Alta registrada en el servidor: {registro}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
{registro && (
|
||||||
|
<p className="mb-6 text-xs text-[#64748B] dark:text-[#94A3B8]">
|
||||||
|
Redirigiendo a Mi día en unos segundos…
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
{sinConexion && (
|
{sinConexion && (
|
||||||
<p
|
<p
|
||||||
role="alert"
|
role="alert"
|
||||||
|
|||||||
Reference in New Issue
Block a user