/* ========================================================================= app.jsx — main app: hash routing, language switching, page composition ========================================================================= */ const { useState, useEffect, useMemo, useRef } = React; /* -------- Hash routing helpers -------- */ const ROUTES = { "": "home", "/": "home", "/cash": "cash", "/waqf-services": "waqf", "/government-employee":"gov", "/real-estate-liquidity": "liq" }; const useHashRoute = () => { const [route, setRoute] = useState(() => { const h = window.location.hash.replace(/^#/, ""); return ROUTES[h] || "home"; }); useEffect(() => { const onChange = () => { const h = window.location.hash.replace(/^#/, ""); setRoute(ROUTES[h] || "home"); window.scrollTo({ top: 0, behavior: "instant" }); track("page_view", { route: h || "/" }); }; window.addEventListener("hashchange", onChange); track("page_view", { route: window.location.hash.replace(/^#/, "") || "/" }); return () => window.removeEventListener("hashchange", onChange); }, []); return route; }; /* -------- Tracking placeholders (Meta / Snapchat / GA) -------- In production these IDs are filled and the SDKs are loaded in . Here we log to console so the wiring is visible. */ function track(event, payload = {}) { const tagged = { event, ...payload, _ts: Date.now() }; // Meta Pixel if (window.fbq) window.fbq("trackCustom", event, payload); // Snapchat Pixel if (window.snaptr) window.snaptr("track", event, payload); // GA4 if (window.gtag) window.gtag("event", event, payload); // visible log for the mockup console.log("[track]", tagged); } window.track = track; /* -------- Language hook -------- */ const useLang = () => { const [lang, setLang] = useState(() => localStorage.getItem("sn_lang") || "ar"); useEffect(() => { localStorage.setItem("sn_lang", lang); document.body.dir = window.I18N[lang].dir; document.body.dataset.lang = lang; document.documentElement.lang = lang; }, [lang]); return [lang, setLang]; }; /* -------- UI atoms -------- */ const Logo = ({ size = 36 }) => ( Sama Najd ); const TopBar = ({ lang, setLang, t }) => (
track("nav_logo_click")}>
{t.common.brand} {t.common.brandSub}
); /* -------- Hero -------- */ const Hero = ({ route, t, page }) => { const onWhatsApp = (e) => { track("whatsapp_click", { from: "hero", route }); e.preventDefault(); window.location.hash = window.location.hash; // no-op nav; in real site → wa.me link window.open("https://wa.me/966550650034", "_blank", "noopener"); }; const onApply = () => { track("cta_apply_click", { from: "hero", route }); const el = document.getElementById("lead-form"); if (el) { const y = el.getBoundingClientRect().top + window.scrollY - 60; window.scrollTo({ top: y, behavior: "smooth" }); } }; return (
{route !== "home" && (
{t.common.adTag} · {route.toUpperCase()}
)}
{page.eyebrow}

{page.h1_pre}{" "} {page.h1_pop} {page.h1_post ? <>
{page.h1_post} : null}

{page.sub}

{t.common.whatsappCta}
{page.artImg ? ( {page.artLabel} ) : (
{page.artTag}
{page.artLabel}
)}
{page.amount}
{page.amountLbl}
); }; /* -------- Services -------- */ const Services = ({ t, route }) => { const activeId = route === "home" ? null : route; return (
{t.sections.servicesEyebrow}

{t.sections.servicesTitle}

{t.sections.servicesLede}

{t.services.map(s => { const targetHash = s.id === "cash" ? "#/cash" : s.id === "waqf" ? "#/waqf-services" : s.id === "gov" ? "#/government-employee" : s.id === "liq" || s.id === "surplus" ? "#/real-estate-liquidity" : "#/"; const isActive = s.id === activeId || (s.id === "surplus" && route === "liq"); return ( track("service_card_click", { id: s.id })} >

{s.title}

{s.desc}

{t.common.orderNow}
); })}
); }; /* -------- Steps -------- */ const Steps = ({ t }) => (
{t.sections.stepsEyebrow}

{t.sections.stepsTitle}

{t.sections.stepsLede}

{t.steps.map((s, i) => (
{i + 1}
{s.title}
{s.sub}
))}
); /* -------- Lead form -------- */ const LeadForm = ({ t, route }) => { const [name, setName] = useState(""); const [mobile, setMobile] = useState(""); const [hasMortgage, setHM] = useState(null); const [employer, setEmp] = useState(null); const [errors, setErrors] = useState({}); const [sending, setSending] = useState(false); const [sent, setSent] = useState(false); // Pre-select gov for the government-employee landing useEffect(() => { if (route === "gov") setEmp("gov"); if (route === "cash" || route === "liq") setHM(true); }, [route]); const submit = (e) => { e.preventDefault(); const errs = {}; if (!name.trim()) errs.name = t.common.required; if (!/^05\d{8}$/.test(mobile.trim().replace(/\s|-/g, ""))) errs.mobile = t.common.invalidMobile; setErrors(errs); if (Object.keys(errs).length) { track("form_error", { errors: Object.keys(errs), route }); return; } setSending(true); track("form_submit", { route, hasMortgage: hasMortgage === null ? "unset" : hasMortgage, employer: employer || "unset", name_provided: !!name, mobile_provided: !!mobile }); // simulated network — real backend would replace this setTimeout(() => { setSending(false); setSent(true); track("form_submit_success", { route }); }, 900); }; if (sent) { return (

{t.common.submitted}

{t.common.submittedSub}

); } return (
{t.sections.formEyebrow}

{t.sections.formTitle}

{t.sections.formLede}

setName(e.target.value)} placeholder={t.common.namePh} className={errors.name ? "err" : ""} autoComplete="name" /> {errors.name && {errors.name}}
setMobile(e.target.value)} placeholder={t.common.mobilePh} className={errors.mobile ? "err" : ""} dir="ltr" autoComplete="tel" inputMode="numeric" /> {errors.mobile && {errors.mobile}}
); }; /* -------- Trust + Contact -------- */ const Trust = ({ t }) => { const onPhone = () => track("phone_click", { from: "trust" }); const onWA = () => track("whatsapp_click", { from: "trust" }); return (
{t.sections.trustEyebrow}

{t.sections.trustTitle}

{t.sections.trustLede}

{t.trust.map((x, i) => (
{x.title}
))}
{t.common.free}
{t.common.phone}
WhatsApp
{t.common.whatsapp}
{e.preventDefault(); track("social_click",{net:"ig"});}}> {e.preventDefault(); track("social_click",{net:"snap"});}}> {e.preventDefault(); track("social_click",{net:"tt"});}}> track("social_click",{net:"wa"})}>
); }; /* -------- Bottom nav rail (mockup-only — lets reviewers click between ad pages) -------- */ const NavRail = ({ route, t }) => { const items = [ { key: "home", hash: "#/", label: t.nav.home, icon: "house" }, { key: "cash", hash: "#/cash", label: t.nav.cash, icon: "cash" }, { key: "waqf", hash: "#/waqf-services", label: t.nav.waqf, icon: "unlock" }, { key: "gov", hash: "#/government-employee", label: t.nav.gov, icon: "badge" }, { key: "liq", hash: "#/real-estate-liquidity", label: t.nav.liq, icon: "trending" }, ]; return ( ); }; /* -------- Footer -------- */ const Foot = ({ t }) => ( ); /* -------- App root -------- */ const App = () => { const route = useHashRoute(); const [lang, setLang] = useLang(); const t = window.I18N[lang]; const page = t.pages[route] || t.pages.home; return (
); }; const root = ReactDOM.createRoot(document.getElementById("root")); root.render();