feat(ui): smart proximity label — infer street from deal data

Instead of showing "סביבה קרובה" for all street-polygon deals, we now
infer the searched street from the most common streetNameHeb among
deal_source="street" deals. Deals on that street get "אותו רחוב" (blue);
deals on other streets get "סביבה קרובה" (lighter blue). Works correctly
for both address searches and gush+plot searches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 14:55:27 +00:00
parent 9aa9fa29f1
commit 918e7dbe02
+32 -11
View File
@@ -5,11 +5,34 @@ interface Props {
deals: Deal[]; deals: Deal[];
} }
const SOURCE_LABELS: Record<string, string> = { function inferStreetName(deals: Deal[]): string | null {
same_building: "אותו בניין", const freq: Record<string, number> = {};
street: "סביבה קרובה", for (const d of deals) {
neighborhood: "שכונה", if (d.deal_source === "street" && d.streetNameHeb) {
}; freq[d.streetNameHeb] = (freq[d.streetNameHeb] ?? 0) + 1;
}
}
const entries = Object.entries(freq);
if (!entries.length) return null;
return entries.reduce((a, b) => (b[1] > a[1] ? b : a))[0];
}
function proximityLabel(deal: Deal, inferredStreet: string | null): string {
if (!deal.deal_source) return "—";
if (deal.deal_source === "same_building") return "אותו בניין";
if (deal.deal_source === "neighborhood") return "שכונה";
// "street" source — check if actually same street
if (inferredStreet && deal.streetNameHeb === inferredStreet) return "אותו רחוב";
return "סביבה קרובה";
}
function proximityClass(deal: Deal, inferredStreet: string | null): string {
if (deal.deal_source === "same_building") return "bg-emerald-100 text-emerald-800";
if (deal.deal_source === "street" && inferredStreet && deal.streetNameHeb === inferredStreet)
return "bg-blue-100 text-blue-800";
if (deal.deal_source === "street") return "bg-sky-50 text-sky-700";
return "bg-slate-100 text-slate-700";
}
export function DealsTable({ deals }: Props) { export function DealsTable({ deals }: Props) {
if (!deals.length) { if (!deals.length) {
@@ -20,6 +43,8 @@ export function DealsTable({ deals }: Props) {
); );
} }
const inferredStreet = inferStreetName(deals);
return ( return (
<div className="overflow-x-auto rounded-md border"> <div className="overflow-x-auto rounded-md border">
<table dir="rtl" className="w-full text-sm"> <table dir="rtl" className="w-full text-sm">
@@ -67,14 +92,10 @@ export function DealsTable({ deals }: Props) {
<span <span
className={ className={
"inline-block rounded-full px-2 py-0.5 text-xs " + "inline-block rounded-full px-2 py-0.5 text-xs " +
(d.deal_source === "same_building" proximityClass(d, inferredStreet)
? "bg-emerald-100 text-emerald-800"
: d.deal_source === "street"
? "bg-blue-100 text-blue-800"
: "bg-slate-100 text-slate-700")
} }
> >
{SOURCE_LABELS[d.deal_source] || d.deal_source} {proximityLabel(d, inferredStreet)}
</span> </span>
) : ( ) : (
"—" "—"