// App shell — routing, cart state, chrome, toast.
(function () {
if (typeof React === "undefined") return;
const DS = window.VElaStvNajmanDesignSystem_bc3fc2;
const Icon = window.VNIcon;
// 9.4 — announcement bar: 3 rotating messages, auto every 4s, manual arrows
function Announce() {
const msgs = [
{ ic: "truck", node: Matky zasíláme v klíckách doporučeně po celé ČR },
{ ic: "shield", node: Ke každé zásilce veterinární osvědčení o zdraví včelstev },
{ ic: "door", node: Osobní převzetí na včelnici po domluvě · Na Samotě 1029, Hostivice },
];
const [i, setI] = React.useState(0);
React.useEffect(() => {
const t = setInterval(() => setI((v) => (v + 1) % msgs.length), 4000);
return () => clearInterval(t);
}, []);
const move = (d) => setI((v) => (v + d + msgs.length) % msgs.length);
const m = msgs[i];
return (
move(-1)} aria-label="Předchozí sdělení">‹
{m.node}
move(1)} aria-label="Další sdělení">›
);
}
// Friendly, honey-themed 404 / error fallback
function Error404({ onHome, onShop }) {
return (
404
Tahle stránka se někam zatoulala
Asi ji odnesla na křídlech nějaká zatoulaná včela — matky v úlích máme, ale tuhle adresu jsme nenašli ani pod posledním plástem. Zkuste to prosím znovu.
}>Zpátky domů
Prohlédnout nabídku
🐝 Tip: matka se výjimečně zatoulá — stránky bohužel častěji.
);
}
// Catches render errors anywhere in the screen and shows the 404 instead of a white screen
class ErrorBoundary extends React.Component {
constructor(p) { super(p); this.state = { err: false }; }
static getDerivedStateFromError() { return { err: true }; }
componentDidUpdate(prev) { if (prev.routeKey !== this.props.routeKey && this.state.err) this.setState({ err: false }); }
render() { return this.state.err ? : this.props.children; }
}
function App() {
const [route, setRoute] = React.useState({ screen: "home", arg: null });
const [cart, setCart] = React.useState([]);
const [cartOpen, setCartOpen] = React.useState(false);
const [cartPeek, setCartPeek] = React.useState(false);
const [menuOpen, setMenuOpen] = React.useState(false);
const [quickView, setQuickView] = React.useState(null);
const [preorder, setPreorder] = React.useState(null);
const [toast, setToast] = React.useState(null);
const [user, setUser] = React.useState(null);
const [authOpen, setAuthOpen] = React.useState(false);
const [cartPulse, setCartPulse] = React.useState(0);
const [showTop, setShowTop] = React.useState(false);
const toastTimer = React.useRef(null);
React.useEffect(() => {
const fn = () => setShowTop(window.scrollY > 500);
window.addEventListener("scroll", fn, { passive: true });
return () => window.removeEventListener("scroll", fn);
}, []);
React.useEffect(() => {
window.__openRezervace = (p, qty) => { go("rezervace", p); };
return () => { delete window.__openRezervace; };
}, []);
// Preview the 404 page by adding #404 (or any unknown #hash) to the URL
React.useEffect(() => {
const sync = () => {
const h = (window.location.hash || "").replace(/^#/, "");
if (h === "404") setRoute({ screen: "404", arg: null });
};
sync();
window.addEventListener("hashchange", sync);
return () => window.removeEventListener("hashchange", sync);
}, []);
const go = (screen, arg = null) => {
setRoute({ screen, arg });
setMenuOpen(false);
setCartOpen(false);
setCartPeek(false);
if (screen !== "product") window.scrollTo({ top: 0, behavior: "auto" });
else window.scrollTo({ top: 0 });
};
const login = (u) => {
const acc = window.SHOP_DATA && window.SHOP_DATA.account;
const resolved = u || (acc && acc.user) || null;
setUser(resolved);
setAuthOpen(false);
const fn = (resolved && resolved.firstName) || "";
const initials = resolved ? (((resolved.firstName || "")[0] || "") + ((resolved.lastName || "")[0] || "")).toUpperCase() : "";
showToast({ kind: "status", title: fn ? ("Vítejte zpět, " + fn) : "Přihlášeno", sub: "Jsme rádi, že jste zpět.", initials });
};
const logout = () => { setUser(null); go("home"); showToast({ kind: "status", title: "Byli jste odhlášeni", icon: "logout" }); };
const showToast = (data) => {
setToast(data);
clearTimeout(toastTimer.current);
const dur = data && typeof data === "object" ? 3200 : 2400;
toastTimer.current = setTimeout(() => setToast(null), dur);
};
const openRezervace = (p, qty = 1) => {
if (!p || p.stock === "out") return;
if (window.__openRezervace) window.__openRezervace(p, qty);
else go("rezervace", p);
};
const addToCart = (p, qty = 1) => openRezervace(p, qty);
const buyNow = (p, qty = 1) => openRezervace(p, qty);
const setQty = (id, q) => setCart((c) => c.map((i) => i.id === id ? { ...i, qty: q } : i));
const removeItem = (id) => setCart((c) => c.filter((i) => i.id !== id));
const cartCount = cart.reduce((s, i) => s + i.qty, 0);
const notify = (p) => showToast(`Dáme vědět, až naskádníme: ${p.name}`);
let screen;
const props = { go, addToCart, onQuickView: setQuickView, onNotify: notify, onPreorder: setPreorder };
switch (route.screen) {
case "category": screen = ; break;
case "product": screen = ; break;
case "blog": screen = ; break;
case "article": screen = ; break;
case "about": screen = ; break;
case "contact": screen = ; break;
case "podminky": screen = ; break;
case "gdpr": screen = ; break;
case "checkout":
case "rezervace": screen = ; break;
case "account":
screen = user
? addToCart(p, q, { peek: true })} onQuickView={setQuickView} onNotify={notify} onPreorder={setPreorder} />
: ;
break;
case "404": screen = go("home")} onShop={() => go("category")} />; break;
default: screen = ;
}
return (
{ setCartPeek(false); setCartOpen(true); }} onMenu={() => setMenuOpen(true)}
user={user} onProfile={() => setAuthOpen(true)} onLogout={logout} />
go("home")} onShop={() => go("category")}>{screen}
setMenuOpen(false)} go={go} />
{/* košík vypnutý — rezervačný flow */}
{window.VNPreorder && setPreorder(null)}
onAddToCart={addToCart} onBuyNow={buyNow} onContact={() => go("contact")} />}
{window.VNAuth && setAuthOpen(false)} onLogin={login} />}
window.scrollTo({ top: 0, behavior: "smooth" })} aria-label="Nahoru na začátek">
{toast && typeof toast === "object" && toast.kind === "cart" && (
<>
{toast.preorder ? "Předobjednávka přidána" : "Přidáno do košíku"}
{toast.name} · {toast.weight}
{ setToast(null); setCartPeek(false); setCartOpen(true); }}>
Zobrazit košík
>
)}
{toast && !(typeof toast === "object" && toast.kind === "cart") && (
typeof toast === "object" ? (
<>
{toast.initials
?
{toast.initials}
:
}
{toast.title}
{toast.sub ? {toast.sub} : null}
>
) : (
<>
{toast} >
)
)}
);
}
// NOTE: do not auto-mount here. This file is also concatenated into
// _ds_bundle.js; mounting at load time would crash the bundle (and any
// consumer that imports it). index.html mounts explicitly after
// all kit scripts have loaded.
window.VNApp = App;
})();