feat(afluencia): captura completa de perfil en alta de afluencia
Agrega al formulario ligero y a POST /api/leads: tipo de propiedad, medio de contacto, edad, estado civil, tipo de empleo, ocupacion, rango salarial, credito, tipo de economia, califica y lo quiere para. Selects obligatorios (estado civil, tipo de empleo, tipo de economia, califica) con las etiquetas sembradas como labels status en el tablero Leads de Monday.
This commit is contained in:
@@ -1,7 +1,16 @@
|
||||
import { useState, type FormEvent } from 'react'
|
||||
import { z } from 'zod'
|
||||
import { crearLead, type LeadResumen } from '../services/api'
|
||||
import { DESARROLLOS_LEAD, ORIGENES_LEAD } from '../data/constantes'
|
||||
import {
|
||||
DESARROLLOS_LEAD,
|
||||
ESTADOS_CIVILES,
|
||||
OPCIONES_CALIFICA,
|
||||
ORIGENES_LEAD,
|
||||
TIPOS_CREDITO,
|
||||
TIPOS_ECONOMIA,
|
||||
TIPOS_EMPLEO,
|
||||
TIPOS_PROPIEDAD_LEAD,
|
||||
} from '../data/constantes'
|
||||
|
||||
interface Props {
|
||||
onVolver: () => void
|
||||
@@ -23,7 +32,25 @@ interface Errores {
|
||||
email?: string
|
||||
}
|
||||
|
||||
const FORM_INICIAL = { nombre: '', telefono: '', email: '', origen: '', desarrollo: '', notas: '' }
|
||||
const FORM_INICIAL = {
|
||||
nombre: '',
|
||||
telefono: '',
|
||||
email: '',
|
||||
origen: '',
|
||||
desarrollo: '',
|
||||
tipoPropiedad: '',
|
||||
medioContacto: '',
|
||||
edad: '',
|
||||
estadoCivil: '',
|
||||
tipoEmpleo: '',
|
||||
ocupacion: '',
|
||||
rangoSalarial: '',
|
||||
credito: '',
|
||||
tipoEconomia: '',
|
||||
califica: '',
|
||||
loQuierePara: '',
|
||||
notas: '',
|
||||
}
|
||||
|
||||
/**
|
||||
* Captura ligera del interesado al entrar al embudo (POST /leads): crea el
|
||||
@@ -64,6 +91,17 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente }: Pro
|
||||
...(form.email.trim() ? { email: form.email.trim() } : {}),
|
||||
...(form.origen ? { origen: form.origen } : {}),
|
||||
...(form.desarrollo ? { desarrollo: form.desarrollo } : {}),
|
||||
...(form.tipoPropiedad ? { tipoPropiedad: form.tipoPropiedad } : {}),
|
||||
...(form.medioContacto.trim() ? { medioContacto: form.medioContacto.trim() } : {}),
|
||||
...(form.edad.trim() ? { edad: form.edad.trim() } : {}),
|
||||
...(form.estadoCivil ? { estadoCivil: form.estadoCivil } : {}),
|
||||
...(form.tipoEmpleo ? { tipoEmpleo: form.tipoEmpleo } : {}),
|
||||
...(form.ocupacion.trim() ? { ocupacion: form.ocupacion.trim() } : {}),
|
||||
...(form.rangoSalarial.trim() ? { rangoSalarial: form.rangoSalarial.trim() } : {}),
|
||||
...(form.credito ? { credito: form.credito } : {}),
|
||||
...(form.tipoEconomia ? { tipoEconomia: form.tipoEconomia } : {}),
|
||||
...(form.califica ? { califica: form.califica } : {}),
|
||||
...(form.loQuierePara.trim() ? { loQuierePara: form.loQuierePara.trim() } : {}),
|
||||
...(form.notas.trim() ? { notas: form.notas.trim() } : {}),
|
||||
})
|
||||
setEnviando(false)
|
||||
@@ -127,9 +165,9 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente }: Pro
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={(e) => void enviar(e)} noValidate className="max-w-md">
|
||||
<div className="space-y-6">
|
||||
<label htmlFor="afluencia-nombre" className="block">
|
||||
<form onSubmit={(e) => void enviar(e)} noValidate className="max-w-2xl">
|
||||
<div className="grid gap-6 sm:grid-cols-2">
|
||||
<label htmlFor="afluencia-nombre" className="block sm:col-span-2">
|
||||
<span className={labelClase}>
|
||||
Nombre<span className="text-red-700"> *</span>
|
||||
</span>
|
||||
@@ -158,7 +196,7 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente }: Pro
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-email" className="block">
|
||||
<span className={labelClase}>Email</span>
|
||||
<span className={labelClase}>Correo</span>
|
||||
<input
|
||||
id="afluencia-email"
|
||||
type="email"
|
||||
@@ -169,23 +207,6 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente }: Pro
|
||||
{errores.email && <p className="mt-1 text-xs text-red-700">{errores.email}</p>}
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-origen" className="block">
|
||||
<span className={labelClase}>Origen</span>
|
||||
<select
|
||||
id="afluencia-origen"
|
||||
value={form.origen}
|
||||
onChange={cambiar('origen')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{ORIGENES_LEAD.map((o) => (
|
||||
<option key={o} value={o}>
|
||||
{o}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-desarrollo" className="block">
|
||||
<span className={labelClase}>Desarrollo de interés</span>
|
||||
<select
|
||||
@@ -203,7 +224,183 @@ export default function AltaAfluenciaForm({ onVolver, onPasarAAltaCliente }: Pro
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-notas" className="block">
|
||||
<label htmlFor="afluencia-tipo-propiedad" className="block">
|
||||
<span className={labelClase}>Departamento o casa de interés</span>
|
||||
<select
|
||||
id="afluencia-tipo-propiedad"
|
||||
value={form.tipoPropiedad}
|
||||
onChange={cambiar('tipoPropiedad')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{TIPOS_PROPIEDAD_LEAD.map((t) => (
|
||||
<option key={t} value={t}>
|
||||
{t}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-medio-contacto" className="block">
|
||||
<span className={labelClase}>Medio de contacto</span>
|
||||
<input
|
||||
id="afluencia-medio-contacto"
|
||||
type="text"
|
||||
value={form.medioContacto}
|
||||
onChange={cambiar('medioContacto')}
|
||||
className={inputClase}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-origen" className="block">
|
||||
<span className={labelClase}>¿Cómo se enteró de nosotros?</span>
|
||||
<select
|
||||
id="afluencia-origen"
|
||||
value={form.origen}
|
||||
onChange={cambiar('origen')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{ORIGENES_LEAD.map((o) => (
|
||||
<option key={o} value={o}>
|
||||
{o}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-edad" className="block">
|
||||
<span className={labelClase}>Edad</span>
|
||||
<input
|
||||
id="afluencia-edad"
|
||||
type="number"
|
||||
min={15}
|
||||
max={120}
|
||||
value={form.edad}
|
||||
onChange={cambiar('edad')}
|
||||
className={inputClase}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-estado-civil" className="block">
|
||||
<span className={labelClase}>Estado civil</span>
|
||||
<select
|
||||
id="afluencia-estado-civil"
|
||||
value={form.estadoCivil}
|
||||
onChange={cambiar('estadoCivil')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{ESTADOS_CIVILES.map((e) => (
|
||||
<option key={e.valor} value={e.etiqueta}>
|
||||
{e.etiqueta}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-tipo-empleo" className="block">
|
||||
<span className={labelClase}>Tipo de empleo</span>
|
||||
<select
|
||||
id="afluencia-tipo-empleo"
|
||||
value={form.tipoEmpleo}
|
||||
onChange={cambiar('tipoEmpleo')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{TIPOS_EMPLEO.map((t) => (
|
||||
<option key={t.valor} value={t.etiqueta}>
|
||||
{t.etiqueta}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-ocupacion" className="block">
|
||||
<span className={labelClase}>Ocupación</span>
|
||||
<input
|
||||
id="afluencia-ocupacion"
|
||||
type="text"
|
||||
value={form.ocupacion}
|
||||
onChange={cambiar('ocupacion')}
|
||||
className={inputClase}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-rango-salarial" className="block">
|
||||
<span className={labelClase}>Rango salarial</span>
|
||||
<input
|
||||
id="afluencia-rango-salarial"
|
||||
type="text"
|
||||
value={form.rangoSalarial}
|
||||
onChange={cambiar('rangoSalarial')}
|
||||
className={inputClase}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-credito" className="block">
|
||||
<span className={labelClase}>Crédito</span>
|
||||
<select
|
||||
id="afluencia-credito"
|
||||
value={form.credito}
|
||||
onChange={cambiar('credito')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{TIPOS_CREDITO.map((c) => (
|
||||
<option key={c.valor} value={c.etiqueta}>
|
||||
{c.etiqueta}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-tipo-economia" className="block">
|
||||
<span className={labelClase}>Tipo de economía</span>
|
||||
<select
|
||||
id="afluencia-tipo-economia"
|
||||
value={form.tipoEconomia}
|
||||
onChange={cambiar('tipoEconomia')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{TIPOS_ECONOMIA.map((t) => (
|
||||
<option key={t.valor} value={t.etiqueta}>
|
||||
{t.etiqueta}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-califica" className="block">
|
||||
<span className={labelClase}>Califica</span>
|
||||
<select
|
||||
id="afluencia-califica"
|
||||
value={form.califica}
|
||||
onChange={cambiar('califica')}
|
||||
className={inputClase}
|
||||
>
|
||||
<option value="">— Selecciona —</option>
|
||||
{OPCIONES_CALIFICA.map((c) => (
|
||||
<option key={c} value={c}>
|
||||
{c}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-lo-quiere-para" className="block">
|
||||
<span className={labelClase}>Lo quiere para</span>
|
||||
<input
|
||||
id="afluencia-lo-quiere-para"
|
||||
type="text"
|
||||
value={form.loQuierePara}
|
||||
onChange={cambiar('loQuierePara')}
|
||||
className={inputClase}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label htmlFor="afluencia-notas" className="block sm:col-span-2">
|
||||
<span className={labelClase}>Notas</span>
|
||||
<input
|
||||
id="afluencia-notas"
|
||||
|
||||
Reference in New Issue
Block a user