Four frontend display fixes for the Site Finder analysis report (audit #1953); all consume fields the (already-deployed) backend now returns. - #1954: ЕГРН «Обременения» row was hardcoded «—». Wire top-level `encumbrance` block {has_zouit, zouit_count, zouit_types} via formatEncumbrance → «ЗОУИТ: N (types)» / «не выявлено (НСПД)». - #1955: show obj_class per success bucket («Студии 15-30 · Комфорт») so rows with identical area-labels are distinct; fix top-row match + React key to (bucket, obj_class). - #1957: NspdZouitOverlapsBlock renders human type_zone + reg_numb_border, adds a СЗЗ caveat banner (СанПиН 2.2.1/2.1.1.1200-03) and «СЗЗ вашего участка» highlight; switched raw hex to UI tokens. - #1958: ForecastChart axis names → nameLocation:middle + nameGap (no legend overlap); grey flat-state callout when the deficit line is degenerate (scenarios_collapsed or all points clamped at ±1). Tests: formatEncumbrance + isDeficitDegenerate (15 new). Real segment differentiation is backend #1959 (separate).
148 lines
5.1 KiB
TypeScript
148 lines
5.1 KiB
TypeScript
"use client";
|
||
|
||
import type { ParcelAnalysis } from "@/types/site-finder";
|
||
import { SectionLabel } from "@/components/ui/SectionLabel";
|
||
import { EmptyState } from "@/components/ui/EmptyState";
|
||
import { GeologyBlock } from "./GeologyBlock";
|
||
import { GeometrySuitabilityBlock } from "./GeometrySuitabilityBlock";
|
||
import { GeotechRiskBlock } from "./GeotechRiskBlock";
|
||
import { NeighborsBlock } from "./NeighborsBlock";
|
||
import { NspdZoningBlock } from "./NspdZoningBlock";
|
||
import { NspdZouitOverlapsBlock } from "./NspdZouitOverlapsBlock";
|
||
import { NspdEngineeringNearbyBlock } from "./NspdEngineeringNearbyBlock";
|
||
import { NspdRiskZonesBlock } from "./NspdRiskZonesBlock";
|
||
import { NspdOpportunityBlock } from "./NspdOpportunityBlock";
|
||
import { NspdRedLinesBlock } from "./NspdRedLinesBlock";
|
||
import { NspdFreshnessBadge } from "./NspdFreshnessBadge";
|
||
|
||
interface Props {
|
||
data: ParcelAnalysis;
|
||
}
|
||
|
||
export function LandTab({ data }: Props) {
|
||
const hasAny =
|
||
data.geotech_risk !== undefined ||
|
||
data.geology !== undefined ||
|
||
data.geometry_suitability !== undefined ||
|
||
data.neighbors_summary !== undefined ||
|
||
data.nspd_zoning !== undefined ||
|
||
data.nspd_zouit_overlaps !== undefined ||
|
||
data.nspd_engineering_nearby !== undefined ||
|
||
data.nspd_risk_zones !== undefined ||
|
||
(data.nspd_opportunity_parcels !== undefined &&
|
||
(data.nspd_opportunity_parcels?.length ?? 0) > 0) ||
|
||
(data.nspd_red_lines !== undefined &&
|
||
(data.nspd_red_lines?.length ?? 0) > 0);
|
||
|
||
return (
|
||
<div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
|
||
{/* P2 (#46) — Соседи + overlap warning (hard warn если overlap) */}
|
||
{data.neighbors_summary && (
|
||
<NeighborsBlock data={data.neighbors_summary} />
|
||
)}
|
||
|
||
{/* P1 (#45) — Geometry suitability */}
|
||
{data.geometry_suitability !== undefined && (
|
||
<GeometrySuitabilityBlock data={data.geometry_suitability} />
|
||
)}
|
||
|
||
{/* Issue #202 — Зонирование (ПЗЗ) из НСПД */}
|
||
<div>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 8,
|
||
marginBottom: 10,
|
||
}}
|
||
>
|
||
<SectionLabel>Зонирование (ПЗЗ)</SectionLabel>
|
||
<NspdFreshnessBadge dump={data.nspd_dump} />
|
||
</div>
|
||
<NspdZoningBlock
|
||
data={data.nspd_zoning}
|
||
dump={data.nspd_dump}
|
||
cadNum={data.cad_num}
|
||
/>
|
||
</div>
|
||
|
||
{/* Issue #202 — ЗОУИТ пересечения */}
|
||
{data.nspd_zouit_overlaps !== undefined && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 10 }}>
|
||
Зоны с особыми условиями использования (ЗОУИТ)
|
||
</SectionLabel>
|
||
<NspdZouitOverlapsBlock
|
||
overlaps={data.nspd_zouit_overlaps ?? []}
|
||
parcelCad={data.cad_num}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Issue #94 PR2 TIER 4 — Opportunity parcels */}
|
||
{(data.nspd_opportunity_parcels?.length ?? 0) > 0 && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 10 }}>
|
||
Возможности рядом (НСПД)
|
||
</SectionLabel>
|
||
<NspdOpportunityBlock
|
||
opportunityParcels={data.nspd_opportunity_parcels}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Issue #94 PR2 TIER 4 — Red lines */}
|
||
{(data.nspd_red_lines?.length ?? 0) > 0 && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 10 }}>
|
||
Красные линии застройки (НСПД)
|
||
</SectionLabel>
|
||
<NspdRedLinesBlock redLines={data.nspd_red_lines} />
|
||
</div>
|
||
)}
|
||
|
||
{/* Issue #94 TIER 3 — Риск-зоны НСПД */}
|
||
{data.nspd_risk_zones !== undefined && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 10 }}>
|
||
Природные риски (НСПД)
|
||
</SectionLabel>
|
||
<NspdRiskZonesBlock riskZones={data.nspd_risk_zones} />
|
||
</div>
|
||
)}
|
||
|
||
{/* Issue #202 — Инженерные объекты в 200 м */}
|
||
{data.nspd_engineering_nearby !== undefined && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 10 }}>
|
||
Инженерные объекты вблизи участка
|
||
</SectionLabel>
|
||
<NspdEngineeringNearbyBlock
|
||
nearby={data.nspd_engineering_nearby ?? []}
|
||
cadNum={data.cad_num}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Geotech risk */}
|
||
{data.geotech_risk !== undefined && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 12 }}>
|
||
Геотехнический риск
|
||
</SectionLabel>
|
||
<GeotechRiskBlock risk={data.geotech_risk} />
|
||
</div>
|
||
)}
|
||
|
||
{/* Geology */}
|
||
{data.geology !== undefined && (
|
||
<div>
|
||
<SectionLabel style={{ marginBottom: 12 }}>Геология</SectionLabel>
|
||
<GeologyBlock geology={data.geology} />
|
||
</div>
|
||
)}
|
||
|
||
{!hasAny && <EmptyState message="Данные о земле и геологии недоступны" />}
|
||
</div>
|
||
);
|
||
}
|