"use client"; import type { RecommendBucket } from "@/types/analytics"; interface DerivedBucket extends RecommendBucket { effective_share_pct: number; effective_units: number | null; effective_revenue_rub: number | null; } interface Props { rows: DerivedBucket[]; hasAllocation: boolean; priceFactor?: number; elasticity?: number; } const fmtInt = (n: number | null | undefined) => n == null ? "—" : Math.round(n).toLocaleString("ru"); const fmtMln = (rub: number | null | undefined) => rub == null ? "—" : `${(rub / 1_000_000).toFixed(1)} млн ₽`; export function RecommendBucketsTable({ rows, hasAllocation, priceFactor = 1, elasticity = -1.5, }: Props) { const pfPow = priceFactor > 0 ? priceFactor ** elasticity : 1; return (
{[ "Бакет", "Успех", "Доля", "Сделок", "Площадь ср., м²", "Цена p25, ₽/м²", "Цена медиана, ₽/м²", "Цена p75, ₽/м²", "Темп, кв/мес", ...(hasAllocation ? ["Юнитов", "Срок, мес", "Выручка"] : []), ].map((h) => ( ))} {rows.map((r, i) => { const adjVelocity = (r.velocity_per_month ?? 0) * pfPow; const months = r.effective_units && adjVelocity > 0 ? r.effective_units / adjVelocity : null; const adjPriceMedian = r.price_median_per_m2 * priceFactor; const adjP25 = r.price_p25_per_m2 * priceFactor; const adjP75 = r.price_p75_per_m2 * priceFactor; const adjRevenue = r.effective_revenue_rub != null ? r.effective_revenue_rub * priceFactor : null; return ( {hasAllocation ? ( <> ) : null} ); })}
{h}
{r.bucket} {r.is_top_success === true ? ( ) : null} {r.effective_share_pct.toFixed(1)}% {fmtInt(r.deal_count)} {r.area_avg_m2.toFixed(1)} {fmtInt(adjP25)} {fmtInt(adjPriceMedian)} {fmtInt(adjP75)} {adjVelocity > 0 ? adjVelocity.toFixed(1) : "—"} {fmtInt(r.effective_units)} {months == null ? "—" : months > 60 ? "60+" : months.toFixed(1)} {fmtMln(adjRevenue)}
); } const td: React.CSSProperties = { padding: "8px 10px" };