"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 (
); }