graycoreio/daffodil

View on GitHub
libs/product/state/src/selectors/best-sellers/best-sellers.selectors.ts

Summary

Maintainability
A
1 hr
Test Coverage
import {
  createSelector,
  MemoizedSelector,
} from '@ngrx/store';

import { DaffProduct } from '@daffodil/product';

import { DaffBestSellersReducerState } from '../../reducers/best-sellers/best-sellers-reducer-state.interface';
import {
  DaffProductReducersState,
  DaffProductStateRootSlice,
} from '../../reducers/product-reducers-state.interface';
import { getDaffProductEntitiesSelectors } from '../product-entities/product-entities.selectors';
import { getDaffProductFeatureSelector } from '../product-feature.selector';

/**
 * An interface for the available best sellers selectors.
 */
export interface DaffBestSellersMemoizedSelectors<T extends DaffProduct = DaffProduct> {
  /**
   * Selector for best sellers feature state
   */
  selectBestSellersState: MemoizedSelector<DaffProductStateRootSlice<T>, DaffBestSellersReducerState>;
  /**
   * Selector for the loading state of best selling products.
   */
  selectBestSellersLoadingState: MemoizedSelector<DaffProductStateRootSlice<T>, boolean>;
  /**
   * Selector for the IDs of best selling products.
   */
  selectBestSellersIdsState: MemoizedSelector<DaffProductStateRootSlice<T>, T['id'][]>;
  /**
   * Selector for the best selling products.
   */
  selectBestSellersProducts: MemoizedSelector<DaffProductStateRootSlice<T>, T[]>;
}

const createBestSellersSelectors = <T extends DaffProduct>(): DaffBestSellersMemoizedSelectors<T> => {
  const {
    selectAllProducts,
  } = getDaffProductEntitiesSelectors<T>();
  const {
    selectProductState,
  } = getDaffProductFeatureSelector<T>();

  const selectBestSellersState = createSelector(
    selectProductState,
    (state: DaffProductReducersState<T>) => state.bestSellers,
  );

  const selectBestSellersLoadingState = createSelector(
    selectBestSellersState,
    (state: DaffBestSellersReducerState) => state.loading,
  );

  const selectBestSellersIdsState = createSelector(
    selectBestSellersState,
    (state: DaffBestSellersReducerState) => state.productIds,
  );

  const selectBestSellersProducts = createSelector<DaffProductStateRootSlice<T>, [string[], T[]], T[]>(
    selectBestSellersIdsState,
    selectAllProducts,
    (ids: T['id'][], products: T[]) => products.filter(product => ids.indexOf(product.id) > -1),
  );

  return {
    selectBestSellersState,
    selectBestSellersLoadingState,
    selectBestSellersIdsState,
    selectBestSellersProducts,
  };
};

/**
 * A function that returns all selectors related to best sellers state.
 *
 * Returns {@link DaffBestSellersMemoizedSelectors}.
 */
export const getDaffBestSellersSelectors = (() => {
  let cache;
  return <T extends DaffProduct>(): DaffBestSellersMemoizedSelectors<T> => cache = cache
    ? cache
    : createBestSellersSelectors<T>();
})();