/** * Shared HTML Components * Eliminates duplication across HTML files */ // Component templates const Components = { /** * Render cart drawer HTML * @returns {string} Cart drawer HTML */ cartDrawer: () => `

Shopping Cart

`, /** * Render wishlist drawer HTML * @returns {string} Wishlist drawer HTML */ wishlistDrawer: () => `

Wishlist

`, /** * Render navbar HTML * @param {Object} options - Navbar options * @param {string} options.activePage - Current active page * @returns {string} Navbar HTML */ navbar: ({ activePage = "" } = {}) => { const isActive = (page) => (page === activePage ? "active" : ""); return ` `; }, /** * Render footer HTML * @returns {string} Footer HTML */ footer: () => ` `, /** * Render notification container * @returns {string} Notification container HTML */ notificationContainer: () => `
`, }; /** * Initialize components in the DOM * @param {Object} options - Component options * @param {boolean} options.navbar - Include navbar * @param {boolean} options.footer - Include footer * @param {boolean} options.cart - Include cart drawer * @param {boolean} options.wishlist - Include wishlist drawer * @param {boolean} options.notifications - Include notifications * @param {string} options.activePage - Active page for navbar */ function initializeComponents({ navbar = true, footer = true, cart = true, wishlist = true, notifications = true, activePage = "", } = {}) { // Inject components into DOM if (navbar) { const navPlaceholder = document.getElementById("navbar-placeholder"); if (navPlaceholder) { navPlaceholder.innerHTML = Components.navbar({ activePage }); } } if (footer) { const footerPlaceholder = document.getElementById("footer-placeholder"); if (footerPlaceholder) { footerPlaceholder.innerHTML = Components.footer(); } } if (cart) { const cartPlaceholder = document.getElementById("cart-drawer-placeholder"); if (cartPlaceholder) { cartPlaceholder.innerHTML = Components.cartDrawer(); } } if (wishlist) { const wishlistPlaceholder = document.getElementById( "wishlist-drawer-placeholder" ); if (wishlistPlaceholder) { wishlistPlaceholder.innerHTML = Components.wishlistDrawer(); } } if (notifications) { const notificationPlaceholder = document.getElementById( "notification-placeholder" ); if (notificationPlaceholder) { notificationPlaceholder.innerHTML = Components.notificationContainer(); } } // Initialize mobile menu toggle initMobileMenu(); // Initialize cart and wishlist interactions if (cart) initCartDrawer(); if (wishlist) initWishlistDrawer(); } /** * Initialize mobile menu functionality */ function initMobileMenu() { const menuToggle = document.getElementById("mobileMenuToggle"); const navMenu = document.getElementById("navMenu"); if (menuToggle && navMenu) { menuToggle.addEventListener("click", () => { navMenu.classList.toggle("active"); menuToggle.classList.toggle("active"); }); // Close menu when clicking outside document.addEventListener("click", (e) => { if ( !menuToggle.contains(e.target) && !navMenu.contains(e.target) && navMenu.classList.contains("active") ) { navMenu.classList.remove("active"); menuToggle.classList.remove("active"); } }); } } /** * Initialize cart drawer functionality */ function initCartDrawer() { const cartBtn = document.getElementById("cartBtn"); const cartDrawer = document.getElementById("cartDrawer"); const closeCart = document.getElementById("closeCart"); if (cartBtn && cartDrawer) { cartBtn.addEventListener("click", () => { cartDrawer.classList.add("active"); document.body.style.overflow = "hidden"; updateCartUI(); }); if (closeCart) { closeCart.addEventListener("click", () => { cartDrawer.classList.remove("active"); document.body.style.overflow = ""; }); } // Close on overlay click cartDrawer.addEventListener("click", (e) => { if (e.target === cartDrawer) { cartDrawer.classList.remove("active"); document.body.style.overflow = ""; } }); } // Initialize checkout button const checkoutBtn = document.getElementById("checkoutBtn"); if (checkoutBtn) { checkoutBtn.addEventListener("click", () => { window.location.href = "/checkout"; }); } } /** * Initialize wishlist drawer functionality */ function initWishlistDrawer() { const wishlistBtn = document.getElementById("wishlistBtn"); const wishlistDrawer = document.getElementById("wishlistDrawer"); const closeWishlist = document.getElementById("closeWishlist"); if (wishlistBtn && wishlistDrawer) { wishlistBtn.addEventListener("click", () => { wishlistDrawer.classList.add("active"); document.body.style.overflow = "hidden"; updateWishlistUI(); }); if (closeWishlist) { closeWishlist.addEventListener("click", () => { wishlistDrawer.classList.remove("active"); document.body.style.overflow = ""; }); } // Close on overlay click wishlistDrawer.addEventListener("click", (e) => { if (e.target === wishlistDrawer) { wishlistDrawer.classList.remove("active"); document.body.style.overflow = ""; } }); } } /** * Update cart UI with current items */ function updateCartUI() { if (typeof CartUtils === "undefined") return; const cart = CartUtils.getCart(); const cartItems = document.getElementById("cartItems"); const cartTotal = document.getElementById("cartTotal"); const cartBadge = document.getElementById("cartBadge"); if (cartBadge) { cartBadge.textContent = cart.length; cartBadge.style.display = cart.length > 0 ? "flex" : "none"; } if (!cartItems) return; if (cart.length === 0) { cartItems.innerHTML = '

Your cart is empty

'; if (cartTotal) cartTotal.textContent = "$0.00"; return; } cartItems.innerHTML = cart .map( (item) => `
${item.name}

${item.name}

${formatPrice(item.price)}

${item.quantity}
` ) .join(""); if (cartTotal) { cartTotal.textContent = formatPrice(CartUtils.getCartTotal()); } } /** * Update wishlist UI with current items */ function updateWishlistUI() { if (typeof WishlistUtils === "undefined") return; const wishlist = WishlistUtils.getWishlist(); const wishlistItems = document.getElementById("wishlistItems"); const wishlistBadge = document.getElementById("wishlistBadge"); if (wishlistBadge) { wishlistBadge.textContent = wishlist.length; wishlistBadge.style.display = wishlist.length > 0 ? "flex" : "none"; } if (!wishlistItems) return; if (wishlist.length === 0) { wishlistItems.innerHTML = '

Your wishlist is empty

'; return; } wishlistItems.innerHTML = wishlist .map( (item) => `
${
        item.name
      }

${item.name}

${formatPrice(item.price)}

` ) .join(""); } // Global functions for inline event handlers window.increaseQuantity = (productId) => { if (typeof CartUtils !== "undefined") { const cart = CartUtils.getCart(); const item = cart.find((item) => item.id === productId); if (item) { CartUtils.updateQuantity(productId, item.quantity + 1); updateCartUI(); } } }; window.decreaseQuantity = (productId) => { if (typeof CartUtils !== "undefined") { const cart = CartUtils.getCart(); const item = cart.find((item) => item.id === productId); if (item && item.quantity > 1) { CartUtils.updateQuantity(productId, item.quantity - 1); updateCartUI(); } } }; window.removeFromCart = (productId) => { if (typeof CartUtils !== "undefined") { CartUtils.removeFromCart(productId); updateCartUI(); showNotification("Item removed from cart", "info"); } }; window.removeFromWishlist = (productId) => { if (typeof WishlistUtils !== "undefined") { WishlistUtils.removeFromWishlist(productId); updateWishlistUI(); showNotification("Item removed from wishlist", "info"); } }; window.moveToCart = (productId) => { if ( typeof WishlistUtils !== "undefined" && typeof CartUtils !== "undefined" ) { const wishlist = WishlistUtils.getWishlist(); const item = wishlist.find((item) => item.id === productId); if (item) { CartUtils.addToCart(item); WishlistUtils.removeFromWishlist(productId); updateWishlistUI(); updateCartUI(); showNotification("Item moved to cart", "success"); } } }; // Initialize on DOM load if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => { // Auto-initialize if data attribute is set const autoInit = document.body.dataset.autoInitComponents; if (autoInit !== "false") { initializeComponents({ activePage: document.body.dataset.activePage || "", }); } }); } else { // Already loaded const autoInit = document.body.dataset.autoInitComponents; if (autoInit !== "false") { initializeComponents({ activePage: document.body.dataset.activePage || "", }); } } // Export for manual initialization window.Components = Components; window.initializeComponents = initializeComponents;