updateweb
This commit is contained in:
236
website/assets/js/state-manager.js
Normal file
236
website/assets/js/state-manager.js
Normal file
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
* Global State Management
|
||||
* Centralized state for cart, wishlist, and user preferences
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
class StateManager {
|
||||
constructor() {
|
||||
this.state = {
|
||||
cart: [],
|
||||
wishlist: [],
|
||||
user: null,
|
||||
preferences: {},
|
||||
};
|
||||
this.listeners = {};
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.loadFromStorage();
|
||||
this.setupStorageSync();
|
||||
}
|
||||
|
||||
loadFromStorage() {
|
||||
try {
|
||||
this.state.cart = JSON.parse(localStorage.getItem("cart") || "[]");
|
||||
this.state.wishlist = JSON.parse(
|
||||
localStorage.getItem("wishlist") || "[]"
|
||||
);
|
||||
this.state.preferences = JSON.parse(
|
||||
localStorage.getItem("preferences") || "{}"
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("State load error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
saveToStorage() {
|
||||
try {
|
||||
localStorage.setItem("cart", JSON.stringify(this.state.cart));
|
||||
localStorage.setItem("wishlist", JSON.stringify(this.state.wishlist));
|
||||
localStorage.setItem(
|
||||
"preferences",
|
||||
JSON.stringify(this.state.preferences)
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("State save error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
setupStorageSync() {
|
||||
window.addEventListener("storage", (e) => {
|
||||
if (e.key === "cart" || e.key === "wishlist") {
|
||||
this.loadFromStorage();
|
||||
this.emit("stateChanged", { key: e.key });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Cart methods
|
||||
addToCart(product, quantity = 1) {
|
||||
const existing = this.state.cart.find((item) => item.id === product.id);
|
||||
|
||||
if (existing) {
|
||||
existing.quantity += quantity;
|
||||
} else {
|
||||
this.state.cart.push({
|
||||
...product,
|
||||
quantity,
|
||||
addedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
this.saveToStorage();
|
||||
this.emit("cartUpdated", this.state.cart);
|
||||
return this.state.cart;
|
||||
}
|
||||
|
||||
removeFromCart(productId) {
|
||||
this.state.cart = this.state.cart.filter((item) => item.id !== productId);
|
||||
this.saveToStorage();
|
||||
this.emit("cartUpdated", this.state.cart);
|
||||
return this.state.cart;
|
||||
}
|
||||
|
||||
updateCartQuantity(productId, quantity) {
|
||||
const item = this.state.cart.find((item) => item.id === productId);
|
||||
if (item) {
|
||||
item.quantity = Math.max(0, quantity);
|
||||
if (item.quantity === 0) {
|
||||
return this.removeFromCart(productId);
|
||||
}
|
||||
this.saveToStorage();
|
||||
this.emit("cartUpdated", this.state.cart);
|
||||
}
|
||||
return this.state.cart;
|
||||
}
|
||||
|
||||
getCart() {
|
||||
return this.state.cart;
|
||||
}
|
||||
|
||||
getCartTotal() {
|
||||
return this.state.cart.reduce(
|
||||
(sum, item) => sum + item.price * item.quantity,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
getCartCount() {
|
||||
return this.state.cart.reduce((sum, item) => sum + item.quantity, 0);
|
||||
}
|
||||
|
||||
clearCart() {
|
||||
this.state.cart = [];
|
||||
this.saveToStorage();
|
||||
this.emit("cartUpdated", this.state.cart);
|
||||
}
|
||||
|
||||
// Wishlist methods
|
||||
addToWishlist(product) {
|
||||
const exists = this.state.wishlist.find((item) => item.id === product.id);
|
||||
|
||||
if (!exists) {
|
||||
this.state.wishlist.push({
|
||||
...product,
|
||||
addedAt: Date.now(),
|
||||
});
|
||||
this.saveToStorage();
|
||||
this.emit("wishlistUpdated", this.state.wishlist);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
removeFromWishlist(productId) {
|
||||
this.state.wishlist = this.state.wishlist.filter(
|
||||
(item) => item.id !== productId
|
||||
);
|
||||
this.saveToStorage();
|
||||
this.emit("wishlistUpdated", this.state.wishlist);
|
||||
return this.state.wishlist;
|
||||
}
|
||||
|
||||
getWishlist() {
|
||||
return this.state.wishlist;
|
||||
}
|
||||
|
||||
isInWishlist(productId) {
|
||||
return this.state.wishlist.some((item) => item.id === productId);
|
||||
}
|
||||
|
||||
// Event system
|
||||
on(event, callback) {
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push(callback);
|
||||
}
|
||||
|
||||
off(event, callback) {
|
||||
if (this.listeners[event]) {
|
||||
this.listeners[event] = this.listeners[event].filter(
|
||||
(cb) => cb !== callback
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
emit(event, data) {
|
||||
if (this.listeners[event]) {
|
||||
this.listeners[event].forEach((callback) => {
|
||||
try {
|
||||
callback(data);
|
||||
} catch (e) {
|
||||
console.error(`Error in ${event} listener:`, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create global instance
|
||||
window.StateManager = window.StateManager || new StateManager();
|
||||
|
||||
// Expose helper functions for backward compatibility
|
||||
window.addToCart = function (productId, name, price, imageurl) {
|
||||
const product = { id: productId, name, price: parseFloat(price), imageurl };
|
||||
window.StateManager.addToCart(product, 1);
|
||||
if (window.showNotification) {
|
||||
window.showNotification(`${name} added to cart!`, "success");
|
||||
}
|
||||
};
|
||||
|
||||
window.addToWishlist = function (productId, name, price, imageurl) {
|
||||
const product = { id: productId, name, price: parseFloat(price), imageurl };
|
||||
const added = window.StateManager.addToWishlist(product);
|
||||
if (window.showNotification) {
|
||||
window.showNotification(
|
||||
added ? `${name} added to wishlist!` : "Already in wishlist!",
|
||||
added ? "success" : "info"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Update badges on state changes
|
||||
window.StateManager.on("cartUpdated", () => {
|
||||
const badge = document.querySelector(".cart-badge");
|
||||
if (badge) {
|
||||
const count = window.StateManager.getCartCount();
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? "flex" : "none";
|
||||
}
|
||||
});
|
||||
|
||||
window.StateManager.on("wishlistUpdated", () => {
|
||||
const badge = document.querySelector(".wishlist-badge");
|
||||
if (badge) {
|
||||
const count = window.StateManager.getWishlist().length;
|
||||
badge.textContent = count;
|
||||
badge.style.display = count > 0 ? "flex" : "none";
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize badges
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
window.StateManager.emit("cartUpdated");
|
||||
window.StateManager.emit("wishlistUpdated");
|
||||
});
|
||||
} else {
|
||||
window.StateManager.emit("cartUpdated");
|
||||
window.StateManager.emit("wishlistUpdated");
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user