feat(cotizador): enganche editable directo en su renglon (min 7.5%, tope 90% de anticipo); se quita el espacio separado de adicional
This commit is contained in:
@@ -16,11 +16,13 @@ interface Props {
|
||||
fechaEntrega?: string | null
|
||||
/** Tope de mensualidades: los meses que faltan para la entrega (default 36 sin fecha) */
|
||||
maxMensualidades?: number
|
||||
/** Enganche adicional capturado (>= 0) */
|
||||
engancheAdicional: number
|
||||
onEngancheAdicional: (v: number) => void
|
||||
/** Máximo de enganche adicional permitido por el tope del 90% de anticipo */
|
||||
engancheAdicionalMaximo: number
|
||||
/** Enganche base del esquema (7.5% del precio, neto del excedente del apartado) */
|
||||
engancheBase: number
|
||||
/** Enganche total capturado (base + extra); el input vive en el renglón del enganche */
|
||||
engancheTotal: number
|
||||
onEngancheTotal: (v: number) => void
|
||||
/** Máximo de enganche total permitido por el tope del 90% de anticipo */
|
||||
engancheMax: number
|
||||
numMensualidades: number
|
||||
onNumMensualidades: (n: number) => void
|
||||
escrituracionDiferida: boolean
|
||||
@@ -44,9 +46,10 @@ export function EsquemaPanel({
|
||||
esquema,
|
||||
fechaEntrega,
|
||||
maxMensualidades = MENSUALIDADES_MAX,
|
||||
engancheAdicional,
|
||||
onEngancheAdicional,
|
||||
engancheAdicionalMaximo,
|
||||
engancheBase,
|
||||
engancheTotal,
|
||||
onEngancheTotal,
|
||||
engancheMax,
|
||||
numMensualidades,
|
||||
onNumMensualidades,
|
||||
escrituracionDiferida,
|
||||
@@ -116,10 +119,24 @@ export function EsquemaPanel({
|
||||
)}
|
||||
<div className="flex flex-col gap-1 py-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<dt className="text-sm text-[#64748B] dark:text-[#94A3B8]">
|
||||
Enganche ({formatoPorcentaje(PCT_ENGANCHE)}) diferible
|
||||
Enganche diferible
|
||||
<span className="mt-0.5 block text-xs font-normal text-[#64748B] dark:text-[#94A3B8]">
|
||||
Mín. {formatoPorcentaje(PCT_ENGANCHE)} del precio; puedes subirlo hasta el tope del{' '}
|
||||
{formatoPorcentaje(PCT_ENGANCHE_MAXIMO)} de anticipo total
|
||||
</span>
|
||||
</dt>
|
||||
<dd className="text-sm font-medium text-[#111827] dark:text-[#E2E8F0]">
|
||||
{formatoMoneda(esquema.enganche)}
|
||||
<dd className="flex items-center gap-1.5">
|
||||
<span className="text-sm text-[#64748B] dark:text-[#94A3B8]">$</span>
|
||||
<input
|
||||
id="enganche-diferible"
|
||||
type="number"
|
||||
min={engancheBase}
|
||||
max={engancheMax}
|
||||
step={1000}
|
||||
value={Math.round(engancheTotal)}
|
||||
onChange={(e) => onEngancheTotal(e.target.value === '' ? engancheBase : Number(e.target.value))}
|
||||
className="w-36 rounded-lg border border-[#D1D5DB] bg-white px-3 py-1.5 text-right text-sm font-medium text-[#111827] transition-colors focus:border-accent focus:ring-2 focus:ring-accent/20 focus:outline-none dark:bg-[#0F172A] dark:border-[#334155] dark:text-[#E2E8F0]"
|
||||
/>
|
||||
</dd>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 py-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
@@ -135,20 +152,15 @@ export function EsquemaPanel({
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 py-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<dt className="text-sm font-semibold text-[#111827] dark:text-[#E2E8F0]">
|
||||
Total del esquema (15.5% del precio)
|
||||
Total del esquema
|
||||
<span className="ml-2 text-xs font-normal text-[#64748B] dark:text-[#94A3B8]">
|
||||
{formatoPorcentaje(esquema.totalPagado / esquema.precio)} del precio
|
||||
</span>
|
||||
</dt>
|
||||
<dd className="text-sm font-semibold text-[#111827] dark:text-[#E2E8F0]">
|
||||
{formatoMoneda(esquema.totalPagado)}
|
||||
</dd>
|
||||
</div>
|
||||
{esquema.engancheAdicional > 0 && (
|
||||
<div className="flex flex-col gap-1 py-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<dt className="text-sm text-[#64748B] dark:text-[#94A3B8]">Enganche adicional</dt>
|
||||
<dd className="text-sm font-medium text-[#111827] dark:text-[#E2E8F0]">
|
||||
{formatoMoneda(esquema.engancheAdicional)}
|
||||
</dd>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-1 py-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<dt className="text-sm font-semibold text-[#111827] dark:text-[#E2E8F0]">
|
||||
Saldo a financiar
|
||||
@@ -163,31 +175,6 @@ export function EsquemaPanel({
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
{/* Enganche adicional: anticipo extra hasta completar 90% del precio */}
|
||||
<section className="rounded-xl border border-[#E5E7EB] bg-white p-6 dark:border-[#1E293B] dark:bg-[#1E293B] shadow-sm">
|
||||
<label htmlFor="enganche-adicional" className="mb-2 block text-xs font-medium text-[#4B5563] dark:text-[#CBD5E1]">
|
||||
Enganche adicional (opcional)
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-[#64748B] dark:text-[#94A3B8]">$</span>
|
||||
<input
|
||||
id="enganche-adicional"
|
||||
type="number"
|
||||
min={0}
|
||||
max={engancheAdicionalMaximo}
|
||||
step={1000}
|
||||
value={engancheAdicional === 0 ? '' : engancheAdicional}
|
||||
placeholder="0"
|
||||
onChange={(e) => onEngancheAdicional(e.target.value === '' ? 0 : Number(e.target.value))}
|
||||
className="w-full rounded-lg border border-[#D1D5DB] bg-white px-3 py-2.5 text-sm transition-colors focus:border-accent focus:ring-2 focus:ring-accent/20 focus:outline-none dark:bg-[#0F172A] dark:border-[#334155] dark:text-[#E2E8F0]"
|
||||
/>
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-[#64748B] dark:text-[#94A3B8]">
|
||||
Anticipo extra del cliente; máximo {formatoMoneda(engancheAdicionalMaximo)} para no pasar del{' '}
|
||||
{formatoPorcentaje(PCT_ENGANCHE_MAXIMO)} de enganche total (queda un mínimo del 10% por financiar)
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Controles del diferimiento */}
|
||||
<section className="flex flex-col gap-4 rounded-xl border border-[#E5E7EB] bg-white p-6 dark:border-[#1E293B] dark:bg-[#1E293B] shadow-sm sm:flex-row sm:items-end">
|
||||
<div className="flex-1">
|
||||
|
||||
@@ -792,9 +792,14 @@ export default function CotizadorPage() {
|
||||
esquema={resultado}
|
||||
fechaEntrega={unidad?.fechaEntrega ?? null}
|
||||
maxMensualidades={unidad ? mensualidadesParaUnidad(unidad) : MENSUALIDADES_MAX}
|
||||
engancheAdicional={engancheAdicional}
|
||||
onEngancheAdicional={setEngancheAdicional}
|
||||
engancheAdicionalMaximo={engancheAdicionalMaximo}
|
||||
engancheBase={resultado.enganche}
|
||||
engancheTotal={resultado.enganche + engancheAdicional}
|
||||
onEngancheTotal={(v) =>
|
||||
setEngancheAdicional(
|
||||
Math.min(Math.max(0, v - resultado.enganche), engancheAdicionalMaximo),
|
||||
)
|
||||
}
|
||||
engancheMax={resultado.enganche + engancheAdicionalMaximo}
|
||||
numMensualidades={numMensualidades}
|
||||
onNumMensualidades={setNumMensualidades}
|
||||
escrituracionDiferida={escrituracionDiferida}
|
||||
|
||||
Reference in New Issue
Block a user