"use client"; import { ArrowUpRight } from "lucide-react"; import dynamic from "next/dynamic"; import Link from "next/link"; import { useParams } from "next/navigation"; import { KpiCard } from "@/components/analytics/KpiCard"; import { LazyMount } from "@/components/analytics/LazyMount"; import { ObjectChecksBadges } from "@/components/analytics/ObjectChecksBadges"; import { ObjectDocumentsList } from "@/components/analytics/ObjectDocumentsList"; import { ObjectMetroList } from "@/components/analytics/ObjectMetroList"; import { ObjectQuartirographyTable } from "@/components/analytics/ObjectQuartirographyTable"; import { ObjectSpecsTable } from "@/components/analytics/ObjectSpecsTable"; import { Section } from "@/components/analytics/Section"; import { useObjectBuildings, useObjectChecks, useObjectDocuments, useObjectFullDetail, useObjectQuartirography, useObjectSalesAgg, } from "@/lib/analytics-api"; // Heavy sections deferred so initial paint and main-thread are not blocked. const ObjectSaleChart = dynamic( () => import("@/components/analytics/ObjectSaleChart").then( (m) => m.ObjectSaleChart, ), { ssr: false, loading: () => (
), }, ); const ObjectInfraMap = dynamic( () => import("@/components/analytics/ObjectInfraMap").then( (m) => m.ObjectInfraMap, ), { ssr: false, loading: () => (
), }, ); const ObjectPhotoGallery = dynamic( () => import("@/components/analytics/ObjectPhotoGallery").then( (m) => m.ObjectPhotoGallery, ), { ssr: false, loading: () =>
, }, ); export default function ObjectDrillInPage() { const params = useParams<{ id: string }>(); const objId = params.id; const fullDetail = useObjectFullDetail(objId); const agg = useObjectSalesAgg(objId); const buildings = useObjectBuildings(objId); const quartirography = useObjectQuartirography(objId); const checks = useObjectChecks(objId); const documents = useObjectDocuments(objId); const apartments = agg.data?.find((r) => r.type === "apartments"); const parking = agg.data?.find((r) => r.type === "parking"); const nonliv = agg.data?.find((r) => r.type === "nonliv"); const d = fullDetail.data; // Cross-link target (#65): first building's cadastral number — a real parcel // Site Finder can analyze. Объект сам по себе не несёт cad_quarter, но корпуса // из NSPD несут cad_num, что и есть точка входа в анализ участка. const siteFinderCad = buildings.data?.find( (b) => b.cad_num != null && b.cad_num !== "", )?.cad_num; return ( <> ← К PRINZIP

{d?.comm_name ?? "Загрузка…"}{" "} {d?.site_status ? ( {d.site_status} ) : null}

{d?.addr ?? ""} · obj_id={d?.obj_id} · {d?.dev_name ?? ""} {d?.escrow ? " · эскроу" : ""}

{/* ── KPI row — распроданность ────────────────────────────────────────── */}
= 50 ? "выше среднего рынка" : apartments.perc >= 30 ? "около среднего" : "ниже среднего", positive: apartments.perc >= 30, } : undefined } /> {d?.price_min_rub != null ? ( ) : null} {d?.price_max_rub != null ? ( ) : null}
{/* ── DOM.РФ scores ───────────────────────────────────────────────────── */} {(d?.domrf_score_location != null || d?.domrf_score_transport != null || d?.domrf_score_infrastructure != null) && (
{d?.domrf_score_location != null && ( )} {d?.domrf_score_transport != null && ( )} {d?.domrf_score_infrastructure != null && ( )}
)} {/* ── 1. Динамика продаж ──────────────────────────────────────────────── */}
{/* ── 2. Квартирография ──────────────────────────────────────────────── */}
{quartirography.isLoading ? (
) : ( )}
{/* ── 3. Ближайшее метро ──────────────────────────────────────────────── */} {(d?.metro_nearest_name != null || (d?.metro_top3 != null && d.metro_top3.length > 0)) && (
)} {/* ── 4. Инфраструктура (POI) ─────────────────────────────────────────── */}
{/* ── 5. Фото прогресса строительства ─────────────────────────────────── */}
{/* ── 6. Проверено на наш.дом.рф ─────────────────────────────────────── */} {!checks.isLoading && (checks.data?.length ?? 0) > 0 && (
)} {/* ── 7. Документы ────────────────────────────────────────────────────── */} {!documents.isLoading && (documents.data?.length ?? 0) > 0 && (
)} {/* ── 8. Все характеристики ───────────────────────────────────────────── */} {d && (
)} {/* ── 9. Корпуса ЖК ───────────────────────────────────────────────────── */} {(d?.buildings_count ?? 0) > 0 && buildings.data && buildings.data.length > 0 && (
Посмотреть участок в Site Finder ) : undefined } >
{[ "Кад. номер", "Этажей", "Площадь, м²", "Назначение", "Название", "Адрес", ].map((h) => ( ))} {buildings.data.map((b, i) => ( ))}
{h}
{b.cad_num ?? "—"} {b.floors ?? "—"} {b.area != null ? b.area.toLocaleString("ru-RU", { maximumFractionDigits: 1, }) : "—"} {b.purpose ?? "—"} {b.building_name ?? "—"} {b.readable_address ?? "—"}
)} {(d?.buildings_count ?? 0) > 0 && buildings.data && buildings.data.length === 0 && (

Геометрия корпусов ещё не подгружена с NSPD.

)} ); }