(() => { "use strict"; if (!document.body.classList.contains("ex-u-3097861")) return; /* ----------------------------------------------------------------------- 1) Config ----------------------------------------------------------------------- */ const FREE_DELIVERY_THRESHOLD = 100; const PROGRESS_DURATION_MS = 5000; const CONGRATS_DURATION_MS = 10000; const STORAGE_KEY = "coFreeDeliveryReached"; const SVG_ATTRS = 'width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"'; const ICONS = { progress: ``, congrats: ``, }; /* ----------------------------------------------------------------------- 2) Helpers ----------------------------------------------------------------------- */ const formatMoney = (amount) => { const isoCode = typeof window.$globalCurrencyISO !== "undefined" && window.$globalCurrencyISO ? window.$globalCurrencyISO : "GBP"; const symbol = typeof window.$globalCurrency !== "undefined" && window.$globalCurrency ? window.$globalCurrency : "£"; const value = Math.max(0, amount); try { return new Intl.NumberFormat(undefined, { style: "currency", currency: isoCode }).format(value); } catch (e) { return symbol + value.toFixed(2); } }; // Tries window.$mini_cart first, then falls back to common event.detail shapes. const getMinicartItems = (evt) => { if (Array.isArray(window.$mini_cart)) return window.$mini_cart; if (evt && evt.detail) { if (Array.isArray(evt.detail)) return evt.detail; if (Array.isArray(evt.detail.items)) return evt.detail.items; if (Array.isArray(evt.detail.minicart)) return evt.detail.minicart; if (Array.isArray(evt.detail.$mini_cart)) return evt.detail.$mini_cart; } return []; }; const getCartTotal = (items) => { const total = items.reduce((sum, item) => { if (!item) return sum; const lineTotal = typeof item.item_line_total === "number" ? item.item_line_total : parseFloat(item.item_line_total); return isNaN(lineTotal) ? sum : sum + lineTotal; }, 0); return Math.round(total * 100) / 100; }; const hasReachedThreshold = (total) => total >= FREE_DELIVERY_THRESHOLD; const safeSessionGet = (key) => { try { return sessionStorage.getItem(key); } catch (e) { return null; } }; const safeSessionSet = (key, value) => { try { sessionStorage.setItem(key, value); } catch (e) { /* private mode etc. */ } }; const wasReached = () => safeSessionGet(STORAGE_KEY) === "1"; const setReached = (reached) => safeSessionSet(STORAGE_KEY, reached ? "1" : "0"); // Headline is the primary (larger/bolder) line; sub is the optional secondary line. const buildMessage = (reached, total) => { if (reached) { return { type: "congrats", headline: "Congratulations! You've unlocked FREE delivery!", sub: "", }; } const remaining = FREE_DELIVERY_THRESHOLD - total; return { type: "progress", headline: `Spend another ${formatMoney(remaining)} to unlock FREE delivery`, sub: "", }; }; /* ----------------------------------------------------------------------- 3) Toast popup ----------------------------------------------------------------------- */ let popupEl = null; let popupTimer = null; const closePopup = () => { if (popupTimer) { clearTimeout(popupTimer); popupTimer = null; } if (!popupEl) return; const el = popupEl; popupEl = null; el.classList.remove("is-visible"); setTimeout(() => { if (el.parentNode) el.parentNode.removeChild(el); }, 300); }; const showPopup = (msg) => { closePopup(); const duration = msg.type === "congrats" ? CONGRATS_DURATION_MS : PROGRESS_DURATION_MS; const toast = document.createElement("div"); toast.className = `co-delivery-popup co-delivery-popup--${msg.type}`; toast.setAttribute("role", "status"); toast.setAttribute("aria-live", "polite"); toast.innerHTML = ` ${ICONS[msg.type]}
${msg.headline}
${msg.sub ? `${msg.sub}
` : ""}${msg.headline}
`; if (info.className !== className) info.className = className; if (info.innerHTML !== html) info.innerHTML = html; }); }; /* ----------------------------------------------------------------------- 6) Wire up ----------------------------------------------------------------------- */ if (document.body.classList.contains("ex-cart")) { if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => renderCartInfo()); } else { renderCartInfo(); } document.addEventListener("cart-total-update", renderCartInfo); } else { document.addEventListener("cart-total-update", handleCartUpdate); } document.addEventListener("keydown", (e) => { if (e.key === "Escape") closePopup(); }); })();