"use client"; import type { NspdEngineeringNearby } from "@/types/nspd"; import { useConnectionPoints } from "@/hooks/useConnectionPoints"; interface Props { nearby: NspdEngineeringNearby[]; cadNum: string | null | undefined; } interface MergedRow { label: string; type: string | null; distanceM: number; source: "analyze" | "connection-points"; // Stable structure identifier (НСПД cad_num) when available — используется для // дедупа между источниками, т.к. distanceM меряется до разных опорных точек // (analyze — до центроида, connection-points — до границы участка). cadNum: string | null; } export function NspdEngineeringNearbyBlock({ nearby, cadNum }: Props) { const { data: cpData, isPending: cpLoading } = useConnectionPoints(cadNum); // Merge and sort by distance const rows: MergedRow[] = []; for (const item of nearby) { if (item.distance_m !== null) { rows.push({ label: item.name ?? item.type ?? "Объект", type: item.type, distanceM: item.distance_m, source: "analyze", cadNum: null, }); } } if (cpData) { for (const s of cpData.engineering_structures) { rows.push({ label: s.name ?? s.type ?? "Объект", type: s.type, distanceM: s.distance_to_boundary_m, source: "connection-points", cadNum: s.cad_num, }); } } // Dedup. distanceM меряется до разных опорных точек (analyze — до центроида, // connection-points — до границы), поэтому label+round(distance) пропускает // дубли одного физического сооружения. Дедупим по стабильному cad_num, когда он // есть; иначе (analyze без cad_num) — по label + округлённому расстоянию. const seen = new Set(); const deduped = rows.filter((r) => { const key = r.cadNum !== null ? `cad:${r.cadNum}` : `lbl:${r.label}|${Math.round(r.distanceM)}`; if (seen.has(key)) return false; seen.add(key); return true; }); deduped.sort((a, b) => a.distanceM - b.distanceM); if (deduped.length === 0 && !cpLoading) { return (
Инженерных объектов поблизости не найдено
); } return (
{deduped.length > 0 && ( {deduped.map((row, idx) => ( ))}
Объект Тип Расстояние
{row.label} {row.type ?? "—"} {Math.round(row.distanceM)} м
)} {cpLoading && (
Загружаем данные точек подключения…
)} {cpData?.summary && (
{cpData.summary.in_protection_zone && ( В охранной зоне )} {cpData.summary.nearest_structure_distance_m !== null && ( Ближайший:{" "} {Math.round(cpData.summary.nearest_structure_distance_m)} м )}
)}
); }