feat(8-mejoras): cancelar+motivo, brocker, etapas, calendario, modal cliente

1. Cancelar con motivo: Mis apartados y Escrituración piden motivo (modal reutilizado)
2. Origen BROCKER agregado en alta afluencia y captura rápida
3. Etapas oportunidades reordenadas: Agendo Cita → Afluencia → Cotizador
4. Cotizador: mensualidades diferibles (6, 12, 14, 18, 24 meses)
5. Calendario semanal por vendedor en Mi día
6. Hora en citas (datetime-local en vez de solo fecha)
7. Click en nombre → modal DetalleLeadModal (info + notas + historial)
This commit is contained in:
2026-09-09 10:26:36 +00:00
parent 6db9662838
commit d546460ba4
11 changed files with 808 additions and 26 deletions

View File

@@ -38,6 +38,10 @@ interface UseCotizacionResult {
propuestaIndex: number
setPropuestaIndex: (i: number) => void
precioLista: number
/** Número de mensualidades elegido por el vendedor; null = usa el calculado */
numMensualidades: number | null
setNumMensualidades: (n: number | null) => void
/** Número efectivo de mensualidades (la elegida o la calculada) */
numMeses: number | null
propuestas: PropuestaResultado[]
/** Restaura el estado completo desde una cotización guardada (historial) */
@@ -66,6 +70,7 @@ export function useCotizacion(): UseCotizacionResult {
const [enganchePct, setEnganchePct] = useState<number | null>(null)
const [descuentos, setDescuentos] = useState<DescuentosPropuestas>(descuentosDefault(DESARROLLO_DEFAULT))
const [propuestaIndex, setPropuestaIndex] = useState(0)
const [numMensualidades, setNumMensualidades] = useState<number | null>(null)
const params = obtenerDesarrollo(desarrollo)
@@ -75,6 +80,7 @@ export function useCotizacion(): UseCotizacionResult {
setAcabados(false)
setDescuentos(descuentosDefault(id))
setPropuestaIndex(0)
setNumMensualidades(null)
}
const setDescuento = (clave: keyof DescuentosPropuestas, valor: number) => {
@@ -103,13 +109,17 @@ export function useCotizacion(): UseCotizacionResult {
setEnganchePct(null)
setDescuentos(descuentosDefault(desarrollo))
setPropuestaIndex(0)
setNumMensualidades(null)
}
const numMeses = useMemo(
const numMesesCalculado = useMemo(
() => (unidad ? resolverNumMensualidades(unidad, params) : null),
[unidad, params],
)
/** Número efectivo de mensualidades: la elegida por el vendedor, o la calculada */
const numMeses = numMensualidades ?? numMesesCalculado
const precioLista = useMemo(
() => (unidad ? obtenerPrecioLista(unidad, acabados) : 0),
[unidad, acabados],
@@ -125,8 +135,8 @@ export function useCotizacion(): UseCotizacionResult {
const propuestas = useMemo(() => {
if (!unidad) return []
return calcularPropuestas({ unidad, acabados, apartado: apartadoEfectivo, descuentos, desarrollo, enganchePct: engancheEfectivo })
}, [unidad, acabados, apartadoEfectivo, descuentos, desarrollo, engancheEfectivo])
return calcularPropuestas({ unidad, acabados, apartado: apartadoEfectivo, descuentos, desarrollo, enganchePct: engancheEfectivo, numMeses: numMeses ?? undefined })
}, [unidad, acabados, apartadoEfectivo, descuentos, desarrollo, engancheEfectivo, numMeses])
return {
desarrollo,
@@ -148,6 +158,8 @@ export function useCotizacion(): UseCotizacionResult {
propuestaIndex,
setPropuestaIndex,
precioLista,
numMensualidades,
setNumMensualidades,
numMeses,
propuestas,
restaurar,