// Interactive Riyadh map page — the centerpiece const MapPage = ({ t, lang, selectedParcel, setSelectedParcel, setPage, setPreselectedServices }) => { const data = window.DAOOB_DATA; const [tool, setTool] = React.useState("pin"); // pin | draw | upload | clear const [basemap, setBasemap] = React.useState("street"); const [search, setSearch] = React.useState(""); const [filterZones, setFilterZones] = React.useState([]); const [heatmap, setHeatmap] = React.useState(true); const [layers, setLayers] = React.useState({ zoning: true, traffic: false, amenities: false, planning: false }); const toggleZone = (key) => { setFilterZones(prev => prev.includes(key) ? prev.filter(z => z !== key) : [...prev, key]); }; const toggleLayer = (key) => setLayers(l => ({ ...l, [key]: !l[key] })); const sel = data.parcels.find(p => p.id === selectedParcel); const visible = filterZones.length ? data.parcels.filter(p => filterZones.includes(p.zone)) : data.parcels; return (
{/* Left: tools */} {/* Center: map */}
{ // Drop a pin anywhere → snap to nearest parcel within range if (nearestId) setSelectedParcel(nearestId); }} /> {/* Heatmap toggle */} {/* Legend overlay */}
{t.map.legend}
    {[ { k: "mixed", lbl: t.map.legend_mixed }, { k: "commercial", lbl: t.map.legend_commercial }, { k: "residential", lbl: t.map.legend_residential }, { k: "industrial", lbl: t.map.legend_industrial }, { k: "govt", lbl: t.map.legend_govt }, ].map(x => (
  • {x.lbl}
  • ))}
{/* Right: detail panel */}
); }; const ParcelEmpty = ({ t }) => (

{t.map.no_select_t}

{t.map.no_select_d}

); const ParcelDetail = ({ sel, t, lang, data, setPage, setPreselectedServices }) => { const zone = data.zoningTypes[sel.zone]; const district = data.districts[sel.district]; const askPrice = sel.price ? `${(sel.price * sel.area / 1000).toFixed(1)}M ${t.map.sar}` : "—"; // 12-month price trend percentage change const trend = sel.priceTrend; const trendPct = trend ? Math.round(((trend[trend.length - 1] - trend[0]) / trend[0]) * 100) : null; // Format last transaction date const fmtDate = (d) => { if (!d) return null; const dt = new Date(d); return dt.toLocaleDateString(lang === "ar" ? "ar-SA" : "en-GB", { day: "numeric", month: "short", year: "numeric" }); }; return (
{/* Header */}
{t.map.parcel} · {sel.id}

{district[lang]}

{zone[lang]} · {(lang === "ar" ? "ملكية " : "Ownership: ") + (sel.owner === "Govt." ? (lang === "ar" ? "حكومية" : "Govt.") : (lang === "ar" ? "خاصة" : "Private"))}
{/* Price headline */} {sel.price && (
{askPrice} {sel.price.toLocaleString()} {lang === "ar" ? "ر.س/م²" : "SAR/m²"}
{trendPct !== null && (
= 0 ? "up" : "down")}> {trendPct >= 0 ? "↑" : "↓"} {Math.abs(trendPct)}% {lang === "ar" ? "آخر 12 شهر" : "12 mo."}
)}
)} {/* 12-month price trend sparkline */} {trend && } {/* Quick facts grid */}
{t.map.area}
{sel.area.toLocaleString()} {t.map.sqm}
{lang === "ar" ? "التصنيف" : "Zoning"}
{zone[lang]}
{sel.frontages &&
{lang === "ar" ? "الواجهات" : "Frontages"}
{sel.frontages}
} {sel.width &&
{lang === "ar" ? "العرض × العمق" : "W × D"}
{sel.width} × {sel.depth} m
} {sel.metro &&
{lang === "ar" ? "أقرب محطة مترو" : "Nearest metro"}
{sel.metro.station} ({sel.metro.line}) · {sel.metro.distance_m}m
}
{/* Building regulations */} {sel.restrictions && (
{lang === "ar" ? "اشتراطات البناء" : "Building regulations"}
FAR{sel.restrictions.far}
{lang === "ar" ? "نسبة البناء" : "Coverage"}{Math.round(sel.restrictions.coverage * 100)}%
{lang === "ar" ? "ارتفاع أقصى" : "Max height"}{sel.restrictions.height}m
{lang === "ar" ? "الارتداد" : "Setback"}{sel.restrictions.setback}m
)} {/* Utilities */} {sel.utilities && (
{lang === "ar" ? "البنية التحتية" : "Utilities"}
{Object.entries({ water: lang === "ar" ? "ماء" : "Water", sewage: lang === "ar" ? "صرف" : "Sewage", electricity: lang === "ar" ? "كهرباء" : "Electricity", gas: lang === "ar" ? "غاز" : "Gas", fiber: lang === "ar" ? "ألياف" : "Fiber", }).map(([k, lbl]) => (
{sel.utilities[k] ? "✓" : "—"} {lbl}
))}
)} {/* Last transaction */} {sel.lastTx && (
{lang === "ar" ? "آخر معاملة" : "Last transaction"}
{lang === "ar" ? "القيمة" : "Value"} {(sel.lastTx.price / 1_000_000).toFixed(1)}M {lang === "ar" ? "ر.س" : "SAR"}
{lang === "ar" ? "التاريخ" : "Date"} {fmtDate(sel.lastTx.date)}
{sel.compsCount > 0 && (
{lang === "ar" ? "معاملات مشابهة" : "Comparable txns"} {sel.compsCount} {lang === "ar" ? "آخر 12 شهر" : "last 12mo"}
)}
)} {/* AI Score */} {sel.score && (
{sel.score}
{t.map.ai_score}
{sel.score >= 75 ? (lang === "ar" ? "ممتاز" : "Excellent") : sel.score >= 60 ? (lang === "ar" ? "جيد" : "Strong") : (lang === "ar" ? "متوسط" : "Moderate")}
)}
{t.map.ai_summary} {t.map.ai_summary_body}
{/* Services — pick one to request */}
{lang === "ar" ? "اختر دراسة لهذه القطعة" : "Choose a study for this parcel"} {t.services.list.length} {lang === "ar" ? "خدمات" : "services"}
{t.services.list.map((s, i) => ( ))}
); }; // 12-month price trend sparkline const PriceSpark = ({ trend, lang }) => { const W = 280, H = 50, pad = 4; const min = Math.min(...trend); const max = Math.max(...trend); const sx = (i) => pad + (i / (trend.length - 1)) * (W - pad * 2); const sy = (v) => H - pad - ((v - min) / (max - min || 1)) * (H - pad * 2); const d = trend.map((v, i) => `${i === 0 ? "M" : "L"} ${sx(i)} ${sy(v)}`).join(" "); const area = d + ` L ${sx(trend.length - 1)} ${H} L ${sx(0)} ${H} Z`; return (
{lang === "ar" ? "قبل 12 شهر" : "12 mo. ago"} {trend[0]} → {trend[trend.length - 1]} {lang === "ar" ? "ر.س/م²" : "SAR/m²"}
); }; Object.assign(window, { MapPage });