fix: add action list
This commit is contained in:
158
js/store/cart.js
Normal file
158
js/store/cart.js
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Cart Store
|
||||
* Manages shopping cart state with localStorage persistence
|
||||
* Dispatches 'cart-updated' events when cart changes
|
||||
*/
|
||||
|
||||
const CART_STORAGE_KEY = "milinda-cart";
|
||||
|
||||
class CartStore {
|
||||
constructor() {
|
||||
this.items = this.loadFromStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load cart from localStorage
|
||||
*/
|
||||
loadFromStorage() {
|
||||
try {
|
||||
const stored = localStorage.getItem(CART_STORAGE_KEY);
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
} catch (e) {
|
||||
console.error("Failed to load cart from storage:", e);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save cart to localStorage
|
||||
*/
|
||||
saveToStorage() {
|
||||
try {
|
||||
localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(this.items));
|
||||
} catch (e) {
|
||||
console.error("Failed to save cart to storage:", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch cart-updated event
|
||||
*/
|
||||
notifyUpdate() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("cart-updated", {
|
||||
detail: {
|
||||
items: this.items,
|
||||
count: this.getItemCount(),
|
||||
total: this.getTotal(),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item to cart
|
||||
* @param {Object} item - Item to add { title, author, price, type, image }
|
||||
*/
|
||||
addItem(item) {
|
||||
// Check if item already exists (by title and type)
|
||||
const existingIndex = this.items.findIndex(
|
||||
(i) => i.title === item.title && i.type === item.type
|
||||
);
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// Increment quantity
|
||||
this.items[existingIndex].quantity += 1;
|
||||
} else {
|
||||
// Add new item
|
||||
this.items.push({
|
||||
...item,
|
||||
quantity: 1,
|
||||
addedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
this.saveToStorage();
|
||||
this.notifyUpdate();
|
||||
|
||||
return this.items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item from cart
|
||||
* @param {number} index - Index of item to remove
|
||||
*/
|
||||
removeItem(index) {
|
||||
if (index >= 0 && index < this.items.length) {
|
||||
this.items.splice(index, 1);
|
||||
this.saveToStorage();
|
||||
this.notifyUpdate();
|
||||
}
|
||||
return this.items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update item quantity
|
||||
* @param {number} index - Index of item
|
||||
* @param {number} quantity - New quantity
|
||||
*/
|
||||
updateQuantity(index, quantity) {
|
||||
if (index >= 0 && index < this.items.length) {
|
||||
if (quantity <= 0) {
|
||||
this.removeItem(index);
|
||||
} else {
|
||||
this.items[index].quantity = quantity;
|
||||
this.saveToStorage();
|
||||
this.notifyUpdate();
|
||||
}
|
||||
}
|
||||
return this.items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all items from cart
|
||||
*/
|
||||
clear() {
|
||||
this.items = [];
|
||||
this.saveToStorage();
|
||||
this.notifyUpdate();
|
||||
return this.items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items
|
||||
*/
|
||||
getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total item count (sum of quantities)
|
||||
*/
|
||||
getItemCount() {
|
||||
return this.items.reduce((sum, item) => sum + item.quantity, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cart total price
|
||||
*/
|
||||
getTotal() {
|
||||
return this.items.reduce((sum, item) => {
|
||||
// Parse price like "€ 24,95" to number
|
||||
const priceStr = item.price || "0";
|
||||
const price = parseFloat(
|
||||
priceStr.replace(/[€$£\s]/g, "").replace(",", ".")
|
||||
);
|
||||
return sum + price * item.quantity;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Create singleton instance
|
||||
const cart = new CartStore();
|
||||
|
||||
// Export for module use
|
||||
export default cart;
|
||||
|
||||
// Also attach to window for global access
|
||||
window.cartStore = cart;
|
||||
Reference in New Issue
Block a user