/* global React, ReactDOM, Topbar, Footer, Splash, PageHome, PageGroove, PageAbout, PageShows, PageMedia, PageContact */ const { useState, useEffect } = React; // Single-page layout: all sections live on one page. Header nav and footer links // call setPage(id), which smooth-scrolls to
and updates the // active nav state via IntersectionObserver below. function App() { const [page, setPage] = useState('home'); // setPage scrolls to a section instead of swapping pages. const goToSection = (id) => { const el = document.getElementById(id); if (!el) return; const topbarH = document.querySelector('.topbar')?.offsetHeight || 0; const y = el.getBoundingClientRect().top + window.scrollY - topbarH + 1; window.smoothScrollTo(y); }; // Track which section is currently in view to highlight the nav. useEffect(() => { const ids = ['home', 'groove', 'about', 'media', 'shows', 'contact']; const sections = ids.map(id => document.getElementById(id)).filter(Boolean); if (!sections.length) return; const topbarH = document.querySelector('.topbar')?.offsetHeight || 80; const io = new IntersectionObserver((entries) => { // Pick the entry closest to the top that is intersecting. const visible = entries .filter(e => e.isIntersecting) .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top); if (visible[0]) setPage(visible[0].target.id); }, { // A horizontal band just below the topbar. Whatever section enters this // band becomes "active". rootMargin: `-${topbarH + 8}px 0px -65% 0px`, threshold: 0, }); sections.forEach(s => io.observe(s)); return () => io.disconnect(); }, []); // Besucher-Tracking: feuert wenn Nutzer 1.5s auf einer Sektion bleibt useEffect(() => { const t = setTimeout(() => { fetch('/api/track.php', { method: 'POST', body: new URLSearchParams({ page }), }).catch(() => {}); }, 1500); return () => clearTimeout(t); }, [page]); // Honor an initial hash like #shows. useEffect(() => { if (location.hash) { const id = location.hash.slice(1); // wait for fonts/layout to settle setTimeout(() => goToSection(id), 50); } }, []); return (
); } ReactDOM.createRoot(document.getElementById('root')).render();