From 03bb5e70ee1a81dfb1db1bc50be9609d6ea219f9 Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Tue, 6 May 2025 08:33:46 +0200 Subject: [PATCH] feat(product-selection): add loading state during product fetch --- .../product-quantity/product-quantity.component.html | 2 +- .../product-quantity/product-quantity.component.ts | 3 ++- .../product-selection.component.html | 10 +++++++--- .../product-selection/product-selection.component.ts | 11 ++++++++--- src/app/services/product.service.ts | 12 +++++++----- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/app/product-quantity/product-quantity.component.html b/src/app/product-quantity/product-quantity.component.html index aa78cfc..b47245c 100644 --- a/src/app/product-quantity/product-quantity.component.html +++ b/src/app/product-quantity/product-quantity.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/product-quantity/product-quantity.component.ts b/src/app/product-quantity/product-quantity.component.ts index 4c3d07b..8df853a 100644 --- a/src/app/product-quantity/product-quantity.component.ts +++ b/src/app/product-quantity/product-quantity.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, signal } from '@angular/core'; import { Product } from '../product-selection/product-selection.component'; import { FormsModule } from '@angular/forms'; import { ProductService } from '../services/product.service'; @@ -11,6 +11,7 @@ import { ProductService } from '../services/product.service'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ProductQuantityComponent { + @Input({ required: true }) set product(value: Product | null) { this.productService.setProduct(value); } diff --git a/src/app/product-selection/product-selection.component.html b/src/app/product-selection/product-selection.component.html index 0712a8f..679abff 100644 --- a/src/app/product-selection/product-selection.component.html +++ b/src/app/product-selection/product-selection.component.html @@ -1,4 +1,8 @@ - + + \ No newline at end of file diff --git a/src/app/product-selection/product-selection.component.ts b/src/app/product-selection/product-selection.component.ts index 8b5f224..d51b79a 100644 --- a/src/app/product-selection/product-selection.component.ts +++ b/src/app/product-selection/product-selection.component.ts @@ -1,4 +1,4 @@ -import { NgFor } from '@angular/common'; +import { NgFor, NgIf } from '@angular/common'; import { CurrencyPipe } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Component, ChangeDetectionStrategy, Output, EventEmitter, signal, inject, computed, OnInit } from '@angular/core'; @@ -20,7 +20,7 @@ export type Product = { @Component({ selector: 'app-product-selection', standalone: true, - imports: [NgFor, CurrencyPipe, FormsModule], + imports: [NgFor, CurrencyPipe, FormsModule, NgIf], templateUrl: './product-selection.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) @@ -31,6 +31,8 @@ export class ProductSelectionComponent implements OnInit { selectedProduct = signal(null); quantity = signal(1); + + isProductLoading = signal(true); @Output() quantityChange = new EventEmitter(); @Output() productChange = new EventEmitter(); @@ -38,7 +40,10 @@ export class ProductSelectionComponent implements OnInit { private productService = inject(ProductService); ngOnInit() { - this.productService.getProducts().subscribe(products => this.products.set(products)); + this.productService.getProducts().subscribe(products => { + this.products.set(products); + this.isProductLoading.set(false); + }); } onProductChange(selectedProduct: Product) { diff --git a/src/app/services/product.service.ts b/src/app/services/product.service.ts index e4df12d..44df20a 100644 --- a/src/app/services/product.service.ts +++ b/src/app/services/product.service.ts @@ -1,6 +1,6 @@ import { Injectable, signal, WritableSignal } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable, shareReplay } from 'rxjs'; +import { delay, Observable, shareReplay } from 'rxjs'; import { Product } from '../product-selection/product-selection.component'; @Injectable({ @@ -12,7 +12,6 @@ export class ProductService { constructor(private http: HttpClient) {} - // Local state management setProduct(product: Product | null): void { this.productSignal.set(product); if (product) { @@ -32,12 +31,15 @@ export class ProductService { return this.quantitySignal(); } - // API calls getProducts(): Observable { - return this.http.get('https://fakestoreapi.com/products'); + return this.http.get('https://fakestoreapi.com/products').pipe( + delay(1000) + ); } getProductById(id: number): Observable { - return this.http.get(`https://fakestoreapi.com/products/${id}`); + return this.http.get(`https://fakestoreapi.com/products/${id}`).pipe( + delay(1000) + ); } } \ No newline at end of file