diff --git a/domme-converters/assets/js/ui.js b/domme-converters/assets/js/ui.js new file mode 100644 index 0000000..fcc4723 --- /dev/null +++ b/domme-converters/assets/js/ui.js @@ -0,0 +1,208 @@ +"use strict"; + +/** + * Globale UI die op elke pagina aanwezig is: winkelmandje-lade, afrekenmodal + * en toast-meldingen. Deze module praat uitsluitend met CL.store, zodat de + * mandjestoestand consistent blijft tijdens het navigeren. + */ +(function () { + const CL = (window.CL = window.CL || {}); + const { formatPrice, escapeHtml } = CL.fmt; + const store = CL.store; + const PRODUCTS = window.PRODUCTS || []; + const findProduct = (id) => PRODUCTS.find((p) => p.id === id); + + const els = {}; + let toastTimer; + + function init() { + els.overlay = document.getElementById("overlay"); + els.drawer = document.getElementById("drawer"); + els.closeCart = document.getElementById("closeCart"); + els.cartItems = document.getElementById("cartItems"); + els.cartSub = document.getElementById("cartSub"); + els.cartTax = document.getElementById("cartTax"); + els.cartTotal = document.getElementById("cartTotal"); + els.checkoutBtn = document.getElementById("checkoutBtn"); + els.modalWrap = document.getElementById("modalWrap"); + els.modalContent = document.getElementById("modalContent"); + els.toast = document.getElementById("toast"); + + els.closeCart.addEventListener("click", closeCart); + els.overlay.addEventListener("click", closeCart); + els.checkoutBtn.addEventListener("click", () => { + if (store.size() === 0) return; + closeCart(); + renderCheckoutForm(); + openModal(); + }); + + // Aantal aanpassen in de lade (delegatie). + els.cartItems.addEventListener("click", (e) => { + const btn = e.target.closest("[data-step]"); + if (btn) store.step(btn.dataset.id, Number(btn.dataset.step)); + }); + + // "Toevoegen" werkt overal: catalogus, productpagina, aanbiedingen. + document.addEventListener("click", (e) => { + const add = e.target.closest("[data-add]"); + if (!add) return; + e.preventDefault(); + const product = findProduct(add.dataset.add); + if (!product) return; + store.add(product.id); + showToast(product.name + " toegevoegd aan het mandje."); + }); + + els.modalWrap.addEventListener("click", (e) => { + if (e.target === els.modalWrap) closeModal(); + }); + document.addEventListener("keydown", (e) => { + if (e.key === "Escape") { closeModal(); closeCart(); } + }); + } + + // Koppelt knoppen die per route opnieuw worden gerenderd (in de header). + function bindHeader() { + const openCartBtn = document.getElementById("openCart"); + if (openCartBtn) openCartBtn.addEventListener("click", openCart); + + const toggle = document.getElementById("navToggle"); + const links = document.getElementById("navLinks"); + if (toggle && links) { + toggle.addEventListener("click", () => { + const open = links.classList.toggle("open"); + toggle.setAttribute("aria-expanded", String(open)); + }); + // Sluit het mobiele menu na een keuze. + links.addEventListener("click", (e) => { + if (e.target.closest("a")) { + links.classList.remove("open"); + toggle.setAttribute("aria-expanded", "false"); + } + }); + } + } + + function updateCartCount() { + const { count } = store.totals(); + document.querySelectorAll("[data-cart-count]").forEach((el) => (el.textContent = String(count))); + } + + function renderCart() { + const { count, subtotal, tax, total } = store.totals(); + els.cartSub.innerHTML = formatPrice(subtotal); + els.cartTax.innerHTML = formatPrice(tax); + els.cartTotal.innerHTML = formatPrice(total); + els.checkoutBtn.disabled = count === 0; + + const entries = store.entries(); + if (entries.length === 0) { + els.cartItems.innerHTML = '
Dit formulier verwerkt geen gegevens. Ingevoerde waarden worden niet opgeslagen of verzonden.
+ + `; + document.getElementById("payForm").addEventListener("submit", (event) => { + event.preventDefault(); + const form = event.currentTarget; + if (!form.checkValidity()) { form.reportValidity(); return; } + renderSuccess(); + }); + } + + function renderSuccess() { + const { count } = store.totals(); + const orderId = "CL-" + Math.floor(100000 + Math.random() * 900000); + els.modalContent.innerHTML = ` +${count} fictief artikel(en) zijn vastgelegd in deze demonstratie.
+Verwachte levering: niet van toepassing.
+ +