import { State , Action , StateContext , Selector } from '@ngxs/store' ; import { mergeMap , catchError , take , tap } from 'rxjs/operators' ; import { of } from 'rxjs' ; import { GetCoffeeListSuccess , GetCoffeeListFailed , AddToCart , RemoveCartItem , RemoveOneCartItem , EmptyCart , AddToCoffeeList , GetCoffeeList , DummySetState , AddOneCartItem } from './app.actions' ; import { CoffeeService } from '../services/coffee.service' ; export const getAppInitialState = ( ) : App => ( { coffeeList : [ ] , cart : [ ] } ) ; @ State < App > ( { name : 'app' , defaults : getAppInitialState ( ) } ) export class AppState { constructor ( private coffeeSvc ) { } @ Selector ( ) static coffeeList ( state ) { return state . coffeeList ; } @ Selector ( ) static totalCartAmount ( state ) { const priceList = state . cart . map ( c => { const unitPrice = state . coffeeList . find ( x => x . name === c . name ) . price ; return unitPrice * c . quantity ; } ) ; const sum = priceList . reduce ( ( acc , curr ) => acc + curr , 0 ) ; return sum ; } @ Selector ( ) static totalCartQuantity ( state ) { const total = state . cart . reduce ( ( acc , curr ) => acc + curr . quantity , 0 ) ; return total ; } @ Action ( GetCoffeeList ) async getCoffeeList ( ctx , action ) { try { const coffeeList = await this . coffeeSvc . getList ( ) ; const state = ctx . getState ( ) ; ctx . setState ( { ... state , coffeeList } ) ; } catch ( error ) { ctx . dispatch ( new GetCoffeeListFailed ( error ) ) ; } } @ Action ( [ AddToCart , AddOneCartItem ] ) addToCart ( ctx , action ) { const state = ctx . getState ( ) ; const { quantity = 0 } = state . cart . find ( x => x . name === action . payload ) || { } ; const current = { cart : [ ... state . cart . filter ( x => x . name !== action . payload ) , { name : action . payload , quantity : quantity + 1 } ] } ; ctx . setState ( { ... state , ... current } ) ; } @ Action ( RemoveCartItem ) removeCartItem ( ctx , action ) { const state = ctx . getState ( ) ; const current = { cart : [ ... state . cart . filter ( x => x . name !== action . payload ) ] } ; ctx . setState ( { ... state , ... current } ) ; } @ Action ( RemoveOneCartItem ) removeOneCartItem ( ctx , action ) { const state = ctx . getState ( ) ; const item = state . cart . find ( x => x . name === action . payload ) ; const current = { cart : [ ... state . cart . filter ( x => x . name !== action . payload ) , ... ( item . quantity - 1 <= 0 ? [ ] : [ { name : item . name , quantity : item . quantity - 1 } ] ) ] } ; ctx . setState ( { ... state , ... current } ) ; } @ Action ( EmptyCart ) emptyCart ( ctx , action ) { const state = ctx . getState ( ) ; const current = { cart : [ ] } ; ctx . setState ( { ... state , ... current } ) ; } @ Action ( AddToCoffeeList ) addToCoffeeList ( ctx , action ) { const state = ctx . getState ( ) ; const current = { coffeeList : [ ... state . coffeeList , ... action . payload ] } ; ctx . setState ( { ... state , ... current } ) ; } @ Action ( DummySetState ) dummySetState ( ctx , action ) { const state = ctx . getState ( ) ; const current = { ... action . payload } ; ctx . setState ( { ... state , ... current } ) ; } }