66 lines
1.5 KiB
TypeScript
66 lines
1.5 KiB
TypeScript
"use client";
|
||
import type { HouseAnalyticsKpi } from "@/types/trade-in";
|
||
|
||
type Props = { kpi: HouseAnalyticsKpi };
|
||
|
||
function KpiCard({
|
||
label,
|
||
value,
|
||
sub,
|
||
}: {
|
||
label: string;
|
||
value: string;
|
||
sub?: string;
|
||
}) {
|
||
return (
|
||
<div className="card" style={{ padding: 12, flex: 1, minWidth: 0 }}>
|
||
<div
|
||
style={{ fontSize: 11, color: "var(--muted, #6b7280)", marginBottom: 4 }}
|
||
>
|
||
{label}
|
||
</div>
|
||
<div style={{ fontSize: 20, fontWeight: 700 }}>{value}</div>
|
||
{sub && (
|
||
<div
|
||
style={{
|
||
fontSize: 11,
|
||
color: "var(--muted, #6b7280)",
|
||
marginTop: 2,
|
||
}}
|
||
>
|
||
{sub}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export function HouseAnalyticsKpiRow({ kpi }: Props) {
|
||
return (
|
||
<div style={{ display: "flex", gap: 12, marginTop: 8 }}>
|
||
<KpiCard
|
||
label="Средняя экспозиция"
|
||
value={
|
||
kpi.median_exposure_days != null
|
||
? `${kpi.median_exposure_days} дн.`
|
||
: "—"
|
||
}
|
||
sub="по архивным объявлениям"
|
||
/>
|
||
<KpiCard
|
||
label="Средний торг"
|
||
value={
|
||
kpi.median_bargain_pct != null
|
||
? `−${kpi.median_bargain_pct.toFixed(1)}%`
|
||
: "—"
|
||
}
|
||
sub="от start_price до last_price"
|
||
/>
|
||
<KpiCard
|
||
label="Доля снятых"
|
||
value={`${kpi.sold_rate_pct.toFixed(0)}%`}
|
||
sub={`${kpi.sold_count} из ${kpi.total_lots}`}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|