gendesign/frontend/src/hooks/useNeighborBuildings.ts
bot-backend a7ad1764c1
Some checks failed
Deploy / build-frontend (push) Has been cancelled
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
feat(concept): 3D-макет окружения — соседние здания из кадастра в §7 (#2180) (#2210)
2026-07-02 19:33:44 +00:00

70 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useQuery } from "@tanstack/react-query";
import type { FeatureCollection, MultiPolygon, Polygon } from "geojson";
import { apiFetch } from "@/lib/api";
/**
* Радиус поиска соседних зданий вокруг участка для 3D-сцены / 2D-плана §7
* («Размещение застройки»). Дефолт 300 м — согласован с бэком
* (GET /neighbor-buildings?radius_m=…, диапазон 501000). Держим отдельной
* константой, чтобы подпись и запрос не расходились.
*/
export const NEIGHBOR_BUILDINGS_RADIUS_M = 300;
/**
* properties одной соседней постройки. Форма — единственный источник истины
* бэкенд (parcels.py::get_parcel_neighbor_buildings): endpoint отдаёт plain
* GeoJSON FeatureCollection (handler-return `dict[str, Any]`, НЕ Pydantic-модель),
* поэтому в api-types.ts codegen'ом он не попадает — типизуем вручную, как и
* соседний `NeighborBuilding` в types/site-finder.ts.
*/
export interface NeighborBuildingProps {
cad_num: string | null;
/** Этажность НСПД (int) либо null, если не заполнена в кадастре. */
floors: number | null;
/** Высота = floors × 3 м (бэк), либо null при неизвестной этажности. */
height_m: number | null;
building_name: string | null;
year_built: number | null;
is_neighbor: true;
}
export interface NeighborBuildingsResponse extends FeatureCollection<
Polygon | MultiPolygon,
NeighborBuildingProps
> {
/** Число возвращённых фич (после cap на бэке). */
count: number;
/** Радиус, по которому реально искали (echo query-параметра). */
radius_m: number;
/** true, если в радиусе зданий было больше лимита (300) и выборку обрезали. */
truncated: boolean;
}
/**
* Соседние здания (footprint'ы) вокруг участка для сцены «Размещение застройки»
* (§7 отчёта ПТИЦА, Forgejo #2180): существующая застройка контекста, чтобы
* концепция читалась в окружении квартала.
*
* Зеркалит useConnectionCapacity: apiFetch, queryKey-массив, staleTime 5 мин,
* enabled по cadNum. Пустой / отсутствующий cadNum (например standalone-страница
* /concept без кадастра) → запрос не идёт (enabled=false), сцена работает как
* раньше без соседей.
*/
export function useNeighborBuildings(
cadNum: string | null | undefined,
radiusM: number = NEIGHBOR_BUILDINGS_RADIUS_M,
enabled = true,
) {
return useQuery<NeighborBuildingsResponse>({
queryKey: ["neighbor-buildings", cadNum, radiusM],
queryFn: () =>
apiFetch<NeighborBuildingsResponse>(
`/api/v1/parcels/${encodeURIComponent(cadNum!)}/neighbor-buildings?radius_m=${radiusM}`,
),
enabled: !!cadNum && enabled,
staleTime: 5 * 60 * 1000,
});
}