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

269 lines
6.8 KiB
JavaScript
Raw 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) {
2026-01-04 17:52:37 -06:00
const existing = this._findById(this.state.cart, product.id);
2026-01-01 22:24:30 -06:00
if (existing) {
existing.quantity += quantity;
} else {
this.state.cart.push({
...product,
quantity,
addedAt: Date.now(),
});
}
2026-01-04 17:52:37 -06:00
this._updateState("cart");
2026-01-01 22:24:30 -06:00
return this.state.cart;
}
removeFromCart(productId) {
2026-01-04 17:52:37 -06:00
this.state.cart = this.state.cart.filter(
(item) => String(item.id) !== String(productId)
);
this._updateState("cart");
2026-01-01 22:24:30 -06:00
return this.state.cart;
}
updateCartQuantity(productId, quantity) {
2026-01-04 17:52:37 -06:00
const item = this._findById(this.state.cart, productId);
2026-01-01 22:24:30 -06:00
if (item) {
item.quantity = Math.max(0, quantity);
if (item.quantity === 0) {
return this.removeFromCart(productId);
}
2026-01-04 17:52:37 -06:00
this._updateState("cart");
2026-01-01 22:24:30 -06:00
}
return this.state.cart;
}
getCart() {
return this.state.cart;
}
getCartTotal() {
2026-01-04 17:52:37 -06:00
return this._calculateTotal(this.state.cart);
2026-01-01 22:24:30 -06:00
}
getCartCount() {
2026-01-04 17:52:37 -06:00
return this._calculateCount(this.state.cart);
2026-01-01 22:24:30 -06:00
}
clearCart() {
this.state.cart = [];
2026-01-04 17:52:37 -06:00
this._updateState("cart");
2026-01-01 22:24:30 -06:00
}
// 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);
}
});
}
}
2026-01-04 17:52:37 -06:00
// Helper methods
_findById(collection, id) {
return collection.find((item) => String(item.id) === String(id));
}
_updateState(type) {
this.saveToStorage();
this.emit(`${type}Updated`, this.state[type]);
}
_calculateTotal(items) {
return items.reduce((sum, item) => {
const price = parseFloat(item.price) || 0;
const quantity = parseInt(item.quantity) || 0;
return sum + price * quantity;
}, 0);
}
_calculateCount(items) {
return items.reduce((sum, item) => {
const quantity = parseInt(item.quantity) || 0;
return sum + quantity;
}, 0);
}
2026-01-01 22:24:30 -06:00
}
// 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 badges = document.querySelectorAll(".cart-badge, #cartCount");
const count = window.StateManager.getCartCount();
badges.forEach((badge) => {
if (badge) {
badge.textContent = count;
if (count > 0) {
badge.classList.add("show");
} else {
badge.classList.remove("show");
}
}
});
2026-01-01 22:24:30 -06:00
});
window.StateManager.on("wishlistUpdated", () => {
const badges = document.querySelectorAll(".wishlist-badge, #wishlistCount");
const count = window.StateManager.getWishlist().length;
badges.forEach((badge) => {
if (badge) {
badge.textContent = count;
if (count > 0) {
badge.classList.add("show");
} else {
badge.classList.remove("show");
}
}
});
2026-01-01 22:24:30 -06:00
});
// 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");
}
})();