Files
ben.de-roo.org/domme-converters/assets/js/store.js
T

111 lines
2.5 KiB
JavaScript

"use strict";
/**
* Winkelmandje-store met persistentie in localStorage en een eenvoudig
* publish/subscribe-mechanisme. Alle pagina's delen dezelfde toestand, zodat
* het mandje behouden blijft tijdens het navigeren.
*/
(function () {
const STORAGE_KEY = "converterland.cart.v1";
const TAX_RATE = 0.21;
const CL = (window.CL = window.CL || {});
const products = window.PRODUCTS || [];
const findProduct = (id) => products.find((p) => p.id === id);
/** @type {Map<string, number>} product-id -> aantal */
const cart = new Map();
const listeners = new Set();
function load() {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return;
const entries = JSON.parse(raw);
if (Array.isArray(entries)) {
for (const [id, qty] of entries) {
if (findProduct(id) && Number.isFinite(qty) && qty > 0) {
cart.set(id, Math.floor(qty));
}
}
}
} catch (err) {
// Beschadigde opslag negeren en met een leeg mandje starten.
}
}
function persist() {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify([...cart.entries()]));
} catch (err) {
// Opslag kan geblokkeerd zijn (privémodus); de store werkt dan in-memory.
}
}
function emit() {
persist();
for (const fn of listeners) fn();
}
const store = {
TAX_RATE,
subscribe(fn) {
listeners.add(fn);
return () => listeners.delete(fn);
},
entries() {
return [...cart.entries()];
},
size() {
return cart.size;
},
quantityOf(id) {
return cart.get(id) || 0;
},
add(id, amount = 1) {
const product = findProduct(id);
if (!product) return;
cart.set(id, (cart.get(id) || 0) + amount);
emit();
},
setQuantity(id, qty) {
if (!findProduct(id)) return;
if (qty <= 0) cart.delete(id);
else cart.set(id, Math.floor(qty));
emit();
},
step(id, delta) {
if (!cart.has(id)) return;
this.setQuantity(id, cart.get(id) + delta);
},
clear() {
cart.clear();
emit();
},
totals() {
let count = 0;
let subtotal = 0;
for (const [id, qty] of cart) {
const product = findProduct(id);
if (!product) continue;
count += qty;
subtotal += product.price * qty;
}
const tax = subtotal * TAX_RATE;
return { count, subtotal, tax, total: subtotal + tax };
},
};
load();
CL.store = store;
})();