cart.service.ts (2784B)
1 import { Injectable, signal, computed } from '@angular/core'; 2 3 export interface CartItem { 4 product: ProductCard; 5 quantity: number; 6 addedAt: Date; 7 } 8 9 @Injectable({ 10 providedIn: 'root' 11 }) 12 export class CartService { 13 // Private signal for cart items 14 private readonly _cartItems = signal<CartItem[]>([]); 15 16 // Public readonly signals 17 readonly cartItems = this._cartItems.asReadonly(); 18 19 // Computed signals for derived state 20 readonly totalItems = computed(() => 21 this._cartItems().reduce((total, item) => total + item.quantity, 0) 22 ); 23 24 readonly totalPrice = computed(() => 25 this._cartItems().reduce((total, item) => 26 total + (parseFloat(item.product.final_price) * item.quantity), 0 27 ) 28 ); 29 30 readonly isEmpty = computed(() => this._cartItems().length === 0); 31 32 // Private helper methods 33 private findItemIndex(productId: string): number { 34 return this._cartItems().findIndex(item => item.product.eid === productId); 35 } 36 37 private findItem(productId: string): CartItem | undefined { 38 return this._cartItems().find(item => item.product.eid === productId); 39 } 40 41 private updateItems(updater: (items: CartItem[]) => CartItem[]): void { 42 this._cartItems.set(updater([...this._cartItems()])); 43 } 44 45 // Public methods 46 addToCart(product: ProductCard, quantity: number = 1): void { 47 const existingIndex = this.findItemIndex(product.eid); 48 49 if (existingIndex >= 0) { 50 // Update existing item 51 this.updateItems(items => { 52 items[existingIndex].quantity += quantity; 53 return items; 54 }); 55 } else { 56 // Add new item 57 this.updateItems(items => [ 58 ...items, 59 { product, quantity, addedAt: new Date() } 60 ]); 61 } 62 } 63 64 removeFromCart(productId: string): void { 65 this.updateItems(items => items.filter(item => item.product.eid !== productId)); 66 } 67 68 updateQuantity(productId: string, quantity: number): void { 69 if (quantity <= 0) { 70 this.removeFromCart(productId); 71 return; 72 } 73 74 this.updateItems(items => 75 items.map(item => 76 item.product.eid === productId 77 ? { ...item, quantity } 78 : item 79 ) 80 ); 81 } 82 83 increaseQuantity(productId: string): void { 84 const item = this.findItem(productId); 85 if (item) { 86 this.updateQuantity(productId, item.quantity + 1); 87 } 88 } 89 90 decreaseQuantity(productId: string): void { 91 const item = this.findItem(productId); 92 if (item) { 93 this.updateQuantity(productId, item.quantity - 1); 94 } 95 } 96 97 clearCart(): void { 98 this._cartItems.set([]); 99 } 100 101 // Query methods 102 getItem(productId: string): CartItem | undefined { 103 return this.findItem(productId); 104 } 105 106 hasItem(productId: string): boolean { 107 return this.findItemIndex(productId) >= 0; 108 } 109 }