/* global React, ReactDOM */
const { useState, useEffect, useRef } = React;
function SectionTitle({ kicker, title, sub }) {
return (
{kicker}
{title}
{sub ?
{sub}
: null}
);
}
function ChiliIcon() {
return (
);
}
function MenuItem({ item, twoPrice, single }) {
return (
{item.n}
{item.spicy ? : null}
{item.d ?
{item.d}
: null}
{item.a ? (
{item.a.split(",").map((x, i) => (
{x.trim()}
))}
) : null}
{twoPrice ? (
<>
{item.p1}
{item.p2}
>
) : (
€ {item.p}
)}
);
}
function MenuSection({ section }) {
const twoPrice = !!section.twoPrice || !!section.headers;
return (
{section.headers && (
{section.headers[0]}
{section.headers[1]}
)}
{section.items.map((it, i) => (
))}
);
}
function MenuTabBar({ tabs, activeId, onSelect }) {
const ref = useRef(null);
useEffect(() => {
// Scroll active tab into view horizontally
const el = ref.current?.querySelector(`[data-tab="${activeId}"]`);
if (el) el.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
}, [activeId]);
return (
);
}
function MenuPage() {
const data = window.MENU_DATA;
const [mode, setMode] = useState("food"); // "food" | "drinks"
const sections = mode === "food" ? data.food : data.drinks;
const [activeId, setActiveId] = useState(sections[0].id);
// observe sections for tab highlight
useEffect(() => {
const observer = new IntersectionObserver(
entries => {
const visible = entries
.filter(e => e.isIntersecting)
.sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
if (visible.length) setActiveId(visible[0].target.id);
},
{ rootMargin: "-30% 0px -60% 0px", threshold: 0 }
);
sections.forEach(s => {
const el = document.getElementById(s.id);
if (el) observer.observe(el);
});
return () => observer.disconnect();
}, [mode, sections]);
const onSelectTab = id => {
const el = document.getElementById(id);
if (el) {
const y = el.getBoundingClientRect().top + window.scrollY - 160;
window.scrollTo({ top: y, behavior: "smooth" });
}
};
const onModeSwitch = next => {
setMode(next);
setActiveId((next === "food" ? data.food : data.drinks)[0].id);
window.scrollTo({ top: 0, behavior: "smooth" });
};
return (
Drop's Fregene · Menu
Tutto il
menu.
in italiano
Cucina aperta tutto il giorno. Ingredienti freschi, preparazioni
artigianali, ricette che ci piace mangiare per primi.
{sections.map(s => )}
{/* Allergens / footnotes */}
);
}
ReactDOM.createRoot(document.getElementById("root")).render();