Source: app/reducers/view/entityViewReducer.js

import handleActions from 'redux-actions/lib/handleActions';
import { createSelector } from 'reselect';
import find from 'lodash/find';
import { POST } from '../../data/entityTypes';
import { SET_ENTITY_VIEW_REF } from '../../actions/entities/entityViewActions';
import targetedReducer from '../../util/reducers/targetedReducer';

/**
 * @module entityViewReducer
 */

/**
 * A reducer that contains a reference to a single entity that is currently in view.
 */
const entityViewReducer = handleActions(
  {
    [SET_ENTITY_VIEW_REF]: (state, action) => ({
      ...state,
      ref: action.payload,
    }),
  },
  {
    ref: null,
  },
);

/**
 * Returns a new selector to get the entity data that is referenced in the given
 * entityViewReducer state. This selector will look up the referenced data in the
 * 'entities' reducer. For that reason, this returned selector should be passed
 * both the root reducer state and the entityViewReducer state.
 *
 * @function makeEntitySelector
 * @returns {function} A reselect selector function
 * @example const entitySelector = makeEntitySelector();
 * const currentFeaturedArticle = entitySelector(state, state.pages.home.featuredArticle);
 */
export const makeEntitySelector = () =>
  createSelector(
    [state => state.entities, (state, entityViewState) => entityViewState.ref],
    (allEntities, ref) => ref && allEntities[ref.type] && allEntities[ref.type][ref.id],
  );

export const makeEntityByTypeSelector = ({ entityType, entityKind }, slug) =>
  createSelector(
    state => state.entities,
    articleEntity => {
      let article = find(articleEntity?.[entityType], { slug: slug.replace('/', '') });

      if (entityType === POST) {
        article = articleEntity?.[entityType]?.[slug];
      }

      if (article) {
        const { id, title, description, image, text, media } = article;
        /**
         * The post tile has a different object for the image
         */
        if (entityType === POST) {
          return {
            id,
            title,
            description: text,
            image: {
              src: media && media.content,
            },
            entityKind,
          };
        }

        return {
          id,
          title,
          description,
          image,
          entityKind,
        };
      }

      return {};
    },
  );

export default targetedReducer(entityViewReducer);