94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
|
import { HttpClient } from '@angular/common/http';
|
||
|
import { Injectable } from '@angular/core';
|
||
|
import { BehaviorSubject, map } from 'rxjs';
|
||
|
import { environment } from 'src/environments/environment';
|
||
|
import { Basket, IBasket, IBasketItem, IBasketTotals } from '../shared/models/baskset';
|
||
|
import { IProduct } from '../shared/models/product';
|
||
|
|
||
|
@Injectable({
|
||
|
providedIn: 'root'
|
||
|
})
|
||
|
export class BasketService {
|
||
|
baseUrl = environment.apiUrl;
|
||
|
private basketSource = new BehaviorSubject<IBasket>(null);
|
||
|
basket$ = this.basketSource.asObservable();
|
||
|
private basketTotalSource = new BehaviorSubject<IBasketTotals>(null);
|
||
|
basketTotal$ = this.basketTotalSource.asObservable();
|
||
|
|
||
|
constructor(private http: HttpClient) { }
|
||
|
|
||
|
getBasket(id: string){
|
||
|
return this.http.get(this.baseUrl + 'basket?id=' + id).pipe(
|
||
|
map((basket: IBasket) => {
|
||
|
this.basketSource.next(basket);
|
||
|
this.calculateTotals();
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
|
||
|
setBasket(basket: IBasket){
|
||
|
return this.http.post(this.baseUrl + 'basket', basket).subscribe({
|
||
|
next: (response: IBasket) => {
|
||
|
this.basketSource.next(response);
|
||
|
this.calculateTotals();
|
||
|
},
|
||
|
error: (e: any) => { console.log(e); },
|
||
|
complete: () => { console.log('complete'); }
|
||
|
});
|
||
|
}
|
||
|
|
||
|
getCurrentBasketValue(){
|
||
|
return this.basketSource.value;
|
||
|
}
|
||
|
|
||
|
addItemToBasket(item: IProduct, quantity = 1){
|
||
|
const itemToAdd: IBasketItem = this.mapProductItemToBasketItem(item, quantity);
|
||
|
const basket = this.getCurrentBasketValue() ?? this.createBasket();
|
||
|
basket.items = this.addOrUpdateItem(basket.items, itemToAdd, quantity);
|
||
|
this.setBasket(basket);
|
||
|
}
|
||
|
|
||
|
private calculateTotals(){
|
||
|
const basket = this.getCurrentBasketValue();
|
||
|
const shipping = 0;
|
||
|
const subtotal = basket.items.reduce((a, b) => (b.price * b.quantity) + a, 0);
|
||
|
const total = subtotal + shipping;
|
||
|
this.basketTotalSource.next({
|
||
|
shipping,
|
||
|
total,
|
||
|
subtotal
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private addOrUpdateItem(items: IBasketItem[], itemToAdd: IBasketItem, quantity: number): IBasketItem[] {
|
||
|
const index = items.findIndex(i => i.id === itemToAdd.id);
|
||
|
if(index === -1){
|
||
|
itemToAdd.quantity = quantity;
|
||
|
items.push(itemToAdd);
|
||
|
} else {
|
||
|
items[index].quantity += quantity;
|
||
|
}
|
||
|
|
||
|
return items;
|
||
|
}
|
||
|
|
||
|
private createBasket(): IBasket {
|
||
|
const basket = new Basket();
|
||
|
localStorage.setItem('basket_id', basket.id);
|
||
|
return basket;
|
||
|
}
|
||
|
|
||
|
private mapProductItemToBasketItem(item: IProduct, quantity: number): IBasketItem {
|
||
|
return {
|
||
|
id: item.id,
|
||
|
productName: item.name,
|
||
|
price: item.price,
|
||
|
pictureUrl: item.pictureUrl,
|
||
|
quantity,
|
||
|
brand: item.productBrand,
|
||
|
type: item.productType
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|