// Biere — Karussell, Filter, Geschmacksprofil const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "show_grain": true } /*EDITMODE-END*/; const Profile = ({ profile, animated = true }) => { const rows = [ { k: "malz", l: "Malz" }, { k: "hopfen", l: "Hopfen" }, { k: "bitter", l: "Bittere" }, { k: "sauer", l: "Säure" }, { k: "koerper", l: "Körper" }]; return (
{rows.map((r) =>
{r.l}
{Math.round((profile[r.k] || 0) * 100)}
)}
); }; const Carousel = ({ beers }) => { const [idx, setIdx] = React.useState(0); const [dir, setDir] = React.useState(1); const [animKey, setAnimKey] = React.useState(0); React.useEffect(() => {setIdx(0);}, [beers.length]); const go = (d) => { setDir(d); setIdx((i) => (i + d + beers.length) % beers.length); setAnimKey((k) => k + 1); }; if (!beers.length) { return
Keine Biere in dieser Kategorie.
; } const b = beers[idx]; return (
{String(idx + 1).padStart(2, "0")} / {String(beers.length).padStart(2, "0")}
{b.style} · Charge {b.batch}

{b.name}

{b.tagline}

{b.description}

{b.abv}%Vol.
{b.ibu}IBU
33clFlasche
passt zu {b.pairs.join(" · ")}
); }; const BeerCard = ({ beer }) => { const [hover, setHover] = React.useState(false); return ( setHover(true)} onMouseLeave={() => setHover(false)} style={{ textDecoration: "none", scrollMarginTop: 100 }}>
{beer.style} · {beer.abv}% Vol. · {beer.ibu} IBU

{beer.name}

{beer.tagline}

); }; const App = () => { const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS); const [filter, setFilter] = React.useState("alle"); const [beers, setBeers] = React.useState(window.BEERS); React.useEffect(() => { if (window.beersReady) window.beersReady.then(setBeers); }, []); const filtered = filter === "alle" ? beers : beers.filter((b) => b.styleClass === filter); const styles = [ { id: "alle", label: "Alle Sorten" }, { id: "ipa", label: "IPA" }, { id: "stout", label: "Stout" }, { id: "sauer", label: "Sauerbier" }]; return (
); }; ReactDOM.createRoot(document.getElementById("app")).render();