"use client";
/**
* MiniMap — compact Leaflet map (≈400px wide) showing parcel polygon + top POI.
* Dynamic import of react-leaflet (ssr:false) to avoid SSR breakage.
* Wraps SiteMap with constrained width for Section 1 layout.
*
* #1218: ранее обёртка имела `height: 320 + overflow: hidden` — это клипало
* legend + CpLayerControlPanel, рендерящиеся flow-div ПОД картой в SiteMap,
* и делало недостижимыми переключатели рыночных слоёв (Будущие проекты,
* Зоны риска, Перспективные ЗУ, Красные линии). Фикс: задаём только ширину,
* высота тайла карты — через prop `mapHeight` SiteMap; контент течёт вниз.
*/
import dynamic from "next/dynamic";
import type { ParcelAnalyzeResponse } from "@/lib/site-finder-api";
import type { ParcelAnalysis } from "@/types/site-finder";
import type { Geometry } from "geojson";
import { useConnectionPoints } from "@/hooks/useConnectionPoints";
// MiniMap высота тайла карты — компромисс между плотностью Section 1 и
// читаемостью. Layer-controls/легенда вне этого размера (flow ниже).
const MINIMAP_HEIGHT = 280;
// Lazy-mount to avoid SSR breakage (Leaflet uses window)
const SiteMap = dynamic(
() =>
import("@/components/site-finder/SiteMap").then((m) => ({
default: m.SiteMap,
})),
{
ssr: false,
loading: () => (
Загрузка карты...
),
},
);
interface Props {
data: ParcelAnalyzeResponse;
}
/**
* Adapts ParcelAnalyzeResponse → ParcelAnalysis shape expected by SiteMap.
* SiteMap reads: cad_num, geom_geojson, score_breakdown +
* #999 (958-B4): competitors, pipeline_24mo, nspd_risk_zones +
* §12.1-13 (#958): nspd_opportunity_parcels, nspd_red_lines (рыночные слои).
* Остальные required-поля заполняются безопасными дефолтами.
*/
function toSiteMapData(data: ParcelAnalyzeResponse): ParcelAnalysis {
return {
cad_num: data.cad_num,
source: data.source === "cad_building" ? "cad_building" : "cad_quarter",
geom_geojson: (data.geom_geojson as Geometry) ?? null,
score_breakdown: data.score_breakdown,
score: data.score,
poi_count: data.poi_count,
// #999 — пробрасываем рыночные данные в SiteMap-слои.
competitors: data.competitors ?? [],
pipeline_24mo: data.pipeline_24mo ?? undefined,
nspd_risk_zones: data.nspd_risk_zones ?? undefined,
// §12.1-13 (#958) — opportunity-ЗУ + красные линии застройки.
nspd_opportunity_parcels: data.nspd_opportunity_parcels ?? undefined,
nspd_red_lines: data.nspd_red_lines ?? undefined,
// #255 — ЗОУИТ overlaps (geom_geojson) для map-слоя охранных зон.
nspd_zouit_overlaps: data.nspd_zouit_overlaps ?? undefined,
noise: null,
air_quality: null,
wind: null,
district: data.district ?? null,
};
}
export function MiniMap({ data }: Props) {
const adapted = toSiteMapData(data);
// #1736: точки подключения ресурсов (электро/газ/вода/тепло). Зеркалим
// обвязку legacy /site-finder (page.tsx:109,568) — тянем CP-данные по
// data.cad_num и пробрасываем prop `connectionPoints` в , который
// рисует ConnectionPointsLayer + CpLayerControlPanel при truthy prop.
const { data: connectionPoints } = useConnectionPoints(data.cad_num);
// #1218: НЕ задаём height + overflow:hidden на обёртке. SiteMap сам
// ограничивает высоту карты-тайла (mapHeight), а легенда + layer-controls
// (Будущие проекты / Зоны риска / Перспективные ЗУ / Красные линии) + панель
// точек подключения (CpLayerControlPanel) лежат под картой потоком и должны
// быть видны/кликабельны. MINIMAP_HEIGHT ограничивает ТОЛЬКО тайл карты, не
// клипает CP-панель.
return (
);
}