Files
SkyArtShop/website/assets/js/shopping.js

377 lines
11 KiB
JavaScript
Raw Normal View History

/**
* Enhanced Cart and Wishlist Management System
* Amazon/eBay-style product display with images and details
*/
class ShoppingManager {
constructor() {
this.cart = this.loadFromStorage("skyart_cart") || [];
this.wishlist = this.loadFromStorage("skyart_wishlist") || [];
this.init();
}
init() {
this.updateAllBadges();
this.setupEventListeners();
this.renderCart();
this.renderWishlist();
}
loadFromStorage(key) {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch (e) {
console.error("Error loading from storage:", e);
return null;
}
}
saveToStorage(key, data) {
try {
localStorage.setItem(key, JSON.stringify(data));
} catch (e) {
console.error("Error saving to storage:", e);
}
}
setupEventListeners() {
// Cart toggle
const cartToggle = document.getElementById("cartToggle");
const cartPanel = document.getElementById("cartPanel");
const cartClose = document.getElementById("cartClose");
if (cartToggle) {
cartToggle.addEventListener("click", (e) => {
e.stopPropagation();
cartPanel?.classList.toggle("active");
document.getElementById("wishlistPanel")?.classList.remove("active");
});
}
if (cartClose) {
cartClose.addEventListener("click", (e) => {
e.stopPropagation();
cartPanel?.classList.remove("active");
});
}
// Wishlist toggle
const wishlistToggle = document.getElementById("wishlistToggle");
const wishlistPanel = document.getElementById("wishlistPanel");
const wishlistClose = document.getElementById("wishlistClose");
if (wishlistToggle) {
wishlistToggle.addEventListener("click", (e) => {
e.stopPropagation();
wishlistPanel?.classList.toggle("active");
cartPanel?.classList.remove("active");
});
}
if (wishlistClose) {
wishlistClose.addEventListener("click", (e) => {
e.stopPropagation();
wishlistPanel?.classList.remove("active");
});
}
// Mobile menu
const mobileToggle = document.getElementById("mobileMenuToggle");
const mobileMenu = document.getElementById("mobileMenu");
const mobileClose = document.getElementById("mobileMenuClose");
if (mobileToggle) {
mobileToggle.addEventListener("click", () => {
mobileMenu?.classList.toggle("active");
document.body.style.overflow = mobileMenu?.classList.contains("active")
? "hidden"
: "";
});
}
if (mobileClose) {
mobileClose.addEventListener("click", () => {
mobileMenu?.classList.remove("active");
document.body.style.overflow = "";
});
}
// Close dropdowns on outside click
document.addEventListener("click", (e) => {
if (!e.target.closest(".cart-dropdown-wrapper")) {
cartPanel?.classList.remove("active");
}
if (!e.target.closest(".wishlist-dropdown-wrapper")) {
wishlistPanel?.classList.remove("active");
}
});
}
// Add to Cart
addToCart(product, quantity = 1) {
const existingItem = this.cart.find((item) => item.id === product.id);
if (existingItem) {
existingItem.quantity += quantity;
} else {
this.cart.push({
id: product.id,
name: product.name,
price: parseFloat(product.price),
imageurl: product.imageurl,
quantity: quantity,
addedAt: new Date().toISOString(),
});
}
this.saveToStorage("skyart_cart", this.cart);
this.updateAllBadges();
this.renderCart();
this.showNotification(`${product.name} added to cart!`, "success");
}
// Remove from Cart
removeFromCart(productId) {
this.cart = this.cart.filter((item) => item.id !== productId);
this.saveToStorage("skyart_cart", this.cart);
this.updateAllBadges();
this.renderCart();
this.showNotification("Item removed from cart", "info");
}
// Update Cart Quantity
updateCartQuantity(productId, quantity) {
const item = this.cart.find((item) => item.id === productId);
if (item) {
if (quantity <= 0) {
this.removeFromCart(productId);
} else {
item.quantity = quantity;
this.saveToStorage("skyart_cart", this.cart);
this.updateAllBadges();
this.renderCart();
}
}
}
// Add to Wishlist
addToWishlist(product) {
const exists = this.wishlist.find((item) => item.id === product.id);
if (!exists) {
this.wishlist.push({
id: product.id,
name: product.name,
price: parseFloat(product.price),
imageurl: product.imageurl,
addedAt: new Date().toISOString(),
});
this.saveToStorage("skyart_wishlist", this.wishlist);
this.updateAllBadges();
this.renderWishlist();
this.showNotification(`${product.name} added to wishlist!`, "success");
} else {
this.showNotification("Already in wishlist", "info");
}
}
// Remove from Wishlist
removeFromWishlist(productId) {
this.wishlist = this.wishlist.filter((item) => item.id !== productId);
this.saveToStorage("skyart_wishlist", this.wishlist);
this.updateAllBadges();
this.renderWishlist();
this.showNotification("Item removed from wishlist", "info");
}
// Move from Wishlist to Cart
moveToCart(productId) {
const item = this.wishlist.find((item) => item.id === productId);
if (item) {
this.addToCart(item, 1);
this.removeFromWishlist(productId);
}
}
// Update All Badges
updateAllBadges() {
const cartCount = this.cart.reduce((sum, item) => sum + item.quantity, 0);
const wishlistCount = this.wishlist.length;
const cartBadge = document.getElementById("cartCount");
const wishlistBadge = document.getElementById("wishlistCount");
if (cartBadge) {
cartBadge.textContent = cartCount;
cartBadge.style.display = cartCount > 0 ? "flex" : "none";
}
if (wishlistBadge) {
wishlistBadge.textContent = wishlistCount;
wishlistBadge.style.display = wishlistCount > 0 ? "flex" : "none";
}
}
// Render Cart
renderCart() {
const cartContent = document.getElementById("cartContent");
const cartSubtotal = document.getElementById("cartSubtotal");
if (!cartContent) return;
if (this.cart.length === 0) {
cartContent.innerHTML = '<p class="empty-state">Your cart is empty</p>';
if (cartSubtotal) cartSubtotal.textContent = "$0.00";
return;
}
const subtotal = this.cart.reduce(
(sum, item) => sum + item.price * item.quantity,
0
);
cartContent.innerHTML = this.cart
.map(
(item) => `
<div class="cart-item" data-product-id="${item.id}">
<div class="cart-item-image">
<img src="${item.imageurl || "/assets/images/placeholder.jpg"}"
alt="${item.name}"
onerror="this.src='/assets/images/placeholder.jpg'" />
</div>
<div class="cart-item-details">
<h4 class="cart-item-name">${item.name}</h4>
<p class="cart-item-price">$${item.price.toFixed(2)}</p>
<div class="cart-item-quantity">
<button class="qty-btn" onclick="shoppingManager.updateCartQuantity('${
item.id
}', ${item.quantity - 1})">
<i class="bi bi-dash"></i>
</button>
<span class="qty-value">${item.quantity}</span>
<button class="qty-btn" onclick="shoppingManager.updateCartQuantity('${
item.id
}', ${item.quantity + 1})">
<i class="bi bi-plus"></i>
</button>
</div>
</div>
<div class="cart-item-actions">
<button class="cart-item-remove" onclick="shoppingManager.removeFromCart('${
item.id
}')" title="Remove">
<i class="bi bi-trash"></i>
</button>
<p class="cart-item-total">$${(item.price * item.quantity).toFixed(
2
)}</p>
</div>
</div>
`
)
.join("");
if (cartSubtotal) {
cartSubtotal.textContent = `$${subtotal.toFixed(2)}`;
}
}
// Render Wishlist
renderWishlist() {
const wishlistContent = document.getElementById("wishlistContent");
if (!wishlistContent) return;
if (this.wishlist.length === 0) {
wishlistContent.innerHTML =
'<p class="empty-state">Your wishlist is empty</p>';
return;
}
wishlistContent.innerHTML = this.wishlist
.map(
(item) => `
<div class="wishlist-item" data-product-id="${item.id}">
<div class="wishlist-item-image">
<img src="${item.imageurl || "/assets/images/placeholder.jpg"}"
alt="${item.name}"
onerror="this.src='/assets/images/placeholder.jpg'" />
</div>
<div class="wishlist-item-details">
<h4 class="wishlist-item-name">${item.name}</h4>
<p class="wishlist-item-price">$${item.price.toFixed(2)}</p>
<button class="btn-move-to-cart" onclick="shoppingManager.moveToCart('${
item.id
}')">
<i class="bi bi-cart-plus"></i> Add to Cart
</button>
</div>
<button class="wishlist-item-remove" onclick="shoppingManager.removeFromWishlist('${
item.id
}')" title="Remove">
<i class="bi bi-x-lg"></i>
</button>
</div>
`
)
.join("");
}
// Show Notification
showNotification(message, type = "info") {
const notification = document.createElement("div");
notification.className = `notification notification-${type}`;
notification.innerHTML = `
<i class="bi bi-${
type === "success" ? "check-circle" : "info-circle"
}"></i>
<span>${message}</span>
`;
document.body.appendChild(notification);
setTimeout(() => notification.classList.add("show"), 10);
setTimeout(() => {
notification.classList.remove("show");
setTimeout(() => notification.remove(), 300);
}, 3000);
}
// Get Cart Total
getCartTotal() {
return this.cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// Get Cart Count
getCartCount() {
return this.cart.reduce((sum, item) => sum + item.quantity, 0);
}
// Clear Cart
clearCart() {
this.cart = [];
this.saveToStorage("skyart_cart", this.cart);
this.updateAllBadges();
this.renderCart();
}
}
// Initialize Shopping Manager
const shoppingManager = new ShoppingManager();
// Make it globally available
window.shoppingManager = shoppingManager;
// Navigation active state
document.addEventListener("DOMContentLoaded", () => {
const currentPage = window.location.pathname.split("/").pop() || "home.html";
document.querySelectorAll(".nav-link, .mobile-link").forEach((link) => {
const linkPage = link.getAttribute("href")?.split("/").pop();
if (linkPage === currentPage) {
link.classList.add("active");
}
});
});