/* ============================================================
AACSH — Shared components: logo, nav, footer, appointment modal
============================================================ */
const { useState, useEffect, useRef, useMemo, useCallback } = React;
/* ============================================================
FlameMark — original SVG (NOT the raster logo). Refined for hospital tone.
============================================================ */
function FlameMark({ size = 28, mono = false }) {
const id = `g-${Math.random().toString(36).slice(2, 7)}`;
return (
{/* Left flame petal */}
{/* Right flame petal */}
);
}
/* ============================================================
Logo lockup
============================================================ */
function Logo({ size = 30, stacked = false, mono = false }) {
return (
American Academy of
Cosmetic Surgery Hospital
);
}
/* ============================================================
Top nav with mega-menu
============================================================ */
function TopNav({ onNavigate, currentPath, onBook }) {
const [open, setOpen] = useState(null); // "departments" | "doctors" | null
const [scrolled, setScrolled] = useState(false);
const [lang, setLang] = useState("EN");
useEffect(() => {
const fn = () => setScrolled(window.scrollY > 24);
window.addEventListener("scroll", fn);
return () => window.removeEventListener("scroll", fn);
}, []);
const depts = window.AACSH_DATA.departments;
return (
setOpen(null)}>
{/* Top utility row */}
Open today · 09:00 — 21:00
Building 73, Dubai Healthcare City
{/* Main nav row */}
{ onNavigate("/"); setOpen(null); }} style={{ display: "flex" }}>
setOpen("departments")} caret />
{ onNavigate("/doctors"); setOpen(null); }} />
{ onNavigate("/accreditation"); setOpen(null); }} />
{ onNavigate("/before-after"); setOpen(null); }} />
{ onNavigate("/medical-tourism"); setOpen(null); }} />
{ onNavigate("/about"); setOpen(null); }} />
{ onNavigate("/contact"); setOpen(null); }} />
{/* Mega menu — departments */}
{open === "departments" && (
Care under one roof
Ten specialities. One JCI-accredited hospital.
Cosmetic & plastic surgery is our anchor — surrounded by medical, aesthetic and wellness specialities so patients can receive coordinated care in a single environment.
{ onNavigate("/departments"); setOpen(null); }}>
All departments →
{depts.map(d => (
{ onNavigate(`/departments/${d.slug}`); setOpen(null); }}
style={{
textAlign: "left", padding: "14px 16px",
borderRadius: 10, transition: "background 160ms",
display: "flex", flexDirection: "column", gap: 4,
}}
onMouseEnter={(e) => e.currentTarget.style.background = "var(--mist)"}
onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}
>
{d.name}
{d.kind === "surgical" && (
Surgical
)}
{d.procedures.length} procedures
))}
)}
);
}
function NavItem({ label, active, onClick, onMouseEnter, caret }) {
return (
{label}
{caret && }
{active && }
);
}
function LangSwitch({ lang, setLang }) {
const [open, setOpen] = useState(false);
const langs = ["EN", "AR", "RU", "ZH"];
return (
setOpen(false)}>
setOpen(!open)} onMouseEnter={() => setOpen(true)} style={{
display: "inline-flex", gap: 4, alignItems: "center", padding: "4px 6px",
}}>
{lang}
{open && (
{langs.map(l => (
{ setLang(l); setOpen(false); }} style={{
display: "block", width: "100%", textAlign: "left",
padding: "8px 10px", borderRadius: 4, fontSize: 12,
background: lang === l ? "var(--mist)" : "transparent",
color: lang === l ? "var(--plum)" : "var(--ink)",
fontWeight: lang === l ? 500 : 400,
}}>
{{EN: "English", AR: "العربية", RU: "Русский", ZH: "中文"}[l]}
))}
)}
);
}
/* ============================================================
Trust strip — JCI + DHCC + DHA marks
============================================================ */
function TrustStrip({ compact = false }) {
const items = window.AACSH_DATA.accreditations;
return (
{items.map((a, i) => (
{a.name}
{!compact && (
{a.detail}
)}
))}
);
}
function AccreditationMark({ code }) {
const sx = {
width: 44, height: 44,
borderRadius: 999,
display: "flex", alignItems: "center", justifyContent: "center",
fontFamily: "var(--font-serif)",
fontSize: 13, fontWeight: 500,
flexShrink: 0,
};
const styles = {
JCI: { ...sx, background: "var(--plum)", color: "white", letterSpacing: 0.5 },
DHCC: { ...sx, background: "white", border: "1.5px solid var(--plum)", color: "var(--plum)", fontSize: 11 },
DHA: { ...sx, background: "var(--cream)", border: "1.5px solid var(--gold)", color: "var(--gold)" },
MOH: { ...sx, background: "white", border: "1.5px solid var(--ink)", color: "var(--ink)" },
};
return {code}
;
}
/* ============================================================
Appointment modal — multi-step
============================================================ */
function AppointmentModal({ open, onClose, prefillDept, prefillProcedure }) {
const [step, setStep] = useState(0);
const [data, setData] = useState({
dept: "", procedure: "",
date: "", time: "",
firstName: "", lastName: "",
phone: "", email: "",
note: "",
international: false,
});
useEffect(() => {
if (open) {
setStep(0);
setData(d => ({
...d,
dept: prefillDept || d.dept,
procedure: prefillProcedure || d.procedure,
}));
}
}, [open, prefillDept, prefillProcedure]);
if (!open) return null;
const update = (k, v) => setData(d => ({ ...d, [k]: v }));
const dept = window.AACSH_DATA.departments.find(d => d.slug === data.dept);
const next = () => setStep(s => Math.min(s + 1, 3));
const back = () => setStep(s => Math.max(s - 1, 0));
const canProceed = () => {
if (step === 0) return !!data.dept;
if (step === 1) return !!data.date && !!data.time;
if (step === 2) return !!data.firstName && !!data.phone;
return true;
};
return (
e.stopPropagation()} style={{
width: "100%", maxWidth: 720,
background: "white",
borderRadius: 20,
overflow: "hidden",
maxHeight: "92vh",
display: "flex", flexDirection: "column",
boxShadow: "0 50px 100px rgba(22,18,28,0.4)",
}}>
{/* Header */}
Step {step + 1} of 4
{["Choose care", "Pick a date", "Your details", "Confirmed"][step]}
{/* Stepper */}
{[0,1,2,3].map(i => (
))}
{/* Body */}
{step === 0 && (
)}
{step === 1 && (
)}
{step === 2 && (
)}
{step === 3 && (
)}
{/* Footer */}
{step < 3 ? (
<>
Minimal details only · we never collect medical history in a form
>
) : (
A care coordinator will be in touch within one business hour.
)}
{step > 0 && step < 3 && (
← Back
)}
{step < 3 ? (
{step === 2 ? "Confirm request" : "Continue"} →
) : (
Close
)}
);
}
function BookingStepCare({ data, update }) {
const depts = window.AACSH_DATA.departments;
const dept = depts.find(d => d.slug === data.dept);
return (
Department
{depts.map(d => (
update("dept", d.slug)} style={{
padding: "12px 14px",
textAlign: "left",
borderRadius: 10,
border: "1px solid " + (data.dept === d.slug ? "var(--plum)" : "var(--line)"),
background: data.dept === d.slug ? "var(--mist)" : "white",
fontSize: 13.5,
transition: "all 160ms",
}}>
{d.name}
{d.kind === "surgical" ? "Surgical · risks disclosed" : d.kind === "wellness" ? "Wellness" : "Medical"}
))}
{dept && (
Procedure / treatment (optional)
{dept.procedures.map(p => (
update("procedure", p.slug)}
className="chip"
style={{
cursor: "pointer",
background: data.procedure === p.slug ? "var(--plum)" : "var(--mist)",
color: data.procedure === p.slug ? "white" : "var(--plum)",
}}>
{p.name}
))}
)}
);
}
function BookingStepDate({ data, update }) {
const today = new Date();
const days = [...Array(14)].map((_, i) => {
const d = new Date(today);
d.setDate(d.getDate() + i);
return d;
});
const times = ["09:30", "10:30", "11:30", "13:00", "14:30", "16:00", "17:00", "18:30", "20:00"];
const fmtDate = d => d.toISOString().slice(0, 10);
return (
Preferred date
{days.map(d => {
const iso = fmtDate(d);
const isSel = data.date === iso;
return (
update("date", iso)} style={{
padding: "10px 4px", textAlign: "center",
borderRadius: 8,
border: "1px solid " + (isSel ? "var(--plum)" : "var(--line)"),
background: isSel ? "var(--plum)" : "white",
color: isSel ? "white" : "var(--ink)",
transition: "all 160ms",
}}>
{d.toLocaleDateString("en-US", { weekday: "short" })}
{d.getDate()}
{d.toLocaleDateString("en-US", { month: "short" })}
);
})}
Time
{times.map(t => (
update("time", t)} style={{
padding: "10px 4px", textAlign: "center",
borderRadius: 8,
border: "1px solid " + (data.time === t ? "var(--plum)" : "var(--line)"),
background: data.time === t ? "var(--plum)" : "white",
color: data.time === t ? "white" : "var(--ink)",
fontSize: 14,
transition: "all 160ms",
fontFamily: "var(--font-mono)",
}}>
{t}
))}
Hours are 09:00–21:00, seven days a week. Times shown are provisional; a coordinator confirms by phone or email before any visit is locked in.
);
}
function BookingStepDetails({ data, update }) {
return (
update("firstName", v)} />
update("lastName", v)} />
update("phone", v)} placeholder="+971 ..." />
update("email", v)} placeholder="you@example.com" type="email" />
update("note", v)} multiline rows={3}
placeholder="Best time to call, preferred language, etc." />
update("international", e.target.checked)} style={{ marginTop: 3 }} />
I'm travelling from abroad
A medical-tourism coordinator will reach out with visa, accommodation and transfer support.
Please do not share medical history through this form. Clinical details are taken securely during your consultation, not in an unencrypted web form.
);
}
function BookingStepConfirm({ data, dept }) {
const proc = dept?.procedures.find(p => p.slug === data.procedure);
return (
Request received
Thank you, {data.firstName || "patient"}. A coordinator will contact you within one business hour to confirm your appointment.
{proc &&
}
{data.international && International patient} />}
);
}
function Row({ k, v }) {
return (
{k}
{v || "—"}
);
}
function Field({ label, value, onChange, multiline, rows, placeholder, type }) {
return (
{label}
{multiline ? (
);
}
/* ============================================================
Footer
============================================================ */
function Footer({ onNavigate, onBook }) {
const depts = window.AACSH_DATA.departments;
const c = window.AACSH_DATA.contact;
return (
A JCI-accredited multi-specialty hospital in Dubai Healthcare City, with cosmetic and plastic surgery as its anchor speciality.
{["Instagram", "Facebook", "LinkedIn", "TikTok", "X"].map(s => (
{s[0]}
))}
Departments
{depts.slice(0, 6).map(d => (
onNavigate(`/departments/${d.slug}`)}
style={{ textAlign: "left", fontSize: 13.5, color: "rgba(255,255,255,0.78)" }}>
{d.name}
))}
onNavigate("/departments")} style={{ textAlign: "left", fontSize: 13.5, color: "var(--gold-soft)", marginTop: 4 }}>
See all 10 →
Visit
onNavigate("/doctors")} style={{ textAlign: "left", color: "rgba(255,255,255,0.78)" }}>Our doctors
onNavigate("/accreditation")} style={{ textAlign: "left", color: "rgba(255,255,255,0.78)" }}>Accreditation
onNavigate("/medical-tourism")} style={{ textAlign: "left", color: "rgba(255,255,255,0.78)" }}>Medical tourism
onNavigate("/before-after")} style={{ textAlign: "left", color: "rgba(255,255,255,0.78)" }}>Before & after
onNavigate("/about")} style={{ textAlign: "left", color: "rgba(255,255,255,0.78)" }}>About AACSH
onNavigate("/contact")} style={{ textAlign: "left", color: "rgba(255,255,255,0.78)" }}>Contact
Hospital
{c.address}
{c.addressLine2}
Make an appointment
© {new Date().getFullYear()} American Academy of Cosmetic Surgery Hospital (AACSH) FZ-LLC. All rights reserved.
DHCC establishment licence · DHA-supervised clinicians · JCI-accredited · MOH-compliant communications
);
}
Object.assign(window, {
FlameMark, Logo, TopNav, TrustStrip, AppointmentModal, Footer,
});