Files
nadlan-mcp/web/src/components/DealsTable.tsx
T
chaim 918e7dbe02 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>
2026-04-25 14:55:27 +00:00

112 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Deal } from "../api/types";
import { formatCurrencyILS, formatDate, formatNumber } from "../lib/utils";
interface Props {
deals: Deal[];
}
function inferStreetName(deals: Deal[]): string | null {
const freq: Record<string, number> = {};
for (const d of deals) {
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) {
if (!deals.length) {
return (
<div className="text-center py-12 text-muted-foreground">
לא נמצאו עסקאות באזור הזה
</div>
);
}
const inferredStreet = inferStreetName(deals);
return (
<div className="overflow-x-auto rounded-md border">
<table dir="rtl" className="w-full text-sm">
<thead className="bg-muted text-muted-foreground">
<tr>
<th className="p-3 text-start font-medium">תאריך</th>
<th className="p-3 text-start font-medium">כתובת</th>
<th className="p-3 text-start font-medium">סוג</th>
<th className="p-3 text-end font-medium">חדרים</th>
<th className="p-3 text-end font-medium">קומה</th>
<th className="p-3 text-end font-medium">שטח (מ"ר)</th>
<th className="p-3 text-end font-medium">מחיר</th>
<th className="p-3 text-end font-medium">מחיר/מ"ר</th>
<th className="p-3 text-end font-medium">גוש</th>
<th className="p-3 text-end font-medium">חלקה</th>
<th className="p-3 text-end font-medium">תת-חלקה</th>
<th className="p-3 text-start font-medium">קרבה</th>
</tr>
</thead>
<tbody>
{deals.map((d) => {
const street = d.streetNameHeb || "";
const houseNum = d.houseNum ?? "";
const settlement = d.settlementNameHeb || "";
const address = [street, houseNum, settlement].filter(Boolean).join(" ");
return (
<tr key={d.id} className="border-t hover:bg-accent/40">
<td className="p-3 whitespace-nowrap">{formatDate(d.deal_date)}</td>
<td className="p-3">{address || "—"}</td>
<td className="p-3">{d.property_type_description || "—"}</td>
<td className="p-3 text-end tabular-nums">{d.rooms ?? "—"}</td>
<td className="p-3 text-end tabular-nums">{d.floor ?? "—"}</td>
<td className="p-3 text-end tabular-nums">{formatNumber(d.asset_area)}</td>
<td className="p-3 text-end tabular-nums">
{formatCurrencyILS(d.deal_amount)}
</td>
<td className="p-3 text-end tabular-nums">
{formatCurrencyILS(d.price_per_sqm)}
</td>
<td className="p-3 text-end tabular-nums">{d.gushNum ?? "—"}</td>
<td className="p-3 text-end tabular-nums">{d.parcelNum ?? "—"}</td>
<td className="p-3 text-end tabular-nums">{d.subParcelNum ?? "—"}</td>
<td className="p-3">
{d.deal_source ? (
<span
className={
"inline-block rounded-full px-2 py-0.5 text-xs " +
proximityClass(d, inferredStreet)
}
>
{proximityLabel(d, inferredStreet)}
</span>
) : (
"—"
)}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}