// app.jsx
// Mounts the Tweaks panel (palette/density/hero/RTL) and the multi-step Book-a-Tour modal.
const { useState, useEffect, useMemo, useCallback } = React;
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"palette": "redwood",
"density": "standard",
"heroLayout": "split",
"rtl": false,
"showFab": true
}/*EDITMODE-END*/;
const PALETTE_OPTS = [
["#6E1F2D", "#FAF3E6", "#7B8E5E"], // redwood (default)
["#5A1620", "#F6EDE0", "#A36C24"], // bordeaux
["#4A6240", "#F6F1E4", "#6E1F2D"], // sage-led
["#1F2A2B", "#F2EEE5", "#B57928"], // ink
];
const PALETTE_NAMES = ["redwood", "bordeaux", "sage", "ink"];
const BRANCHES = [
{ id: "palm-jumeirah", name: "Palm Jumeirah", area: "Golden Mile, Building 8", phone: "04 422 8581", waText: "Palm%20Jumeirah" },
{ id: "al-garhoud", name: "Al Garhoud", area: "Villa 45, 20 C Street · MEAB", phone: "04 282 7046", waText: "Al%20Garhoud" },
{ id: "jumeirah-park", name: "Jumeirah Park", area: "Level 1, East Pavilion", phone: "04 453 8688", waText: "Jumeirah%20Park" },
{ id: "al-furjan", name: "Al Furjan", area: "West Pavilion · new campus", phone: "04 886 0227", waText: "Al%20Furjan" },
{ id: "tilal-al-ghaf", name: "Tilal Al Ghaf", area: "Tilal Al Ghaf community", phone: "050 213 8502", waText: "Tilal%20Al%20Ghaf" },
];
const AGE_GROUPS = [
"3 – 12 months · Babies",
"1 – 2 years · Toddlers",
"2 – 3 years · Preschool",
"3 – 4 years · Foundation",
"4 – 6 years · Advanced Montessori",
];
// ────────────────────────────────────────────────────────────────────────────
// BOOK A TOUR MODAL
// ────────────────────────────────────────────────────────────────────────────
function TourModal({ open, prefill, onClose }) {
const [step, setStep] = useState(0);
const [branch, setBranch] = useState(prefill?.branch || "palm-jumeirah");
const [age, setAge] = useState(prefill?.age || AGE_GROUPS[2]);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const [date, setDate] = useState("");
const [child, setChild] = useState("");
useEffect(() => {
if (open) {
setStep(0);
if (prefill?.branch) setBranch(prefill.branch);
if (prefill?.age) setAge(prefill.age);
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "";
}
return () => { document.body.style.overflow = ""; };
}, [open, prefill]);
useEffect(() => {
if (!open) return;
const onKey = (e) => {
if (e.key === "Escape") onClose();
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
}, [open, onClose]);
if (!open) return null;
const selectedBranch = BRANCHES.find(b => b.id === branch) || BRANCHES[0];
const waLink = `https://wa.me/971502138502?text=Hi%20Redwood%2C%20I%27d%20like%20to%20book%20a%20tour%20at%20${selectedBranch.waText}%20for%20my%20child%20(${encodeURIComponent(age)})`;
const next = () => setStep(s => Math.min(s + 1, 3));
const back = () => setStep(s => Math.max(s - 1, 0));
const submit = (e) => { e?.preventDefault?.(); setStep(3); };
return (
{ if (e.target === e.currentTarget) onClose(); }}>
Step {step === 3 ? 3 : step + 1} of 3
= 1 ? "is-on" : ""}`}>
= 0 ? "is-on" : ""}`}>
= 2 ? "is-on" : ""}`}>
{step === 0 && (
<>
Choose a branch.
Tours happen at the branch — pick the one closest to home.
{BRANCHES.map(b => (
))}
>
)}
{step === 1 && (
<>
About your child.
So we can show you the right classroom.
>
)}
{step === 2 && (
)}
{step === 3 && (
✓
Your tour is requested.
A guide from {selectedBranch.name} will confirm your slot within one working day. Keep an eye on email or WhatsApp.
)}
);
}
// ────────────────────────────────────────────────────────────────────────────
// TWEAKS APP
// ────────────────────────────────────────────────────────────────────────────
function TweaksApp() {
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
// Apply tweaks to root
useEffect(() => {
document.documentElement.setAttribute("data-palette", t.palette);
document.documentElement.setAttribute("data-density", t.density);
document.documentElement.setAttribute("dir", t.rtl ? "rtl" : "ltr");
const hero = document.querySelector(".hero");
if (hero) hero.setAttribute("data-layout", t.heroLayout);
const fab = document.getElementById("wafab");
if (fab) fab.style.display = t.showFab ? "" : "none";
}, [t]);
return (
{
const idx = PALETTE_OPTS.findIndex(p => p[0] === arr[0]);
if (idx >= 0) setTweak("palette", PALETTE_NAMES[idx]);
}}
/>
setTweak("density", v)}
/>
setTweak("heroLayout", v)}
/>
setTweak("rtl", v)}
/>
setTweak("showFab", v)}
/>
);
}
// ────────────────────────────────────────────────────────────────────────────
// ROOT — wires modal triggers + mounts apps
// ────────────────────────────────────────────────────────────────────────────
function ModalRoot() {
const [open, setOpen] = useState(false);
const [prefill, setPrefill] = useState({});
const openModal = useCallback((data = {}) => {
setPrefill(data);
setOpen(true);
}, []);
useEffect(() => {
const onClick = (e) => {
const t = e.target.closest('[data-action="open-tour"]');
if (t) {
e.preventDefault();
const branch = t.dataset.branch;
openModal(branch ? { branch } : {});
return;
}
const bp = e.target.closest('[data-action="open-branch-placeholder"]');
if (bp) {
e.preventDefault();
const branch = bp.dataset.branch;
openModal({ branch });
}
};
document.addEventListener("click", onClick);
return () => document.removeEventListener("click", onClick);
}, [openModal]);
// Quick-tour form on home page
useEffect(() => {
const f = document.querySelector('[data-form="quick-tour"]');
if (!f) return;
const onSub = (e) => {
e.preventDefault();
const branch = f.querySelector('[name="branch"]').value;
const age = f.querySelector('[name="age"]').value;
openModal({ branch, age });
};
f.addEventListener("submit", onSub);
return () => f.removeEventListener("submit", onSub);
}, [openModal]);
// Locale buttons (visual only; persist via tweak when RTL pressed)
useEffect(() => {
const onClick = (e) => {
const btn = e.target.closest('.loc-btn');
if (!btn) return;
document.querySelectorAll('.loc-btn').forEach(b => b.classList.remove('is-on'));
btn.classList.add('is-on');
const lang = btn.dataset.lang;
document.documentElement.lang = lang;
};
document.addEventListener('click', onClick);
return () => document.removeEventListener('click', onClick);
}, []);
return setOpen(false)} />;
}
// Mount
ReactDOM.createRoot(document.getElementById("tour-root")).render();
ReactDOM.createRoot(document.getElementById("tweaks-root")).render();