/* Cordish Plaza — app shell. Variant LOCKED to the client's choice: hero WITH renders, accents GOLD + TEAL. The dev tweak panel is removed; the shop list loads LIVE from the ERPNext-backed proxy (api/shops.php). Amenities, location and the "who's already here" mix come from plaza-data.js (editorial, not per-unit). */ const { useState, useEffect } = React; const VARIANT = { heroMode: "render", accent: "warm" }; // render on; "warm" = gold + teal function scrollToId(id) { const el = document.getElementById(id); if (!el) return; const y = el.getBoundingClientRect().top + window.scrollY - 56; window.scrollTo({ top: y, behavior: "smooth" }); } const GALLERY = [ { src: "assets/plaza-render.jpeg", kind: "render", alt: "3D render of Cordish Plaza, glass-front design" }, { src: "assets/plaza-render-alt.jpeg", kind: "render", alt: "3D render of Cordish Plaza, alternative colour study" }, { src: "assets/floor-plan.png", kind: "plan", alt: "Ground floor plan of Cordish Plaza" } ]; function PlazaApp() { const P = window.PLAZA; const [shops, setShops] = useState(null); // null = loading const [interestedMix, setInterestedMix] = useState([]); // live "businesses interested so far" const [selected, setSelected] = useState(new Set()); useEffect(() => { let alive = true; fetch("api/shops.php", { headers: { Accept: "application/json" } }) .then(r => (r.ok ? r.json() : Promise.reject(r.status))) .then(data => { if (alive) setShops(Array.isArray(data) ? data : []); }) .catch(() => { if (alive) setShops([]); }); // graceful: empty -> all-leased state fetch("api/interest-summary.php", { headers: { Accept: "application/json" } }) .then(r => (r.ok ? r.json() : Promise.reject(r.status))) .then(data => { if (alive && Array.isArray(data)) setInterestedMix(data.map(label => ({ label }))); }) .catch(() => {}); // strip just stays hidden on failure return () => { alive = false; }; }, []); if (shops === null) { return React.createElement("div", { style: { minHeight: "60vh", display: "grid", placeItems: "center", color: "var(--cd-muted)", fontFamily: "var(--font-body)", fontSize: 15 } }, "Loading available shops…"); } const availableShops = shops.filter(s => s.status === "Available"); const leased = availableShops.length === 0; const count = availableShops.length; const minRent = availableShops.length ? Math.min.apply(null, availableShops.map(s => s.monthly_rent)) : 0; const copy = { headline: "Your space at Cordish Plaza.", sub: "A new retail plaza in Oyibi, with shops available now. Find a unit, check the rent, and tell us it is yours." }; const goForm = () => scrollToId("interest"); const goShops = () => scrollToId("shops"); return React.createElement("div", { "data-accent": VARIANT.accent }, React.createElement(Header, { onExpress: goForm }), React.createElement(Hero, { mode: VARIANT.heroMode, copy, gallery: GALLERY, onExpress: goForm, onViewShops: goShops }), React.createElement(Facts, { count, minRent, location: P.location, leased }), React.createElement(Why, { amenities: P.amenities }), React.createElement(Leasing, { shops, selected, setSelected, mix: interestedMix, leased, badgePos: "top", perRow: 3, badgeFill: false, badgeIcon: false, btnWide: true }), React.createElement(Footer, null) ); } ReactDOM.createRoot(document.getElementById("plaza-root")).render(React.createElement(PlazaApp));