import type { ToveliEstimate } from "@/lib/estimate"; import { fmtPrice, fmtPct } from "@/lib/format"; export function EstimateBreakdown({ e, price }: { e: ToveliEstimate; price?: number | null }) { const r = e.result; const w = (v: number | null) => (v && r.estimate ? Math.min(100, Math.max(0, ((v - r.low) / Math.max(1, r.high - r.low)) * 100)) : null); return (
{[["Estimation", r.estimate, "bg-brand"], ...(r.modelEstimate ? [["Modèle", r.modelEstimate, "bg-ink-3"]] : []), ...(r.compsEstimate ? [["Comparables", r.compsEstimate, "bg-ink-3"]] : []), ...(price ? [["Prix demandé", price, "bg-info"]] : [])].map(([k, v, c]) => { const x = w(v as number); return x == null ? null : {k}; })} {fmtPrice(r.low)}{fmtPrice(r.high)}
{r.modelEstimate != null &&
Modèle hédonique (poids {Math.round(r.modelWeight * 100)} %)
{fmtPrice(r.modelEstimate)}
} {r.compsEstimate != null &&
Comparables ajustés (poids {Math.round((1 - r.modelWeight) * 100)} %)
{fmtPrice(r.compsEstimate)}
}
Comparables retenus
{r.nCompsUsed}
{r.compsDispersionPct != null &&
Dispersion des comparables
{r.compsDispersionPct} %
} {e.roleUnit?.role_value != null &&
Valeur au rôle
{fmtPrice(e.roleUnit.role_value)} ({fmtPct(r.estimate / e.roleUnit.role_value - 1)})
}
Largeur de la fourchette
{fmtPct((r.high - r.low) / r.estimate, 0, false)}

Entrées : {e.method.inputs.join(" ; ")}.

); }