import { Deal } from "../api/types"; import { formatCurrencyILS, formatDate, formatNumber } from "../lib/utils"; interface Props { deals: Deal[]; resolvedAddress?: string; searchedBlock?: string; searchedPlot?: string; } // Extract street name from a Govmap address string like "הילדסהיימר 14, ירושלים". // Takes all leading tokens that contain no digits. Used as fallback only — // for parcel searches Govmap echoes back "גוש N חלקה M" with no street info. function streetFromAddress(address: string | undefined): string | null { if (!address) return null; const tokens = address.split(/[\s,]+/); const parts: string[] = []; for (const t of tokens) { if (/\d/.test(t)) break; if (t) parts.push(t); } return parts.length ? parts.join(" ") : null; } // Find the street name of the searched parcel by picking the deal with the // closest parcelNum within the same gush. Cadastral parcel numbers are usually // assigned along street frontage, so the nearest plot is almost always the // same street. function streetByClosestParcel( deals: Deal[], block: string | undefined, plot: string | undefined ): string | null { if (!plot) return null; const target = parseInt(plot, 10); if (!Number.isFinite(target)) return null; const blockNum = block ? parseInt(block, 10) : null; let best: { dist: number; street: string } | null = null; for (const d of deals) { if (!d.streetNameHeb || d.parcelNum == null) continue; if (blockNum !== null && d.gushNum !== blockNum) continue; const dist = Math.abs((d.parcelNum as number) - target); if (!best || dist < best.dist) { best = { dist, street: d.streetNameHeb }; } } return best?.street ?? null; } 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, resolvedAddress, searchedBlock, searchedPlot }: Props) { if (!deals.length) { return (
| תאריך | כתובת | סוג | חדרים | קומה | שטח (מ"ר) | מחיר | מחיר/מ"ר | גוש | חלקה | תת-חלקה | קרבה |
|---|---|---|---|---|---|---|---|---|---|---|---|
| {formatDate(d.deal_date)} | {address || "—"} | {d.property_type_description || "—"} | {d.rooms ?? "—"} | {d.floor ?? "—"} | {formatNumber(d.asset_area)} | {formatCurrencyILS(d.deal_amount)} | {formatCurrencyILS(d.price_per_sqm)} | {d.gushNum ?? "—"} | {d.parcelNum ?? "—"} | {d.subParcelNum ?? "—"} | {d.deal_source ? ( {proximityLabel(d, inferredStreet)} ) : ( "—" )} |