gendesign/frontend/src/components/analytics/QuartirographyChart.tsx
bot-backend 26ae507c11
Some checks failed
CI / changes (push) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI / frontend-tests (push) Successful in 1m1s
CI / openapi-codegen-check (push) Successful in 1m50s
CI / backend-tests (push) Failing after 9m8s
CI / frontend-tests (pull_request) Successful in 54s
CI / openapi-codegen-check (pull_request) Successful in 1m59s
CI / backend-tests (pull_request) Failing after 8m56s
fix(analytics): align portfolio series to area buckets in quartirography (#1406)
Switch portfolio source from domrf_region_aggregates (room_count_type ONE/TWO/THREE/FOUR)
to domrf_flat_area_distribution (area_bucket FROM_0_TO_25…FROM_100), aggregated into the
same 5 area buckets as the deals series. Both series now share the same axis and are
directly comparable. Frontend portfolioMap simplified to direct bucket key lookup.
2026-06-17 20:25:17 +03:00

76 lines
2.3 KiB
TypeScript

"use client";
import { useMemo } from "react";
import {
useQuartirographyDeals,
useQuartirographyPortfolio,
} from "@/lib/analytics-api";
import { ChartShell } from "./ChartShell";
export function QuartirographyChart() {
const portfolio = useQuartirographyPortfolio();
const deals = useQuartirographyDeals();
const option = useMemo(() => {
const portfolioRows = portfolio.data ?? [];
const dealsRows = deals.data ?? [];
const buckets = [
"Студии 15-30",
"1-к 30-45",
"2-к 45-60",
"3-к 60-80",
"80+ м²",
];
// Portfolio is now served from domrf_flat_area_distribution with the same
// area bucket keys as the deals series — direct lookup by bucket label.
// If a bucket is absent in the source (e.g. studio data gap), percent
// falls back to null so ECharts draws no bar rather than a misleading 0%.
const portfolioMap: Record<string, number | null> = Object.fromEntries(
buckets.map((b) => {
const row = portfolioRows.find((r) => r.bucket === b);
return [b, row != null ? (row.percent ?? null) : null];
}),
);
const dealsPercents = buckets.map(
(b) => dealsRows.find((r) => r.bucket === b)?.percent ?? 0,
);
const portfolioPercents = buckets.map((b) => portfolioMap[b] ?? null);
return {
tooltip: {
trigger: "axis",
axisPointer: { type: "shadow" },
valueFormatter: (v: number | null) =>
v == null ? "нет данных" : `${v}%`,
},
legend: { data: ["Что строится (портфель)", "Что покупают (ДДУ)"] },
grid: { left: 110, right: 32, top: 40, bottom: 28 },
xAxis: { type: "value", axisLabel: { formatter: "{value}%" } },
yAxis: { type: "category", data: buckets, inverse: true },
series: [
{
name: "Что строится (портфель)",
type: "bar",
data: portfolioPercents,
itemStyle: { color: "#94a3b8" },
},
{
name: "Что покупают (ДДУ)",
type: "bar",
data: dealsPercents,
itemStyle: { color: "#0a7a3a" },
},
],
};
}, [portfolio.data, deals.data]);
return (
<ChartShell
option={option}
loading={portfolio.isLoading || deals.isLoading}
height={320}
/>
);
}