Compare commits
No commits in common. "efdf11d10f733f740882b160c1b1dd0351e1ed8d" and "684385263eb81f0b375c83ad6d61a04ce7bfff90" have entirely different histories.
efdf11d10f
...
684385263e
2 changed files with 28 additions and 8 deletions
|
|
@ -182,7 +182,7 @@ export default function TradeInPage() {
|
||||||
<div>
|
<div>
|
||||||
<h1>Оценка квартиры на вторичке</h1>
|
<h1>Оценка квартиры на вторичке</h1>
|
||||||
<p className="page-subtitle" style={{ marginTop: 8 }}>
|
<p className="page-subtitle" style={{ marginTop: 8 }}>
|
||||||
Агрегируем 4 источника объявлений (Авито, Циан, Яндекс, N1) и реальные сделки Росреестра.
|
Агрегируем данные из 7 источников + аналоги в продаже + фактические сделки.
|
||||||
Время сбора — <span className="num">10–30 сек</span>.
|
Время сбора — <span className="num">10–30 сек</span>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -336,7 +336,7 @@ export default function TradeInPage() {
|
||||||
<footer className="page-foot">
|
<footer className="page-foot">
|
||||||
<div>
|
<div>
|
||||||
Мера · MVP ·{" "}
|
Мера · MVP ·{" "}
|
||||||
<span className="mono">data: Avito + Cian + Yandex + N1 + Росреестр</span>
|
<span className="mono">data: Avito + Cian + Yandex + Росреестр</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", gap: 18 }}>
|
<div style={{ display: "flex", gap: 18 }}>
|
||||||
<a href="#">Документация</a>
|
<a href="#">Документация</a>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SourcesProgress — карточка «Шаг B · Агрегация».
|
* SourcesProgress — карточка «Шаг B · Агрегация» под mockup tradein.html.
|
||||||
*
|
*
|
||||||
* Показывает 5 реальных источников: 4 источника объявлений (Циан, Авито,
|
* Показывает статус 7 строк-источников. Реально работают 4: Cian + Avito +
|
||||||
* Яндекс, N1) + Росреестр (внутренние сделки). Статусы выводятся из реального
|
* Yandex + N1. ДомКлик и Restate пока не реализованы — показываем idle для
|
||||||
* `estimate.sources_used` / `countBySource` / `actual_deals`; источник без
|
* соответствия макету.
|
||||||
* вклада честно показывает «нет данных».
|
|
||||||
*/
|
*/
|
||||||
import type { AggregatedEstimate } from "@/types/trade-in";
|
import type { AggregatedEstimate } from "@/types/trade-in";
|
||||||
|
|
||||||
|
|
@ -21,10 +20,15 @@ interface SourceRow {
|
||||||
dotClass: string;
|
dotClass: string;
|
||||||
status: "done" | "loading" | "error" | "idle";
|
status: "done" | "loading" | "error" | "idle";
|
||||||
count?: number;
|
count?: number;
|
||||||
|
median?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatMln(rub: number): string {
|
||||||
|
return `${(rub / 1_000_000).toFixed(2).replace(".", ",")} млн`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SourcesProgress({ estimate, isPending }: Props) {
|
export function SourcesProgress({ estimate, isPending }: Props) {
|
||||||
// Маппинг реальных данных из estimate на строки-источники
|
// Маппинг реальных данных из estimate на 7 строк-источников
|
||||||
const used = new Set(estimate?.sources_used ?? []);
|
const used = new Set(estimate?.sources_used ?? []);
|
||||||
const isDone = estimate !== null && !isPending;
|
const isDone = estimate !== null && !isPending;
|
||||||
|
|
||||||
|
|
@ -45,6 +49,7 @@ export function SourcesProgress({ estimate, isPending }: Props) {
|
||||||
dotClass: "cian",
|
dotClass: "cian",
|
||||||
status: used.has("cian") ? "done" : (isPending ? "loading" : "idle"),
|
status: used.has("cian") ? "done" : (isPending ? "loading" : "idle"),
|
||||||
count: countBySource.cian,
|
count: countBySource.cian,
|
||||||
|
median: used.has("cian") ? estimate?.median_price_rub : undefined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "avito",
|
key: "avito",
|
||||||
|
|
@ -52,6 +57,13 @@ export function SourcesProgress({ estimate, isPending }: Props) {
|
||||||
dotClass: "avito",
|
dotClass: "avito",
|
||||||
status: used.has("avito") ? "done" : (isPending ? "loading" : "idle"),
|
status: used.has("avito") ? "done" : (isPending ? "loading" : "idle"),
|
||||||
count: countBySource.avito,
|
count: countBySource.avito,
|
||||||
|
median: used.has("avito") ? estimate?.median_price_rub : undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "domklik",
|
||||||
|
label: "ДомКлик Прайс",
|
||||||
|
dotClass: "dom",
|
||||||
|
status: isPending ? "loading" : "idle",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "yandex",
|
key: "yandex",
|
||||||
|
|
@ -59,6 +71,13 @@ export function SourcesProgress({ estimate, isPending }: Props) {
|
||||||
dotClass: "yandex",
|
dotClass: "yandex",
|
||||||
status: used.has("yandex") ? "done" : (isPending ? "loading" : "idle"),
|
status: used.has("yandex") ? "done" : (isPending ? "loading" : "idle"),
|
||||||
count: countBySource.yandex,
|
count: countBySource.yandex,
|
||||||
|
median: used.has("yandex") ? estimate?.median_price_rub : undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "restate",
|
||||||
|
label: "Restate",
|
||||||
|
dotClass: "etagi",
|
||||||
|
status: isPending ? "loading" : "idle",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "n1",
|
key: "n1",
|
||||||
|
|
@ -66,6 +85,7 @@ export function SourcesProgress({ estimate, isPending }: Props) {
|
||||||
dotClass: "n1",
|
dotClass: "n1",
|
||||||
status: used.has("n1") ? "done" : (isPending ? "loading" : "idle"),
|
status: used.has("n1") ? "done" : (isPending ? "loading" : "idle"),
|
||||||
count: countBySource.n1,
|
count: countBySource.n1,
|
||||||
|
median: used.has("n1") ? estimate?.median_price_rub : undefined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "rosreestr",
|
key: "rosreestr",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue