Files
SkyArtShop/website/assets/js/state-manager.js

237 lines
6.1 KiB
JavaScript
Raw Permalink Normal View History

2026-01-01 22:24:30 -06:00
/**
* 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");
}
})();