Files
SkyArtShop/website/public/assets/js/shared-utils.js
Local Server 2a2a3d99e5 webupdate
2026-01-18 02:22:05 -06:00

333 lines
8.0 KiB
JavaScript

/**
* 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;
}