gendesign/frontend/src/components/analytics/MarketPulseChart.tsx
lekss361 8d3a0874ef add interactive analytics dashboard for Sverdlovsk market and PRINZIP
3 pages (market, PRINZIP drilldown, developers leaderboard) on top of
existing v_developer_full_metrics + domrf_realization views. ECharts on
the frontend, FastAPI router /api/v1/analytics on the backend.
2026-04-27 16:55:30 +03:00

70 lines
2 KiB
TypeScript

"use client";
import { useMemo } from "react";
import { useMarketPulse } from "@/lib/analytics-api";
import { ChartShell } from "./ChartShell";
export function MarketPulseChart() {
const { data, isLoading } = useMarketPulse();
const option = useMemo(() => {
const points = data ?? [];
const dates = points.map((p) => p.snapshot_date.slice(0, 7));
return {
tooltip: { trigger: "axis", axisPointer: { type: "cross" } },
legend: { data: ["Объём, тыс м²", "sold %", "Цена, ₽/м²"] },
grid: { left: 56, right: 64, top: 40, bottom: 36 },
xAxis: { type: "category", data: dates },
yAxis: [
{
type: "value",
name: "тыс м²",
position: "left",
axisLabel: { color: "#5b6066" },
},
{
type: "value",
name: "% / ₽",
position: "right",
axisLabel: { color: "#5b6066" },
},
],
series: [
{
name: "Объём, тыс м²",
type: "bar",
yAxisIndex: 0,
data: points.map((p) => p.total_square_th_sqm),
itemStyle: { color: "rgba(33, 99, 232, 0.55)" },
},
{
name: "sold %",
type: "line",
yAxisIndex: 1,
smooth: true,
symbol: "circle",
data: points.map((p) => p.sold_perc),
lineStyle: { color: "#0a7a3a", width: 2 },
itemStyle: { color: "#0a7a3a" },
},
{
name: "Цена, ₽/м²",
type: "line",
yAxisIndex: 1,
smooth: true,
symbol: "circle",
data: points.map((p) =>
p.price_avg ? Math.round(p.price_avg / 1000) : null,
),
lineStyle: { color: "#c2410c", width: 2 },
itemStyle: { color: "#c2410c" },
tooltip: { valueFormatter: (v: number) => `${v} тыс ₽/м²` },
},
],
};
}, [data]);
return <ChartShell option={option} loading={isLoading} height={360} />;
}