product-details.component.ts (2556B)
1 import { Component, effect, inject, input, signal } from '@angular/core'; 2 import { ProductService } from './products.service'; 3 import { CommonModule } from '@angular/common'; 4 import { CartService } from '../services/cart.service'; 5 import { RouterLink } from '@angular/router'; 6 7 @Component({ 8 selector: 'div.product-details', 9 templateUrl: './product-details.component.html', 10 styleUrls: ['./product-details.component.scss'], 11 standalone: true, 12 imports: [CommonModule, RouterLink], 13 }) 14 export class ProductDetailsComponent { 15 private productService = inject(ProductService); 16 private cartService = inject(CartService); 17 // Input signal for productId from route parameter 18 readonly productId = input<string>(''); 19 20 // State signals 21 readonly product = signal<Product | null>(null); 22 readonly loading = signal<boolean>(false); 23 readonly error = signal<string | null>(null); 24 25 constructor() { 26 // Effect to load product when productId changes 27 effect(() => { 28 const id = this.productId(); 29 if (id) { 30 this.loadProduct(id); 31 } 32 }); 33 } 34 35 private loadProduct(id: string): void { 36 this.loading.set(true); 37 this.error.set(null); 38 39 this.productService.getProduct(id).subscribe({ 40 next: (product) => { 41 this.product.set(product); 42 this.loading.set(false); 43 }, 44 error: (err) => { 45 console.error('Failed to load product:', err); 46 this.error.set('Failed to load product details. Please try again.'); 47 this.loading.set(false); 48 }, 49 }); 50 } 51 52 get discount(): number { 53 const product = this.product() as Product; 54 const initial = parseFloat(product.initial_price || '0'); 55 const discount = parseFloat(product.discount || '0'); 56 return initial > 0 ? Math.round((discount / initial) * 100) : 0; 57 } 58 59 addToCart(): void { 60 const product = this.product(); 61 if (product && product.stock > 0) { 62 // Convert Product to ProductCard format for cart service 63 const productCard: ProductCard = { 64 eid: product.eid, 65 product_name: product.product_name, 66 description: product.description, 67 category_name: product.category_name, 68 final_price: product.final_price, 69 initial_price: product.initial_price, 70 discount: product.discount, 71 stock: product.stock, 72 average_rating: null, // Not available in Product interface 73 reviews_count: null, // Not available in Product interface 74 brand: product.brand, 75 }; 76 this.cartService.addToCart(productCard); 77 } 78 } 79 }