diff --git a/tradein-mvp/frontend/src/components/trade-in/DistributionCard.tsx b/tradein-mvp/frontend/src/components/trade-in/DistributionCard.tsx index e39214c8..bb8b77bc 100644 --- a/tradein-mvp/frontend/src/components/trade-in/DistributionCard.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/DistributionCard.tsx @@ -25,6 +25,7 @@ interface Props { } const BIN_COUNT = 12; +const MIN_CHART_ANALOGS = 8; const fmtK = (n: number) => `${Math.round(n / 1000)}k`; interface Bin { @@ -74,7 +75,7 @@ export function DistributionCard({ estimate }: Props) { return out; }, [estimate.analogs, subject]); - // Empty state: меньше 3 валидных аналогов — распределение не показываем. + // Empty state: меньше 3 валидных аналогов — бины не строим вовсе. if (bins.length === 0) return null; const n = estimate.analogs.filter((l) => l.price_per_m2 > 0).length; @@ -94,63 +95,73 @@ export function DistributionCard({ estimate }: Props) { - {/* #835: декоративный чарт — aria-hidden (данные в тексте/легенде карточки). */} - + ) : ( + <> + {/* #835: декоративный чарт — aria-hidden (данные в тексте/легенде карточки). */} + + + [`${value} лот.`, "В диапазоне"]} + labelFormatter={(mid: number) => { + const b = bins.find((x) => x.mid === mid); + return b + ? `${Math.round(b.start).toLocaleString("ru-RU")}–${Math.round( + b.end, + ).toLocaleString("ru-RU")} ₽/м²` + : `${Math.round(mid).toLocaleString("ru-RU")} ₽/м²`; + }} + /> + + {bins.map((b, i) => ( + + ))} + + + + + -
- - Ваша оценка:{" "} - {subject.toLocaleString("ru-RU")} ₽/м² · - оранжевый столбец — ваш диапазон - -
+
+ + Ваша оценка:{" "} + {subject.toLocaleString("ru-RU")} ₽/м² · + оранжевый столбец — ваш диапазон + +
+ + )} ); } diff --git a/tradein-mvp/frontend/src/components/trade-in/ExposureCard.tsx b/tradein-mvp/frontend/src/components/trade-in/ExposureCard.tsx index 8c099d49..5a6c1a15 100644 --- a/tradein-mvp/frontend/src/components/trade-in/ExposureCard.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/ExposureCard.tsx @@ -25,6 +25,7 @@ interface Props { estimate: AggregatedEstimate; } +const MIN_CHART_ANALOGS = 8; const fmtM = (n: number) => `${(n / 1_000_000).toFixed(1)}`; interface Point { @@ -72,64 +73,74 @@ export function ExposureCard({ estimate }: Props) { - {/* #835: чарт декоративный (данные — в заголовке/легенде/тексте карточки); - aria-hidden убирает recharts symbol'ы role="img" без accessible-name. */} - + {points.length < MIN_CHART_ANALOGS ? ( +
+

+ Недостаточно данных для графика — нужно не менее {MIN_CHART_ANALOGS} аналогов со сроком. +

+
+ ) : ( + <> + {/* #835: чарт декоративный (данные — в заголовке/легенде/тексте карточки); + aria-hidden убирает recharts symbol'ы role="img" без accessible-name. */} + -
- - Каждая точка — аналог в продаже · вертикаль — ваша оценка{" "} - {fmtM(subjectPrice)} млн ₽ - -
+
+ + Каждая точка — аналог в продаже · вертикаль — ваша оценка{" "} + {fmtM(subjectPrice)} млн ₽ + +
+ + )} ); } diff --git a/tradein-mvp/frontend/src/components/trade-in/PriceHistoryChart.tsx b/tradein-mvp/frontend/src/components/trade-in/PriceHistoryChart.tsx index fec51da6..a4b2c6df 100644 --- a/tradein-mvp/frontend/src/components/trade-in/PriceHistoryChart.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/PriceHistoryChart.tsx @@ -46,10 +46,10 @@ export function PriceHistoryChart({ points }: Props) {

- Динамика цен в доме + История цен в этом доме

- Медиана ₽/м² по году · Avito + Яндекс (по {totalLots} лотам) + Медиана ₽/м² по годам · только этот дом · Avito + Яндекс ({totalLots} лотов)
{/* #835: декоративный чарт — aria-hidden (данные в тексте/легенде карточки). */} diff --git a/tradein-mvp/frontend/src/components/trade-in/PriceTrendCard.tsx b/tradein-mvp/frontend/src/components/trade-in/PriceTrendCard.tsx index 9d30f3d8..70dfe2c4 100644 --- a/tradein-mvp/frontend/src/components/trade-in/PriceTrendCard.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/PriceTrendCard.tsx @@ -58,8 +58,8 @@ export function PriceTrendCard({ estimate }: Props) {
-
Аналитика · Тренд
-

Динамика ₽/м²

+
Аналитика · Тренд рынка
+

Динамика ₽/м² по рынку района

@@ -101,7 +101,7 @@ export function PriceTrendCard({ estimate }: Props) {
- Медиана ₽/м² по месяцам · {fmtMonth(data[0].month)} →{" "} + Медиана ₽/м² по аналогам рынка · {fmtMonth(data[0].month)} →{" "} {fmtMonth(data[data.length - 1].month)}
diff --git a/tradein-mvp/frontend/src/components/trade-in/SourcesProgress.tsx b/tradein-mvp/frontend/src/components/trade-in/SourcesProgress.tsx index 65f34492..adbeb289 100644 --- a/tradein-mvp/frontend/src/components/trade-in/SourcesProgress.tsx +++ b/tradein-mvp/frontend/src/components/trade-in/SourcesProgress.tsx @@ -198,13 +198,6 @@ export function SourcesProgress({ estimate, isPending }: Props) {
- - CACHE-KEY ·{" "} - - - {estimate?.estimate_id?.slice(0, 18) ?? "—"} - {" "} - ·{" "} при недоступности источника частичный результат не блокируется