gendesign/tradein-mvp/frontend/src/lib/sale-share-api.ts
lekss361 f8112b420d
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been cancelled
feat(tradein): страница «доля квартир дома в продаже» — % слайдер, адреса, карта (#2058)
2026-06-28 14:53:38 +00:00

81 lines
2.6 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 { apiFetch } from "./api";
import type {
BuildingListing,
BuildingSaleShare,
SaleShareQuery,
SaleShareSummary,
} from "@/types/sale-share";
const BASE = "/api/v1/buildings";
/**
* GET /api/v1/buildings/sale-share/summary
* Сводка распределения sale_share_pct: coverage, max/p95, гистограмма.
* Нужна для слайдера % и баннера покрытия — кэшируем подольше.
*/
export function useSaleShareSummary() {
return useQuery<SaleShareSummary>({
queryKey: ["sale-share", "summary"],
queryFn: () => apiFetch<SaleShareSummary>(`${BASE}/sale-share/summary`),
staleTime: 10 * 60_000,
});
}
function buildParams(q: SaleShareQuery): string {
const p = new URLSearchParams();
p.set("min_pct", String(q.min_pct));
if (q.max_pct != null) p.set("max_pct", String(q.max_pct));
if (q.city) p.set("city", q.city);
if (q.price_min != null) p.set("price_min", String(q.price_min));
if (q.price_max != null) p.set("price_max", String(q.price_max));
if (q.year_min != null) p.set("year_min", String(q.year_min));
if (q.year_max != null) p.set("year_max", String(q.year_max));
if (q.house_type) p.set("house_type", q.house_type);
p.set("sort", q.sort);
if (q.limit != null) p.set("limit", String(q.limit));
return p.toString();
}
/**
* GET /api/v1/buildings/sale-share
* Список домов вторички с долей квартир в продаже >= min_pct (+ фильтры).
*/
export function useSaleShareBuildings(query: SaleShareQuery) {
return useQuery<BuildingSaleShare[]>({
queryKey: [
"sale-share",
"buildings",
query.min_pct,
query.max_pct ?? null,
query.city ?? null,
query.price_min ?? null,
query.price_max ?? null,
query.year_min ?? null,
query.year_max ?? null,
query.house_type ?? null,
query.sort,
query.limit ?? 200,
],
queryFn: () =>
apiFetch<BuildingSaleShare[]>(`${BASE}/sale-share?${buildParams(query)}`),
staleTime: 5 * 60_000,
});
}
/**
* GET /api/v1/buildings/{house_id}/listings
* Активные вторичные объявления одного дома (для drawer). Лениво —
* enabled только когда выбран дом.
*/
export function useBuildingListings(houseId: number | null) {
return useQuery<BuildingListing[]>({
queryKey: ["sale-share", "listings", houseId],
queryFn: () => apiFetch<BuildingListing[]>(`${BASE}/${houseId}/listings`),
enabled: houseId !== null,
staleTime: 5 * 60_000,
});
}