Source: app/actions/resources/publicActions.js

import createAction from 'redux-actions/lib/createAction';
import { getStaticContent } from 'common/src/app/actions/resources/staticContentActions';
import { getSearchResults, SearchType } from 'common/src/app/actions/resources/searchActions';
import { API_STATIC_PUBLIC_SUCCESS_STORIES_LANDING } from 'common/src/app/data/apiStatics';
import Pages from 'common/src/app/data/enum/Pages';
import { push as historyPush } from 'react-router-redux';
import ArticleType from 'common/src/app/data/enum/ArticleType';
import { apiPost } from './apiActions/apiRequest';
import { getValue } from '../../util/injector';
import { GATEWAY_CONTENT, GATEWAY_COMMUNITY } from '../../data/Injectables';
import { calculateBmi } from '../../util/BmiUtils';
import { RECIPE, PUBLIC_SUCCESS_STORY, SEVEN_DAY_MENU } from '../../data/entityTypes';
import StatusCode from '../../data/enum/StatusCode';
import dedupeAsyncThunk from '../../util/dedupeAsyncThunk';
import apiGetEntity from './apiActions/apiGetEntity';

/**
 * Public recipe
 */

export const PUBLIC_RECIPE_DETAIL = 'publicActions/PUBLIC_RECIPE_DETAIL';
export const getRecipeDetail = dedupeAsyncThunk(
  slug => dispatch =>
    dispatch(
      apiGetEntity(
        PUBLIC_RECIPE_DETAIL,
        GATEWAY_CONTENT,
        `/public-recipes/${slug}`,
        RECIPE,
        {
          findEntity: entity => entity.slug === slug,
          getId: entity => entity.id,
        },
        {
          updateEntityView: 'view.pages.recipeDetail.recipeDetail',
        },
      ),
    ).catch(error =>
      error?.response.status === StatusCode.STATUS_404
        ? dispatch(historyPush(Pages.UK_PUBLIC_RECIPE_SEARCH))
        : error,
    ),

  true,
);

export const PUBLIC_MENU_RECIPE_DETAIL = 'publicActions/PUBLIC_MENU_RECIPE_DETAIL';
export const getMenuRecipeDetail = dedupeAsyncThunk(
  slug => dispatch =>
    dispatch(
      apiGetEntity(
        PUBLIC_MENU_RECIPE_DETAIL,
        GATEWAY_CONTENT,
        `/public-recipes/${slug}`,
        SEVEN_DAY_MENU,
        {
          findEntity: entity => entity.slug === slug,
          getId: entity => entity.slug,
        },
      ),
    ),
  true,
);

export const SEARCH_PUBLIC_RECIPE_SETS = 'publicActions/SEARCH_PUBLIC_RECIPE_SETS';
export const searchRecipeSets = (queries, actionType, excludedIds, limit = 1) => dispatch =>
  Promise.all(
    queries.map(query =>
      dispatch(
        apiGetEntity(
          SEARCH_PUBLIC_RECIPE_SETS,
          GATEWAY_CONTENT,
          `/public-recipes/search`,
          actionType,
          query,
          {
            requestData: {
              query,
              limit,
              excludedIds,
            },
            transformEntity: entity => {
              const { link, ...rest } = entity[0];
              return {
                // Build up the slug from the link for recipes, if the slug does not exist
                slug: link && link.replace('/recipes/', ''),
                ...rest,
              };
            },
          },
        ),
      ),
    ),
  );

export const PUBLIC_SUCCESS_STORIES_DETAIL = 'searchActions/PUBLIC_SUCCESS_STORIES_DETAIL';
export const getPublicDetailSuccessStories = dedupeAsyncThunk(
  slug => dispatch =>
    dispatch(
      apiGetEntity(
        PUBLIC_SUCCESS_STORIES_DETAIL,
        GATEWAY_CONTENT,
        `/public-success-stories/${slug}`,
        PUBLIC_SUCCESS_STORY,
        {
          findEntity: entity => entity.link === `/public-success-stories/${slug}`,
          getId: entity => entity.id,
          transformEntity: entity => {
            const { link, ...rest } = entity;
            return {
              link: link.replace('/success-stories', '/real-life-stories'),
              ...rest,
            };
          },
        },
        {
          updateEntityView: 'view.pages.successStoriesDetail.successStory',
        },
      ),
    ),
  true,
);

export const getAntiForgeryTokenCommunity = () => () =>
  getValue(GATEWAY_COMMUNITY).get('/antiforgery', null, {
    credentials: 'include',
  });

export const SAVE_PUBLIC_BMI = 'public-actions/SAVE_PUBLIC_BMI';
const publicBmiAction = createAction(SAVE_PUBLIC_BMI);

export const calculatePublicBmi = values => dispatch =>
  dispatch(
    publicBmiAction(Math.round(calculateBmi(values.initialWeight, values.height) * 10) / 10),
  );

/**
 * Public Success stories landing page
 */

export const PUBLIC_SUCCESS_STORIES_LANDING = 'publicActions/PUBLIC_SUCCESS_STORIES_LANDING';

export const getPublicLandingSuccessStories = dedupeAsyncThunk(
  () => dispatch =>
    dispatch(
      getStaticContent(API_STATIC_PUBLIC_SUCCESS_STORIES_LANDING, true, entity => {
        const { featuredStory, ...rest } = entity;
        // Change the featuredStory type to be PublicSuccessStoryTile
        if (featuredStory) {
          featuredStory._type = ArticleType.PUBLIC_SUCCESS_STORY; // eslint-disable-line no-underscore-dangle
        }
        return {
          featuredStory,
          ...rest,
        };
      }),
    ).then(dispatch(getSearchResults(SearchType.PUBLIC_SUCCESS_STORIES))),
  true,
);

/**
 * SevenDayMenu - newsletter signup form submission
 */

export const SEVEN_DAY_MENU_SIGNUP = 'publicActions/SEVEN_DAY_MENU_SIGNUP';

export const sevenDayNewsletterSignUp = values => (dispatch, getState) => {
  // get the recaptchaToken from state
  // if the token is not found in state - the back end will fail and display an error to the signing up member
  const recaptchaToken = getState()?.config?.recaptchaToken;

  const mergedValues = { ...values, recaptchaToken };

  return dispatch(getAntiForgeryTokenCommunity()).then(result =>
    dispatch(
      apiPost(SEVEN_DAY_MENU_SIGNUP, GATEWAY_COMMUNITY, '/subscribe/seven-day-menu', mergedValues, {
        headers: {
          'X-XSRF-Token': result.data,
        },
        credentials: 'include',
      }),
    ).then(flowResult => flowResult),
  );
};

/**
 * SevenDayMenu - newsletter signup email confirmation
 * confirm the members email address, using the passed email address and token
 * this endpooint adds them onto the subscriber mailing list
 */

export const CONFIRM_NEWSLETTER_SIGNUP = 'publicActions/CONFIRM_NEWSLETTER_SIGNUP';

export const confirmNewsletterSignup = (email, token) => dispatch =>
  dispatch(getAntiForgeryTokenCommunity()).then(result =>
    dispatch(
      apiPost(
        CONFIRM_NEWSLETTER_SIGNUP,
        GATEWAY_COMMUNITY,
        '/subscribe/verify-seven-day-menu',
        {
          email,
          token,
        },
        {
          headers: {
            'X-XSRF-Token': result.data,
          },
          credentials: 'include',
        },
      ),
    ).then(validationResult => validationResult?.data),
  );

export const PERSIST_HIDE_NAV = 'publicActions/PERSIST_HIDE_NAV';
export const setPersistHideNav = createAction(PERSIST_HIDE_NAV);