From d3563bbda28e42e98423e4da6b43428478131f35 Mon Sep 17 00:00:00 2001 From: J-Laurent Quenin Date: Fri, 5 Apr 2024 14:54:32 +0200 Subject: [PATCH] =?UTF-8?q?feat(cart):=20premi=C3=A8re=20version=20exercic?= =?UTF-8?q?e=20by=20JL=20Quenin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit en attente du push de la fonction de calcul du total --- .../app/components/fruits-list.component.ts | 20 +++++--- .../rxjs-app/shared/services/cart.service.ts | 50 +++++++++++++++---- .../shared/services/fruits.service.ts | 12 +++-- 3 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/app/rxjs-app/app/components/fruits-list.component.ts b/src/app/rxjs-app/app/components/fruits-list.component.ts index 0b0ff12..a51967d 100644 --- a/src/app/rxjs-app/app/components/fruits-list.component.ts +++ b/src/app/rxjs-app/app/components/fruits-list.component.ts @@ -1,21 +1,29 @@ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; -import { FruitService } from '../../shared/services/fruits.service'; -import { CartService } from '../../shared/services/cart.service'; +import {ChangeDetectionStrategy, Component, inject, OnInit} from '@angular/core'; +import {FruitService} from '../../shared/services/fruits.service'; +import {CartService} from '../../shared/services/cart.service'; +import {Fruit} from "../../shared/model/fruit"; +import {Observable} from "rxjs"; @Component({ selector: 'app-fruits-list', template: ` -
- {{fruit.name}} - {{fruit.price}}€ +
+ {{ fruit.name }} - {{ fruit.price }}€
`, styles: ``, changeDetection: ChangeDetectionStrategy.OnPush }) -export class FruitsListComponent { +export class FruitsListComponent implements OnInit { fruitsService = inject(FruitService) cartService = inject(CartService) + fruitsList$?: Observable; + + ngOnInit() { + this.fruitsList$ = this.fruitsService.fruitList + + } } diff --git a/src/app/rxjs-app/shared/services/cart.service.ts b/src/app/rxjs-app/shared/services/cart.service.ts index bec75fa..f340176 100644 --- a/src/app/rxjs-app/shared/services/cart.service.ts +++ b/src/app/rxjs-app/shared/services/cart.service.ts @@ -1,18 +1,18 @@ -import { Injectable } from '@angular/core'; -import { Fruit, FruitState } from '../model/fruit'; -import { BehaviorSubject, Observable, map } from 'rxjs'; +import {Injectable} from '@angular/core'; +import {Fruit, FruitState} from '../model/fruit'; +import {BehaviorSubject, Observable} from 'rxjs'; @Injectable({ providedIn: 'root' }) export class CartService { - /* Le type du panier peut faire peur, nous allons le décomposer + /* Le type du panier peut faire peur, nous allons le décomposer - L'état du panier est stocké sous la forme d'une Map - K est la clé de notre map, ici un nombre, qui va correspondre à l'id d'un fruit - V est un objet de type FruitState, qui est le type Fruit avec une quantité associée - - Par exemple, pour représenter 10 oranges dans notre panier : + - Par exemple, pour représenter 10 oranges dans notre panier : cart.set(2, { id: 2, name: "Orange", price: 3, quantity: 10 }) - La clé est 2, id de notre fruit - { id: 2, @@ -25,7 +25,7 @@ export class CartService { cart$: Observable> /* Pour ceux qui veulent aller plus loin : - - Implémenter un observable total$, qui renvoie le prix total du panier + - Implémenter un observable total$, qui renvoie le prix total du panier */ total$!: Observable @@ -35,6 +35,22 @@ export class CartService { - Le fruit n'est pas déja dans le panier - Le fruit est déja dans le panier */ + const lastValue = this._cart.getValue() + + if (lastValue.has(fruit.id)) { + const fruitInCart = lastValue.get(fruit.id) + let fruitInCartQuantity = fruitInCart?.quantity + + if (fruitInCart && fruitInCartQuantity) { + fruitInCartQuantity++ + lastValue.set(fruit.id, {...fruit, quantity: fruitInCartQuantity}) + } + } else { + lastValue.set(fruit.id, {...fruit, quantity: 1}) + } + + this._cart.next(lastValue); + } /* /!\ Pour les méthodes addFruit(), removeFruit() et removeAllFruitOfType(), attention à ne pas muter la Map existante */ @@ -43,21 +59,33 @@ export class CartService { /* Enlève un fruit dans le panier /* Deux cas à considerer : - Il reste un fruit de ce type dans le panier, enlever l'entrée dans la map - - Il reste plusieurs fruits de ce type dans le panier, dans ce cas enlever tous les types de fruits + - Il reste plusieurs fruits de ce type dans le panier, dans ce cas enlever tous les types de fruits */ + const lastValue = this._cart.getValue() + + if (lastValue.has(fruit.id)) { + const fruitInCart = lastValue.get(fruit.id) + let fruitInCartQuantity = fruitInCart?.quantity + + if (fruitInCart && fruitInCartQuantity && fruitInCartQuantity > 1) { + fruitInCartQuantity-- + lastValue.set(fruit.id, {...fruit, quantity: fruitInCartQuantity}) + } else if (fruitInCart && fruitInCartQuantity && fruitInCartQuantity == 1) + lastValue.delete(fruit.id) + } + + this._cart.next(lastValue); } removeAllFruitOfType(fruit: Fruit) { /* Enlève tous les fruits d'un type dans le panier */ + this._cart.getValue().delete(fruit.id) } /* Ici le constructeur nous donne une valeur par défaut pour le panier, mais il n'est pas indispensable */ constructor() { - const defaultMap = new Map() - defaultMap.set(1, { id: 1, name: "Pomme", price: 1, quantity: 5 }) - defaultMap.set(2, { id: 2, name: "Orange", price: 3, quantity: 10 }) - this._cart = new BehaviorSubject(defaultMap) + this._cart = new BehaviorSubject(new Map()) this.cart$ = this._cart.asObservable() } diff --git a/src/app/rxjs-app/shared/services/fruits.service.ts b/src/app/rxjs-app/shared/services/fruits.service.ts index 7fb07cf..43f6b4c 100644 --- a/src/app/rxjs-app/shared/services/fruits.service.ts +++ b/src/app/rxjs-app/shared/services/fruits.service.ts @@ -1,19 +1,21 @@ -import { Injectable } from '@angular/core'; +import {inject, Injectable} from '@angular/core'; import { Fruit } from '../model/fruit'; +import {HttpClient} from "@angular/common/http"; +import {Observable} from "rxjs"; @Injectable({ providedIn: 'root' }) export class FruitService { + readonly FRUITS_URL = "http://localhost:3000/fruits" + _http = inject(HttpClient); + get fruitList() { return this._list } /* Remplacer cette liste par un appel http */ - private readonly _list: Fruit[] = [ - { id: 1, name: "Pomme", price: 1 }, - { id: 2, name: "Orange", price: 3 }, - ] + private readonly _list = this._http.get(this.FRUITS_URL); }