import { EntityState } from '@ngrx/entity' ; import { createSelector , MemoizedSelector , defaultMemoize , } from '@ngrx/store' ; import { daffSubtract } from '@daffodil/core' ; import { DaffProduct } from '@daffodil/product' ; import { daffProductEntitiesAdapter } from '../../reducers/product-entities/product-entities-reducer-adapter' ; import { DaffProductReducersState , DaffProductStateRootSlice , } from '../../reducers/product-reducers-state.interface' ; import { getDaffProductFeatureSelector } from '../product-feature.selector' ; /**
 * An interface for selectors related to product entities and prices for simple products.
 */ export interface DaffProductEntitiesMemoizedSelectors < T extends DaffProduct = DaffProduct > { /**
     * Selects the ngrx entities state for products.
     */ selectProductEntitiesState : MemoizedSelector < DaffProductStateRootSlice < T > , EntityState < T > > ; /**
     * Selects all ids for products in state.
     */ selectProductIds : MemoizedSelector < DaffProductStateRootSlice < T > , EntityState < T > [ 'ids' ] > ; /**
     * Selects the ngrx entities for all products in state.
     */ selectProductEntities : MemoizedSelector < DaffProductStateRootSlice < T > , EntityState < T > [ 'entities' ] > ; /**
     * Selects all products in state as an array.
     */ selectAllProducts : MemoizedSelector < DaffProductStateRootSlice < T > , T [ ] > ; /**
     * Selects the total number of products in state.
     */ selectProductTotal : MemoizedSelector < DaffProductStateRootSlice < T > , number > ; param productId selectProduct : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , T > ; param productId selectProductPrice : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , number > ; param productId selectProductDiscountAmount : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , number > ; param productId selectProductDiscountedPrice : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , number > ; param productId selectProductDiscountPercent : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , number > ; param productId selectProductHasDiscount : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , boolean > ; param productId selectIsProductOutOfStock : ( productId : T [ 'id' ] ) => MemoizedSelector < DaffProductStateRootSlice < T > , boolean > ; } const createProductEntitiesSelectors = < T extends DaffProduct > ( ) : DaffProductEntitiesMemoizedSelectors < T > => { const { selectProductState , } = getDaffProductFeatureSelector < T > ( ) ; const adapterSelectors = daffProductEntitiesAdapter < T > ( ) . getSelectors ( ) ; /**
     * Product Entities State
     */ const selectProductEntitiesState = createSelector ( selectProductState , ( state ) => state . products ) ; /**
     * Adapters created with @ngrx/entity generate
     * commonly used selector functions including
     * getting all ids in the record set, a dictionary
     * of the records by id, an array of records and
     * the total number of records. This reduces boilerplate
     * in selecting records from the entity state.
     */ const selectProductIds = createSelector ( selectProductEntitiesState , adapterSelectors . selectIds ) ; const selectProductEntities = createSelector ( selectProductEntitiesState , adapterSelectors . selectEntities ) ; const selectAllProducts = createSelector ( selectProductEntitiesState , adapterSelectors . selectAll ) ; const selectProductTotal = createSelector ( selectProductEntitiesState , adapterSelectors . selectTotal ) ; const selectProduct = defaultMemoize ( ( productId ) => createSelector ( selectProductEntities , products => products [ productId ] ) ) . memoized ; const selectProductPrice = defaultMemoize ( ( productId ) => createSelector ( selectProduct ( productId ) , ( product ) => product ?. price || null ) ) . memoized ; const selectProductDiscountAmount = defaultMemoize ( ( productId ) => createSelector ( selectProduct ( productId ) , ( product ) => product ?. discount ?. amount || 0 ) ) . memoized ; const selectProductDiscountedPrice = defaultMemoize ( ( productId ) => createSelector ( selectProductPrice ( productId ) , selectProductDiscountAmount ( productId ) , ( price , discountAmount ) => daffSubtract ( price , discountAmount ) ) ) . memoized ; const selectProductDiscountPercent = defaultMemoize ( ( productId ) => createSelector ( selectProduct ( productId ) , ( product ) => product . discount ?. percent || 0 ) ) . memoized ; const selectProductHasDiscount = defaultMemoize ( ( productId ) => createSelector ( selectProductDiscountAmount ( productId ) , ( discountAmount ) => ! ! discountAmount ) ) . memoized ; const selectIsProductOutOfStock = defaultMemoize ( ( productId ) => createSelector ( selectProduct ( productId ) , ( product ) => product ? ! product . in_stock : null ) ) . memoized ; return { selectProductEntitiesState , selectProductIds , selectProductEntities , selectAllProducts , selectProductTotal , selectProduct , selectProductPrice , selectProductDiscountAmount , selectProductDiscountedPrice , selectProductDiscountPercent , selectProductHasDiscount , selectIsProductOutOfStock , } ; } ; /**
 * A function that returns all selectors related to product entities and simple product prices.
 */ export const getDaffProductEntitiesSelectors = ( ( ) => { let cache ; return < T extends DaffProduct > ( ) : DaffProductEntitiesMemoizedSelectors < T > => cache = cache ? cache : createProductEntitiesSelectors < T > ( ) ; } ) ( ) ;