fix(concept): step="any" on number inputs — stepMismatch блокировал submit (#1953)
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 58s
CI / openapi-codegen-check (pull_request) Successful in 1m51s

Поле «Стоимость участка» (ConceptProgramForm §7 + ConceptParamsForm /concept)
имело step={1_000_000}. Сид из кадастровой стоимости (напр. 74 766.08 ₽, не
кратно шагу) → HTML5 stepMismatch → форма :invalid → браузер МОЛЧА блокирует
submit (submit-событие не выстреливает) → кнопка «Рассчитать концепцию» не
работает на ЛЮБОМ участке с кадастровой стоимостью. Авто-расчёт §7 маскировал
баг — он зовёт движок напрямую, минуя валидацию формы.

Тот же латентный stepMismatch на floor_height (step 0.1) и пятне (step 1) —
clampFloat допускает дробные → step="any" и там.

Подтверждено на проде (DOM-патч step="any" → checkValidity()=true → submit
проходит → GFA 15 876→30 240, FAR 0.24→0.45 под изменённое пятно).
This commit is contained in:
Light1YT 2026-06-30 15:06:57 +05:00
parent 975c400536
commit 68f225f794
2 changed files with 11 additions and 5 deletions

View file

@ -163,7 +163,10 @@ export function ConceptParamsForm({
id="land-cost" id="land-cost"
type="number" type="number"
min={0} min={0}
step={1_000_000} // step="any" — произвольная сумма ₽; step={1_000_000} давал HTML5
// stepMismatch на не-кратных значениях → форма :invalid → submit молча
// блокировался (см. ConceptProgramForm fix).
step="any"
value={params.land_cost_rub ?? ""} value={params.land_cost_rub ?? ""}
placeholder="Необязательно" placeholder="Необязательно"
onChange={(e) => { onChange={(e) => {

View file

@ -383,7 +383,7 @@ export function ConceptProgramForm({
<input <input
id="cpf-floor-height" id="cpf-floor-height"
type="number" type="number"
step={0.1} step="any"
min={FLOOR_HEIGHT_MIN} min={FLOOR_HEIGHT_MIN}
max={FLOOR_HEIGHT_MAX} max={FLOOR_HEIGHT_MAX}
value={floorHeight} value={floorHeight}
@ -438,7 +438,7 @@ export function ConceptProgramForm({
aria-label="Ширина пятна секции, м" aria-label="Ширина пятна секции, м"
min={FOOTPRINT_MIN} min={FOOTPRINT_MIN}
max={FOOTPRINT_MAX} max={FOOTPRINT_MAX}
step={1} step="any"
value={effFootprintW ?? ""} value={effFootprintW ?? ""}
disabled={!catalogReady} disabled={!catalogReady}
onChange={(e) => onChange={(e) =>
@ -461,7 +461,7 @@ export function ConceptProgramForm({
aria-label="Глубина пятна секции, м" aria-label="Глубина пятна секции, м"
min={FOOTPRINT_MIN} min={FOOTPRINT_MIN}
max={FOOTPRINT_MAX} max={FOOTPRINT_MAX}
step={1} step="any"
value={effFootprintD ?? ""} value={effFootprintD ?? ""}
disabled={!catalogReady} disabled={!catalogReady}
onChange={(e) => onChange={(e) =>
@ -542,7 +542,10 @@ export function ConceptProgramForm({
id="cpf-land-cost" id="cpf-land-cost"
type="number" type="number"
min={0} min={0}
step={1_000_000} // step="any" — иначе сид из кадастровой стоимости (не кратной шагу,
// напр. 74 766.08 ₽) даёт HTML5 stepMismatch → форма :invalid →
// браузер молча блокирует submit и кнопка «Рассчитать» не работает.
step="any"
value={landCostRub ?? ""} value={landCostRub ?? ""}
placeholder="Необязательно" placeholder="Необязательно"
onChange={(e) => { onChange={(e) => {