/* app.jsx — main composition + hash routing */
function App() {
const bookingRef = useRef(null);
const [route, setRoute] = useState(getRoute());
// Listen for hash changes (article navigation, back/forward).
useEffect(() => {
const onHash = () => setRoute(getRoute());
window.addEventListener("hashchange", onHash);
return () => window.removeEventListener("hashchange", onHash);
}, []);
// When we land back on the home page, honor any pending scroll target
// (set when a nav/section link was clicked from a subpage).
useEffect(() => {
if (route.name !== "home") return;
let pending = null;
try { pending = sessionStorage.getItem("vd_scrollTo"); } catch (e) {}
if (!pending) return;
try { sessionStorage.removeItem("vd_scrollTo"); } catch (e) {}
setTimeout(() => {
if (pending === "#top") { window.scrollTo({ top: 0, behavior: "smooth" }); return; }
const el = document.querySelector(pending);
if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 80, behavior: "smooth" });
}, 90);
}, [route]);
// Navigate from a subpage back to a section on the landing page.
const goHome = useCallback((hash) => {
try { if (hash) sessionStorage.setItem("vd_scrollTo", hash); } catch (e) {}
if (window.location.hash) window.location.hash = "";
else setRoute({ name: "home" });
}, []);
const onBookClick = useCallback(() => {
const el = document.getElementById("contacto");
if (el) {
window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 60, behavior: "smooth" });
} else {
// We're on a subpage: return home, then scroll to contact.
goHome("#contacto");
}
}, [goHome]);
if (route.name === "article") {
const article = findArticle(route.slug);
if (article) {
return (
);
}
// Unknown slug: fall through to the landing page.
}
return (
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render();