"use client"; /** * ConceptParamsForm — controlled form for the ConceptInput parameters * (housing_class / target_floors / development_type / land_cost_rub). The * parcel polygon is collected separately by the map; this form owns only the * scalar fields and the submit CTA. Submit is disabled until the parent * confirms a polygon is present (`hasPolygon`). */ import { Sparkles } from "lucide-react"; import { DEVELOPMENT_TYPE_LABELS, HOUSING_CLASS_LABELS, type DevelopmentType, type HousingClass, } from "@/lib/concept-api"; export interface ConceptParams { housing_class: HousingClass; target_floors: number; development_type: DevelopmentType; land_cost_rub: number | null; } export const DEFAULT_PARAMS: ConceptParams = { housing_class: "comfort", target_floors: 9, development_type: "mid_rise", land_cost_rub: null, }; const fieldLabelStyle: React.CSSProperties = { display: "block", fontSize: 12, fontWeight: 500, textTransform: "uppercase", letterSpacing: "0.04em", color: "var(--fg-secondary)", marginBottom: 6, }; const controlStyle: React.CSSProperties = { width: "100%", padding: "8px 12px", fontSize: 14, border: "1px solid var(--border-strong)", borderRadius: 8, outline: "none", background: "var(--bg-card)", color: "var(--fg-primary)", }; interface Props { params: ConceptParams; onChange: (params: ConceptParams) => void; onSubmit: () => void; hasPolygon: boolean; isPending: boolean; } export function ConceptParamsForm({ params, onChange, onSubmit, hasPolygon, isPending, }: Props) { function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!hasPolygon || isPending) return; onSubmit(); } const disabled = !hasPolygon || isPending; return (
{ const raw = Number(e.target.value); const clamped = Number.isFinite(raw) ? Math.min(30, Math.max(1, Math.round(raw))) : 1; onChange({ ...params, target_floors: clamped }); }} style={controlStyle} />

От 1 до 30 этажей.

{ const raw = e.target.value.trim(); const value = raw === "" ? null : Number(raw); onChange({ ...params, land_cost_rub: value != null && Number.isFinite(value) && value >= 0 ? value : null, }); }} style={controlStyle} />

Учитывается в финансовой модели как часть затрат.

{!hasPolygon && (

Нарисуйте полигон участка или укажите кадастровый номер, чтобы начать расчёт.

)}
); }