// Vrai-Prix — carte d'annonce (liste « À vendre », voisines, comparables en vente). "use client"; import Link from "next/link"; import type { ListingCard } from "@/lib/immoka"; import { TYPE_GROUPS } from "@/lib/listing-types"; import { money, num, pct, sqftToM2 } from "./fmt"; export function groupLabel(key: string, fr: boolean): string { const g = TYPE_GROUPS.find((x) => x.key === key); return g ? (fr ? g.fr : g.en) : key; } /** Pastille écart estimation vs prix demandé (encre = au-dessus, rouge = en-dessous). */ export function RatioPill({ ratio, fr, size = "sm" }: { ratio: number | null; fr: boolean; size?: "sm" | "md" }) { const cls = size === "md" ? "px-2.5 py-1 text-[11px]" : "px-1.5 py-0.5 text-[9.5px]"; if (ratio == null) return ( {fr ? "non évaluée" : "not evaluated"} ); const d = (ratio - 1) * 100; const tone = Math.abs(d) < 5 ? "border-[var(--line-strong)] text-ink" : d > 0 ? "border-ink bg-ink text-paper" : "border-[var(--danger)] text-[var(--danger)]"; return ( {fr ? "éval." : "est."} {pct(d, fr ? "fr" : "en")} ); } /** Badge « Coût IA » — affiché seulement quand une analyse IA complète existe pour l'annonce (jamais avant). */ export function AiCostBadge({ rcn, fr }: { rcn: number | null; fr: boolean }) { return ( {rcn ? `RCN ${fr ? "estimé" : "est."} ${Math.round(rcn / 1000)} k$` : fr ? "Coût IA disponible" : "AI cost available"} ); } export default function ListingCardView({ c, fr, compact = false, ai = null }: { c: ListingCard; fr: boolean; compact?: boolean; ai?: { rcn: number | null } | null }) { const lang = fr ? "fr" : "en"; const area = sqftToM2(c.areaSqft); const facts = [ c.bedrooms != null ? `${c.bedrooms} ${fr ? "ch." : "bd"}` : null, c.bathrooms != null ? `${c.bathrooms} ${fr ? "sdb" : "ba"}` : null, area ? `${num(area, lang)} m²` : null, c.yearBuilt ? `${c.yearBuilt}` : null, ].filter((x): x is string => x != null); return (
{money(c.price, lang)}
{ai ?{c.address || c.propertyType || "—"}
{[c.sector, c.municipalite ?? c.city].filter(Boolean).join(" · ")}
{facts.length ? facts.join(" · ") : c.propertyType ?? ""} {c.distanceM != null ? ` · ${c.distanceM < 1000 ? `${c.distanceM} m` : `${(c.distanceM / 1000).toFixed(1)} km`}` : ""}
{c.est != null && ({fr ? "Vrai-Prix" : "Vrai-Prix"} {money(c.est, lang)} {c.confidence ? ` · ${fr ? "conf." : "conf."} ${c.confidence}` : ""}
)}