"use client"; import { useState } from "react"; import type { NeighborsSummary } from "@/types/site-finder"; interface Props { data: NeighborsSummary; } function fmtPrice(n: number | null | undefined): string { if (n == null) return "—"; if (n >= 1000) { return `${(n / 1000).toFixed(0)} тыс ₽/м²`; } return `${n.toLocaleString("ru-RU")} ₽/м²`; } function fmtYearBuilt(y: number | null | undefined): string { if (y == null || y === 0) return "—"; return String(y); } // Русский plural: 1 → "здание", 2-4 → "здания", 5+ → "зданий". // Также корректно для 11-14 (zданий), 21 (здание), 22 (здания) etc. function pluralBuildings(n: number): string { const mod10 = n % 10; const mod100 = n % 100; if (mod100 >= 11 && mod100 <= 14) return "зданий"; if (mod10 === 1) return "здание"; if (mod10 >= 2 && mod10 <= 4) return "здания"; return "зданий"; } export function NeighborsBlock({ data }: Props) { const [expanded, setExpanded] = useState(false); if (!data.data_available) { return (
Соседи (100 м)
{data.note ?? "Данные о соседних зданиях недоступны"}
); } const count = data.count_buildings_100m ?? 0; const hasOverlap = !!data.has_existing_buildings; return (
Соседи (100 м) {count} {pluralBuildings(count)}
{/* Overlap warning — hard warn */} {hasOverlap && data.overlap_buildings && data.overlap_buildings.length > 0 && (
На участке уже есть здания (overlap >50 м²)
Инвестиции невозможны без сноса.
)} {/* Summary metrics */} {count > 0 && (
Средн. этажность
{data.avg_floors_100m ?? "—"}
Макс. этажей
{data.max_floors_100m ?? "—"}
Медиана цены
{fmtPrice(data.median_cost_per_m2_100m)}
)} {/* Toggle neighbor list */} {data.neighbors && data.neighbors.length > 0 && (
{expanded && (
{data.neighbors.map((n) => ( ))}
Здание Эт. Год ₽/м² Дист.
{n.building_name ?? n.readable_address ?? n.cad_num} {n.floors ?? "—"} {fmtYearBuilt(n.year_built)} {fmtPrice(n.cost_per_m2)} {n.distance_m} м
)}
)} {data.note && (
{data.note}
)}
); }