webupdatev1
This commit is contained in:
729
website/public/assets/js/shop-system.js
Normal file
729
website/public/assets/js/shop-system.js
Normal file
@@ -0,0 +1,729 @@
|
||||
/**
|
||||
* Shopping Cart & Wishlist System
|
||||
* Complete, simple, reliable implementation
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
console.log("[ShopSystem] Loading...");
|
||||
|
||||
// ========================================
|
||||
// UTILS - Fallback if main.js not loaded
|
||||
// ========================================
|
||||
if (!window.Utils) {
|
||||
window.Utils = {
|
||||
formatCurrency(amount) {
|
||||
return new Intl.NumberFormat("en-US", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
}).format(amount);
|
||||
},
|
||||
escapeHtml(text) {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// VALIDATION UTILITIES
|
||||
// ========================================
|
||||
const ValidationUtils = {
|
||||
validateProduct(product) {
|
||||
if (!product || !product.id) {
|
||||
return { valid: false, error: "Invalid product: missing ID" };
|
||||
}
|
||||
|
||||
const price = parseFloat(product.price);
|
||||
if (isNaN(price) || price < 0) {
|
||||
return { valid: false, error: "Invalid product price" };
|
||||
}
|
||||
|
||||
return { valid: true, price };
|
||||
},
|
||||
|
||||
sanitizeProduct(product, price) {
|
||||
return {
|
||||
id: product.id,
|
||||
name: product.name || product.title || "Product",
|
||||
price: price,
|
||||
imageurl:
|
||||
product.imageurl || product.imageUrl || product.image_url || "",
|
||||
};
|
||||
},
|
||||
|
||||
validateQuantity(quantity) {
|
||||
return Math.max(1, parseInt(quantity) || 1);
|
||||
},
|
||||
|
||||
sanitizeItems(items, includeQuantity = false) {
|
||||
return items
|
||||
.filter(
|
||||
(item) =>
|
||||
item &&
|
||||
item.id &&
|
||||
typeof item.price !== "undefined" &&
|
||||
(!includeQuantity || item.quantity > 0)
|
||||
)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
price: parseFloat(item.price) || 0,
|
||||
...(includeQuantity && {
|
||||
quantity: Math.max(1, parseInt(item.quantity) || 1),
|
||||
}),
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// CART & WISHLIST STATE MANAGEMENT
|
||||
// ========================================
|
||||
|
||||
class ShopState {
|
||||
constructor() {
|
||||
this.cart = [];
|
||||
this.wishlist = [];
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
console.log("[ShopState] Initializing...");
|
||||
this.loadFromStorage();
|
||||
this.updateAllBadges();
|
||||
console.log(
|
||||
"[ShopState] Initialized - Cart:",
|
||||
this.cart.length,
|
||||
"Wishlist:",
|
||||
this.wishlist.length
|
||||
);
|
||||
}
|
||||
|
||||
// Load data from localStorage
|
||||
loadFromStorage() {
|
||||
try {
|
||||
const [cartData, wishlistData] = [
|
||||
localStorage.getItem("skyart_cart"),
|
||||
localStorage.getItem("skyart_wishlist"),
|
||||
];
|
||||
|
||||
// Parse and validate data
|
||||
this.cart = this._parseAndValidate(cartData, "cart");
|
||||
this.wishlist = this._parseAndValidate(wishlistData, "wishlist");
|
||||
|
||||
// Sanitize items
|
||||
this.cart = ValidationUtils.sanitizeItems(this.cart, true);
|
||||
this.wishlist = ValidationUtils.sanitizeItems(this.wishlist, false);
|
||||
} catch (e) {
|
||||
console.error("[ShopState] Load error:", e);
|
||||
this._clearCorruptedData();
|
||||
}
|
||||
}
|
||||
|
||||
_parseAndValidate(data, type) {
|
||||
const parsed = data ? JSON.parse(data) : [];
|
||||
if (!Array.isArray(parsed)) {
|
||||
console.warn(`[ShopState] Invalid ${type} data, resetting`);
|
||||
return [];
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
_clearCorruptedData() {
|
||||
localStorage.removeItem("skyart_cart");
|
||||
localStorage.removeItem("skyart_wishlist");
|
||||
this.cart = [];
|
||||
this.wishlist = [];
|
||||
}
|
||||
|
||||
// Save data to localStorage
|
||||
saveToStorage() {
|
||||
try {
|
||||
// Check localStorage availability
|
||||
if (typeof localStorage === "undefined") {
|
||||
console.error("[ShopState] localStorage not available");
|
||||
return false;
|
||||
}
|
||||
|
||||
const cartJson = JSON.stringify(this.cart);
|
||||
const wishlistJson = JSON.stringify(this.wishlist);
|
||||
|
||||
// Check size (5MB limit for most browsers)
|
||||
if (cartJson.length + wishlistJson.length > 4000000) {
|
||||
console.warn(
|
||||
"[ShopState] Storage data too large, trimming old items"
|
||||
);
|
||||
// Keep only last 50 cart items and 100 wishlist items
|
||||
this.cart = this.cart.slice(-50);
|
||||
this.wishlist = this.wishlist.slice(-100);
|
||||
}
|
||||
|
||||
localStorage.setItem("skyart_cart", JSON.stringify(this.cart));
|
||||
localStorage.setItem("skyart_wishlist", JSON.stringify(this.wishlist));
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error("[ShopState] Save error:", e);
|
||||
|
||||
// Handle quota exceeded error
|
||||
if (e.name === "QuotaExceededError" || e.code === 22) {
|
||||
console.warn("[ShopState] Storage quota exceeded, clearing old data");
|
||||
// Try to recover by keeping only essential items
|
||||
this.cart = this.cart.slice(-20);
|
||||
this.wishlist = this.wishlist.slice(-30);
|
||||
try {
|
||||
localStorage.setItem("skyart_cart", JSON.stringify(this.cart));
|
||||
localStorage.setItem(
|
||||
"skyart_wishlist",
|
||||
JSON.stringify(this.wishlist)
|
||||
);
|
||||
this.showNotification(
|
||||
"Storage limit reached. Older items removed.",
|
||||
"info"
|
||||
);
|
||||
} catch (retryError) {
|
||||
console.error("[ShopState] Failed to recover storage:", retryError);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CART METHODS
|
||||
// ========================================
|
||||
|
||||
addToCart(product, quantity = 1) {
|
||||
console.log("[ShopState] Adding to cart:", product);
|
||||
|
||||
const validation = ValidationUtils.validateProduct(product);
|
||||
if (!validation.valid) {
|
||||
console.error("[ShopState] Invalid product:", product);
|
||||
this.showNotification(validation.error, "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
quantity = ValidationUtils.validateQuantity(quantity);
|
||||
const existing = this._findById(this.cart, product.id);
|
||||
|
||||
if (existing) {
|
||||
existing.quantity = Math.min(existing.quantity + quantity, 999);
|
||||
} else {
|
||||
const sanitized = ValidationUtils.sanitizeProduct(
|
||||
product,
|
||||
validation.price
|
||||
);
|
||||
this.cart.push({ ...sanitized, quantity });
|
||||
}
|
||||
|
||||
return this._saveAndUpdate(
|
||||
"cart",
|
||||
product.name || product.title || "Item",
|
||||
"added to cart"
|
||||
);
|
||||
}
|
||||
|
||||
removeFromCart(productId) {
|
||||
console.log("[ShopState] Removing from cart:", productId);
|
||||
this.cart = this.cart.filter(
|
||||
(item) => String(item.id) !== String(productId)
|
||||
);
|
||||
this.saveToStorage();
|
||||
this.updateAllBadges();
|
||||
this.renderCartDropdown();
|
||||
this.showNotification("Item removed from cart", "info");
|
||||
|
||||
// Dispatch event for cart.js compatibility
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("cart-updated", { detail: this.cart })
|
||||
);
|
||||
}
|
||||
|
||||
updateCartQuantity(productId, quantity) {
|
||||
const item = this.cart.find(
|
||||
(item) => String(item.id) === String(productId)
|
||||
);
|
||||
if (item) {
|
||||
item.quantity = Math.max(1, quantity);
|
||||
this.saveToStorage();
|
||||
this.updateAllBadges();
|
||||
this.renderCartDropdown();
|
||||
|
||||
// Dispatch event for cart.js compatibility
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("cart-updated", { detail: this.cart })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getCartTotal() {
|
||||
return this.cart.reduce((sum, item) => {
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const quantity = parseInt(item.quantity) || 0;
|
||||
return sum + price * quantity;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
getCartCount() {
|
||||
return this.cart.reduce((sum, item) => {
|
||||
const quantity = parseInt(item.quantity) || 0;
|
||||
return sum + quantity;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// WISHLIST METHODS
|
||||
// ========================================
|
||||
|
||||
addToWishlist(product) {
|
||||
console.log("[ShopState] Adding to wishlist:", product);
|
||||
|
||||
const validation = ValidationUtils.validateProduct(product);
|
||||
if (!validation.valid) {
|
||||
console.error("[ShopState] Invalid product:", product);
|
||||
this.showNotification(validation.error, "error");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._findById(this.wishlist, product.id)) {
|
||||
this.showNotification("Already in wishlist", "info");
|
||||
return false;
|
||||
}
|
||||
|
||||
const sanitized = ValidationUtils.sanitizeProduct(
|
||||
product,
|
||||
validation.price
|
||||
);
|
||||
this.wishlist.push(sanitized);
|
||||
|
||||
return this._saveAndUpdate(
|
||||
"wishlist",
|
||||
product.name || product.title || "Item",
|
||||
"added to wishlist"
|
||||
);
|
||||
}
|
||||
|
||||
removeFromWishlist(productId) {
|
||||
console.log("[ShopState] Removing from wishlist:", productId);
|
||||
this.wishlist = this.wishlist.filter(
|
||||
(item) => String(item.id) !== String(productId)
|
||||
);
|
||||
this.saveToStorage();
|
||||
this.updateAllBadges();
|
||||
this.renderWishlistDropdown();
|
||||
this.showNotification("Item removed from wishlist", "info");
|
||||
|
||||
// Dispatch event for cart.js compatibility
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("wishlist-updated", { detail: this.wishlist })
|
||||
);
|
||||
}
|
||||
|
||||
isInWishlist(productId) {
|
||||
return !!this._findById(this.wishlist, productId);
|
||||
}
|
||||
|
||||
isInCart(productId) {
|
||||
return !!this._findById(this.cart, productId);
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
_findById(collection, id) {
|
||||
return collection.find((item) => String(item.id) === String(id));
|
||||
}
|
||||
|
||||
_saveAndUpdate(type, productName, action) {
|
||||
if (!this.saveToStorage()) return false;
|
||||
|
||||
this.updateAllBadges();
|
||||
if (type === "cart") {
|
||||
this.renderCartDropdown();
|
||||
} else {
|
||||
this.renderWishlistDropdown();
|
||||
}
|
||||
|
||||
this.showNotification(`${productName} ${action}`, "success");
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(`${type}-updated`, { detail: this[type] })
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// UI UPDATE METHODS
|
||||
// ========================================
|
||||
|
||||
updateAllBadges() {
|
||||
// Update cart badge
|
||||
const cartBadge = document.getElementById("cartCount");
|
||||
if (cartBadge) {
|
||||
const count = this.getCartCount();
|
||||
cartBadge.textContent = count;
|
||||
cartBadge.style.display = count > 0 ? "flex" : "none";
|
||||
}
|
||||
|
||||
// Update wishlist badge
|
||||
const wishlistBadge = document.getElementById("wishlistCount");
|
||||
if (wishlistBadge) {
|
||||
const count = this.wishlist.length;
|
||||
wishlistBadge.textContent = count;
|
||||
wishlistBadge.style.display = count > 0 ? "flex" : "none";
|
||||
}
|
||||
}
|
||||
|
||||
renderCartDropdown() {
|
||||
const cartContent = document.getElementById("cartContent");
|
||||
if (!cartContent) return;
|
||||
|
||||
if (this.cart.length === 0) {
|
||||
cartContent.innerHTML =
|
||||
'<p class="empty-state"><i class="bi bi-cart-x"></i><br>Your cart is empty</p>';
|
||||
this.updateCartFooter(0);
|
||||
return;
|
||||
}
|
||||
|
||||
cartContent.innerHTML = this.cart
|
||||
.map((item) => this.createCartItemHTML(item))
|
||||
.join("");
|
||||
this.updateCartFooter(this.getCartTotal());
|
||||
this.attachCartEventListeners();
|
||||
}
|
||||
|
||||
createCartItemHTML(item) {
|
||||
const imageUrl =
|
||||
item.imageurl ||
|
||||
item.imageUrl ||
|
||||
item.image_url ||
|
||||
"/assets/images/placeholder.jpg";
|
||||
const price = parseFloat(item.price || 0).toFixed(2);
|
||||
const subtotal = (parseFloat(item.price || 0) * item.quantity).toFixed(2);
|
||||
|
||||
return `
|
||||
<div class="cart-item" data-id="${item.id}">
|
||||
<img src="${imageUrl}" alt="${this.escapeHtml(
|
||||
item.name
|
||||
)}" class="cart-item-image" loading="lazy" onerror="this.src='/assets/images/placeholder.svg'">
|
||||
<div class="cart-item-details">
|
||||
<h4 class="cart-item-title">${this.escapeHtml(item.name)}</h4>
|
||||
<p class="cart-item-price">$${price}</p>
|
||||
<div class="cart-item-quantity">
|
||||
<button class="quantity-btn quantity-minus" data-id="${item.id}">
|
||||
<i class="bi bi-dash"></i>
|
||||
</button>
|
||||
<span class="quantity-value">${item.quantity}</span>
|
||||
<button class="quantity-btn quantity-plus" data-id="${item.id}">
|
||||
<i class="bi bi-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<p class="cart-item-subtotal">Subtotal: $${subtotal}</p>
|
||||
</div>
|
||||
<button class="cart-item-remove" data-id="${item.id}">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
attachCartEventListeners() {
|
||||
// Remove buttons
|
||||
document.querySelectorAll(".cart-item-remove").forEach((btn) => {
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.dataset.id;
|
||||
this.removeFromCart(id);
|
||||
});
|
||||
});
|
||||
|
||||
// Quantity minus
|
||||
document.querySelectorAll(".quantity-minus").forEach((btn) => {
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.dataset.id;
|
||||
const item = this.cart.find((i) => String(i.id) === String(id));
|
||||
if (item && item.quantity > 1) {
|
||||
this.updateCartQuantity(id, item.quantity - 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Quantity plus
|
||||
document.querySelectorAll(".quantity-plus").forEach((btn) => {
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.dataset.id;
|
||||
const item = this.cart.find((i) => String(i.id) === String(id));
|
||||
if (item) {
|
||||
this.updateCartQuantity(id, item.quantity + 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateCartFooter(total) {
|
||||
const footer = document.querySelector("#cartPanel .dropdown-foot");
|
||||
if (!footer) return;
|
||||
|
||||
if (total === 0) {
|
||||
footer.innerHTML =
|
||||
'<a href="/shop" class="btn-outline">Continue Shopping</a>';
|
||||
} else {
|
||||
footer.innerHTML = `
|
||||
<div class="cart-total">
|
||||
<span>Total:</span>
|
||||
<strong>$${total.toFixed(2)}</strong>
|
||||
</div>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<button class="btn-primary-full" onclick="alert('Checkout coming soon!')">
|
||||
Proceed to Checkout
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
renderWishlistDropdown() {
|
||||
const wishlistContent = document.getElementById("wishlistContent");
|
||||
if (!wishlistContent) return;
|
||||
|
||||
if (this.wishlist.length === 0) {
|
||||
wishlistContent.innerHTML =
|
||||
'<p class="empty-state"><i class="bi bi-heart"></i><br>Your wishlist is empty</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
wishlistContent.innerHTML = this.wishlist
|
||||
.map((item) => this.createWishlistItemHTML(item))
|
||||
.join("");
|
||||
this.attachWishlistEventListeners();
|
||||
}
|
||||
|
||||
createWishlistItemHTML(item) {
|
||||
const imageUrl =
|
||||
item.imageurl ||
|
||||
item.imageUrl ||
|
||||
item.image_url ||
|
||||
"/assets/images/placeholder.jpg";
|
||||
const price = parseFloat(item.price || 0).toFixed(2);
|
||||
|
||||
return `
|
||||
<div class="wishlist-item" data-id="${item.id}">
|
||||
<img src="${imageUrl}" alt="${this.escapeHtml(
|
||||
item.name
|
||||
)}" class="wishlist-item-image" loading="lazy" onerror="this.src='/assets/images/placeholder.svg'">
|
||||
<div class="wishlist-item-details">
|
||||
<h4 class="wishlist-item-title">${this.escapeHtml(item.name)}</h4>
|
||||
<p class="wishlist-item-price">$${price}</p>
|
||||
<button class="btn-add-to-cart" data-id="${item.id}">
|
||||
<i class="bi bi-cart-plus"></i> Add to Cart
|
||||
</button>
|
||||
</div>
|
||||
<button class="wishlist-item-remove" data-id="${item.id}">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
attachWishlistEventListeners() {
|
||||
// Remove buttons
|
||||
document.querySelectorAll(".wishlist-item-remove").forEach((btn) => {
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.dataset.id;
|
||||
this.removeFromWishlist(id);
|
||||
});
|
||||
});
|
||||
|
||||
// Add to cart buttons
|
||||
document.querySelectorAll(".btn-add-to-cart").forEach((btn) => {
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.dataset.id;
|
||||
const item = this.wishlist.find((i) => String(i.id) === String(id));
|
||||
if (item) {
|
||||
this.addToCart(item, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// DROPDOWN TOGGLE METHODS
|
||||
// ========================================
|
||||
|
||||
setupDropdowns() {
|
||||
// Cart dropdown
|
||||
const cartToggle = document.getElementById("cartToggle");
|
||||
const cartPanel = document.getElementById("cartPanel");
|
||||
const cartClose = document.getElementById("cartClose");
|
||||
|
||||
if (cartToggle && cartPanel) {
|
||||
cartToggle.addEventListener("click", () => {
|
||||
cartPanel.classList.toggle("active");
|
||||
this.renderCartDropdown();
|
||||
});
|
||||
}
|
||||
|
||||
if (cartClose) {
|
||||
cartClose.addEventListener("click", () => {
|
||||
cartPanel.classList.remove("active");
|
||||
});
|
||||
}
|
||||
|
||||
// Wishlist dropdown
|
||||
const wishlistToggle = document.getElementById("wishlistToggle");
|
||||
const wishlistPanel = document.getElementById("wishlistPanel");
|
||||
const wishlistClose = document.getElementById("wishlistClose");
|
||||
|
||||
if (wishlistToggle && wishlistPanel) {
|
||||
wishlistToggle.addEventListener("click", () => {
|
||||
wishlistPanel.classList.toggle("active");
|
||||
this.renderWishlistDropdown();
|
||||
});
|
||||
}
|
||||
|
||||
if (wishlistClose) {
|
||||
wishlistClose.addEventListener("click", () => {
|
||||
wishlistPanel.classList.remove("active");
|
||||
});
|
||||
}
|
||||
|
||||
// Close dropdowns when clicking outside
|
||||
document.addEventListener("click", (e) => {
|
||||
if (!e.target.closest(".cart-dropdown-wrapper") && cartPanel) {
|
||||
cartPanel.classList.remove("active");
|
||||
}
|
||||
if (!e.target.closest(".wishlist-dropdown-wrapper") && wishlistPanel) {
|
||||
wishlistPanel.classList.remove("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// NOTIFICATION SYSTEM
|
||||
// ========================================
|
||||
|
||||
showNotification(message, type = "info") {
|
||||
// Remove existing notifications
|
||||
document
|
||||
.querySelectorAll(".shop-notification")
|
||||
.forEach((n) => n.remove());
|
||||
|
||||
const notification = document.createElement("div");
|
||||
notification.className = `shop-notification notification-${type}`;
|
||||
notification.textContent = message;
|
||||
|
||||
const bgColors = {
|
||||
success: "#10b981",
|
||||
error: "#ef4444",
|
||||
info: "#3b82f6",
|
||||
};
|
||||
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
right: 20px;
|
||||
background: ${bgColors[type] || bgColors.info};
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
z-index: 10000;
|
||||
animation: slideInRight 0.3s ease;
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.animation = "slideOutRight 0.3s ease";
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// UTILITY METHODS
|
||||
// ========================================
|
||||
|
||||
escapeHtml(text) {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// INITIALIZE SYSTEM
|
||||
// ========================================
|
||||
|
||||
// Create global instance
|
||||
window.ShopSystem = new ShopState();
|
||||
|
||||
// ========================================
|
||||
// APPSTATE COMPATIBILITY LAYER
|
||||
// ========================================
|
||||
// Provide AppState interface for cart.js compatibility
|
||||
window.AppState = {
|
||||
get cart() {
|
||||
return window.ShopSystem.cart;
|
||||
},
|
||||
get wishlist() {
|
||||
return window.ShopSystem.wishlist;
|
||||
},
|
||||
addToCart: (product, quantity = 1) => {
|
||||
window.ShopSystem.addToCart(product, quantity);
|
||||
},
|
||||
removeFromCart: (productId) => {
|
||||
window.ShopSystem.removeFromCart(productId);
|
||||
},
|
||||
updateCartQuantity: (productId, quantity) => {
|
||||
window.ShopSystem.updateCartQuantity(productId, quantity);
|
||||
},
|
||||
getCartTotal: () => {
|
||||
return window.ShopSystem.getCartTotal();
|
||||
},
|
||||
getCartCount: () => {
|
||||
return window.ShopSystem.getCartCount();
|
||||
},
|
||||
addToWishlist: (product) => {
|
||||
window.ShopSystem.addToWishlist(product);
|
||||
},
|
||||
removeFromWishlist: (productId) => {
|
||||
window.ShopSystem.removeFromWishlist(productId);
|
||||
},
|
||||
isInWishlist: (productId) => {
|
||||
return window.ShopSystem.isInWishlist(productId);
|
||||
},
|
||||
showNotification: (message, type) => {
|
||||
window.ShopSystem.showNotification(message, type);
|
||||
},
|
||||
};
|
||||
|
||||
console.log("[ShopSystem] AppState compatibility layer installed");
|
||||
|
||||
// Setup dropdowns when DOM is ready
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
window.ShopSystem.setupDropdowns();
|
||||
});
|
||||
} else {
|
||||
window.ShopSystem.setupDropdowns();
|
||||
}
|
||||
|
||||
// Add animation styles
|
||||
if (!document.getElementById("shop-system-styles")) {
|
||||
const style = document.createElement("style");
|
||||
style.id = "shop-system-styles";
|
||||
style.textContent = `
|
||||
@keyframes slideInRight {
|
||||
from { transform: translateX(400px); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
@keyframes slideOutRight {
|
||||
from { transform: translateX(0); opacity: 1; }
|
||||
to { transform: translateX(400px); opacity: 0; }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
console.log("[ShopSystem] Ready!");
|
||||
})();
|
||||
Reference in New Issue
Block a user