/** * Shared Cart and Wishlist Utilities * Extracted from duplicated code across multiple pages */ const CartUtils = { /** * Get cart from localStorage * @returns {Array} Cart items */ getCart() { try { return JSON.parse(localStorage.getItem("skyart_cart") || "[]"); } catch (error) { console.error("Error loading cart:", error); return []; } }, /** * Save cart to localStorage * @param {Array} cart - Cart items */ saveCart(cart) { try { localStorage.setItem("skyart_cart", JSON.stringify(cart)); this.updateCartBadge(); } catch (error) { console.error("Error saving cart:", error); } }, /** * Add item to cart * @param {Object} product - Product to add * @param {number} quantity - Quantity to add * @param {string} variant - Selected variant */ addToCart(product, quantity = 1, variant = null) { const cart = this.getCart(); const cartKey = variant ? `${product.id}-${variant}` : product.id; const existingIndex = cart.findIndex((item) => { const itemKey = item.variant ? `${item.productId}-${item.variant}` : item.productId; return itemKey === cartKey; }); if (existingIndex >= 0) { cart[existingIndex].quantity += quantity; } else { cart.push({ productId: product.id, name: product.name, price: product.price, image: product.images?.[0]?.image_url || product.imageurl, quantity, variant, slug: product.slug, }); } this.saveCart(cart); return cart; }, /** * Remove item from cart * @param {string} productId - Product ID to remove * @param {string} variant - Variant to remove */ removeFromCart(productId, variant = null) { const cart = this.getCart(); const cartKey = variant ? `${productId}-${variant}` : productId; const filtered = cart.filter((item) => { const itemKey = item.variant ? `${item.productId}-${item.variant}` : item.productId; return itemKey !== cartKey; }); this.saveCart(filtered); return filtered; }, /** * Update cart item quantity * @param {string} productId - Product ID * @param {number} quantity - New quantity * @param {string} variant - Variant */ updateQuantity(productId, quantity, variant = null) { const cart = this.getCart(); const cartKey = variant ? `${productId}-${variant}` : productId; const index = cart.findIndex((item) => { const itemKey = item.variant ? `${item.productId}-${item.variant}` : item.productId; return itemKey === cartKey; }); if (index >= 0) { if (quantity <= 0) { cart.splice(index, 1); } else { cart[index].quantity = quantity; } this.saveCart(cart); } return cart; }, /** * Get cart total * @returns {number} Total price */ getCartTotal() { const cart = this.getCart(); return cart.reduce((total, item) => { return total + parseFloat(item.price) * item.quantity; }, 0); }, /** * Update cart badge count */ updateCartBadge() { const cart = this.getCart(); const count = cart.reduce((sum, item) => sum + item.quantity, 0); const badge = document.querySelector(".cart-badge"); if (badge) { badge.textContent = count; badge.style.display = count > 0 ? "flex" : "none"; } }, /** * Clear cart */ clearCart() { localStorage.removeItem("skyart_cart"); this.updateCartBadge(); }, }; const WishlistUtils = { /** * Get wishlist from localStorage * @returns {Array} Wishlist items */ getWishlist() { try { return JSON.parse(localStorage.getItem("wishlist") || "[]"); } catch (error) { console.error("Error loading wishlist:", error); return []; } }, /** * Save wishlist to localStorage * @param {Array} wishlist - Wishlist items */ saveWishlist(wishlist) { try { localStorage.setItem("wishlist", JSON.stringify(wishlist)); this.updateWishlistBadge(); } catch (error) { console.error("Error saving wishlist:", error); } }, /** * Add item to wishlist * @param {Object} product - Product to add */ addToWishlist(product) { const wishlist = this.getWishlist(); if (!wishlist.find((item) => item.id === product.id)) { wishlist.push({ id: product.id, name: product.name, price: product.price, image: product.images?.[0]?.image_url || product.imageurl, slug: product.slug, }); this.saveWishlist(wishlist); } return wishlist; }, /** * Remove item from wishlist * @param {string} productId - Product ID to remove */ removeFromWishlist(productId) { const wishlist = this.getWishlist(); const filtered = wishlist.filter((item) => item.id !== productId); this.saveWishlist(filtered); return filtered; }, /** * Check if product is in wishlist * @param {string} productId - Product ID * @returns {boolean} True if in wishlist */ isInWishlist(productId) { const wishlist = this.getWishlist(); return wishlist.some((item) => item.id === productId); }, /** * Update wishlist badge count */ updateWishlistBadge() { const wishlist = this.getWishlist(); const badge = document.querySelector(".wishlist-badge"); if (badge) { badge.textContent = wishlist.length; badge.style.display = wishlist.length > 0 ? "flex" : "none"; } }, /** * Clear wishlist */ clearWishlist() { localStorage.removeItem("wishlist"); this.updateWishlistBadge(); }, }; /** * Format price for display * @param {number} price - Price to format * @returns {string} Formatted price */ const formatPrice = (price) => { return `$${parseFloat(price).toFixed(2)}`; }; /** * Format date for display * @param {string} dateString - ISO date string * @returns {string} Formatted date */ const formatDate = (dateString) => { const date = new Date(dateString); return date.toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", }); }; /** * Debounce function * @param {Function} func - Function to debounce * @param {number} wait - Wait time in ms * @returns {Function} Debounced function */ const debounce = (func, wait) => { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }; /** * Show notification toast * @param {string} message - Message to display * @param {string} type - Type: success, error, info */ const showNotification = (message, type = "success") => { // Check if a notification container exists let container = document.querySelector(".notification-container"); if (!container) { container = document.createElement("div"); container.className = "notification-container"; container.style.cssText = ` position: fixed; top: 100px; right: 20px; z-index: 10000; `; document.body.appendChild(container); } const notification = document.createElement("div"); notification.className = `notification notification-${type}`; notification.style.cssText = ` background: ${ type === "success" ? "#10b981" : type === "error" ? "#ef4444" : "#3b82f6" }; color: white; padding: 12px 20px; border-radius: 8px; margin-bottom: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); animation: slideIn 0.3s ease-out; `; notification.textContent = message; container.appendChild(notification); setTimeout(() => { notification.style.animation = "slideOut 0.3s ease-out"; setTimeout(() => notification.remove(), 300); }, 3000); }; // Export for use in other scripts if (typeof window !== "undefined") { window.CartUtils = CartUtils; window.WishlistUtils = WishlistUtils; window.formatPrice = formatPrice; window.formatDate = formatDate; window.debounce = debounce; window.showNotification = showNotification; }