state/defaultReducer.js

import { createAction } from 'redux-actions';
import { UTILS_ACTIONS_PREFIX } from '../config';

export const REDUCER_NAME = 'olaf';

/**
 * Constants for fetch status tracking.
 */
export const FETCH_STATUS = {
  IN_PROGRESS: 'IN_PROGRESS',
  SUCCESS: 'SUCCESS',
  ERROR: 'ERROR',
};

/**
 * Redux action dispatched for every fetch call.
 */
export const FETCH_STARTED_ACTION = `${UTILS_ACTIONS_PREFIX}FETCH_STARTED`;

/**
 * Redux action dispatched when fetch call finishes without errors.
 */
export const FETCH_SUCCESS_ACTION = `${UTILS_ACTIONS_PREFIX}FETCH_SUCCESS`;

/**
 * Redux action dispatched when fetch call finishes with/because of errors.
 */
export const FETCH_ERROR_ACTION = `${UTILS_ACTIONS_PREFIX}FETCH_ERROR`;

/**
 * Action for setting application info
 */
export const PUBLIC_SET_APP_INFO = `${UTILS_ACTIONS_PREFIX}SET_APP_INFO`;

/**
 * Initial global state.
 */
export const initialState = {
  appInfo: {
    appName: '',
  },
  statuses: {
    GLOBAL: {
      fetchInProgress: false,
      fetchStatus: undefined,
      fetchError: undefined,
    },
  },
};

/**
 * Reducer function. This reducer handles the following action types:
 * {@link PUBLIC_SET_APP_INFO}, {@link FETCH_STARTED_ACTION}, {@link FETCH_ERROR_ACTION},
 * {@link FETCH_SUCCESS_ACTION}
 *
 * @param {State} state - App state.
 * @param {ReduxAction} action - Redux Action.
 * @returns {state}
 */
export default function (state = initialState, action) {
  let statuses;

  switch (action.type) {
    case PUBLIC_SET_APP_INFO:
      return {
        ...state,
        appInfo: {
          ...state.appInfo,
          ...action.payload.appInfo,
        },
      };
    case FETCH_STARTED_ACTION:
      statuses = {
        [action.payload.tag]: {
          fetchInProgress: true,
          fetchStatus: FETCH_STATUS.IN_PROGRESS,
          fetchError: undefined,
        },
      };

      return {
        ...state,
        statuses: {
          ...state.statuses,
          ...statuses,
        },
      };
    case FETCH_ERROR_ACTION:
      statuses = {
        [action.payload.tag]: {
          fetchInProgress: false,
          fetchStatus: FETCH_STATUS.ERROR,
          fetchError: action.payload ? action.payload.error : undefined,
        },
      };

      return {
        ...state,
        statuses: {
          ...state.statuses,
          ...statuses,
        },
      };
    case FETCH_SUCCESS_ACTION:
      statuses = {
        [action.payload.tag]: {
          fetchInProgress: false,
          fetchStatus: FETCH_STATUS.SUCCESS,
          fetchError: undefined,
        },
      };

      return {
        ...state,
        statuses: {
          ...state.statuses,
          ...statuses,
        },
      };
    default:
      return state;
  }
}

export const INIT_ACTION = createAction('INIT_ACTION');

/**
 * Action creator. Dispatches {@link PUBLIC_SET_APP_INFO}.
 *
 * @function
 */
export const setAppInfoAction = createAction(PUBLIC_SET_APP_INFO);