Source: app/actions/resources/publicityActions.js

import { createAction } from 'redux-actions';
import Pages from 'common/src/app/data/enum/Pages';
import { push as historyPush } from 'react-router-redux';
import authenticate from 'common/src/app/util/auth/authenticate';
import { PublicityEntryTypes } from 'common/src/app/data/enum/PublicityEntryTypes';
import { userIdSelector } from '../../selectors/userAccountSelectors';
import { apiGet, apiPost, apiPatch, apiPut, apiDelete } from './apiActions/apiRequest';
import { GATEWAY_PUBLICITY_AUTH } from '../../data/Injectables';

export const GET_PUBLICITY_ENTRY_OVERVIEW = 'publicityActions/GET_PUBLICITY_ENTRY_OVERVIEW';

export const RECEIVE_PUBLICITY_ENTRY_OVERVIEW = 'publicityActions/RECEIVE_PUBLICITY_ENTRY_OVERVIEW';
export const receivePublicityEntryOverview = createAction(RECEIVE_PUBLICITY_ENTRY_OVERVIEW);

/**
 * Gets the current success story or competition entry for the authenticated user
 * @param {string} entryType
 */
export const getPublicityEntryOverview = entryType => async (dispatch, getState) => {
  if (entryType === undefined) {
    return null;
  }
  await authenticate();
  const userId = userIdSelector(getState());

  return await dispatch(
    apiGet(
      GET_PUBLICITY_ENTRY_OVERVIEW,
      GATEWAY_PUBLICITY_AUTH,
      `/${entryType}?memberId=${userId}`,
    ),
  )
    .then(({ data }) => {
      dispatch(receivePublicityEntryOverview({ entryType, data }));
      return data;
    })
    .catch(error => {
      if (error.response && error.response.status === 404) {
        const returnUrl =
          entryType === PublicityEntryTypes.COMPETITION
            ? Pages.ACCOUNT_SETTINGS_COMPETITION_ENTRIES
            : Pages.SHARE_STORY_OVERVIEW;
        dispatch(historyPush(returnUrl));
      }
    });
};

export const GET_PUBLICITY_SUCCESS_STORIES_OVERVIEW =
  'publicityActions/GET_PUBLICITY_SUCCESS_STORIES_OVERVIEW';

export const RECEIVE_MEMBERS_SUCCESS_STORIES_OVERVIEW =
  'publicityActions/RECEIVE_MEMBERS_SUCCESS_STORIES_OVERVIEW';
export const receiveMembersSuccessStoriesOverview = createAction(
  RECEIVE_MEMBERS_SUCCESS_STORIES_OVERVIEW,
);

/**
 * Gets a list of all the success stories submitted by the authenticated user
 */
export const getMembersSuccessStoriesOverview = () => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());
  const { data } = await dispatch(
    apiGet(
      GET_PUBLICITY_SUCCESS_STORIES_OVERVIEW,
      GATEWAY_PUBLICITY_AUTH,
      `/members/${userId}/success-stories-overview`,
    ),
  );

  return dispatch(receiveMembersSuccessStoriesOverview({ data }));
};

export const GET_PUBLICITY_COMPETITION_ENTRIES_OVERVIEW =
  'publicityActions/GET_PUBLICITY_COMPETITION_ENTRIES_OVERVIEW';

export const RECEIVE_MEMBERS_COMPETITION_ENTRIES_OVERVIEW =
  'publicityActions/RECEIVE_MEMBERS_COMPETITION_ENTRIES_OVERVIEW';
export const receiveMembersCompetitionEntriesOverview = createAction(
  RECEIVE_MEMBERS_COMPETITION_ENTRIES_OVERVIEW,
);

/**
 * Gets a list of all the competition entries submitted by the authenticated user
 */
export const getMembersCompetitionEntriesOverview = () => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());
  const { data } = await dispatch(
    apiGet(
      GET_PUBLICITY_COMPETITION_ENTRIES_OVERVIEW,
      GATEWAY_PUBLICITY_AUTH,
      `/members/${userId}/competitions-overview`,
    ),
  );

  return dispatch(receiveMembersCompetitionEntriesOverview({ data }));
};

export const CREATE_SUCCESS_STORY = 'publicityActions/CREATE_SUCCESS_STORY';

/**
 * Creates a success story entry in the database, this is needed for the success story overview page
 */
export const createSuccessStory = () => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());
  const { data } = await dispatch(
    apiPost(CREATE_SUCCESS_STORY, GATEWAY_PUBLICITY_AUTH, `/success-stories?memberId=${userId}`),
  );

  return dispatch(receivePublicityEntryOverview({ entryType: 'successStories', data }));
};

export const CONFIRM_ENTRY_DETAILS = 'publicityActions/CONFIRM_ENTRY_DETAILS';

/**
 * Confirms the entry details of the user
 * @param {object} values
 * @param {string} entryType
 * @param {int} id
 */
export const confirmEntryDetails = (values, entryType, id, isCouplesCompetition = false) => async (
  dispatch,
  getState,
) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const endpoint = isCouplesCompetition ? 'couples-details' : 'details';

  await dispatch(
    apiPut(
      CONFIRM_ENTRY_DETAILS,
      GATEWAY_PUBLICITY_AUTH,
      `/${entryType}/${id}/${endpoint}?memberId=${userId}`,
      values,
    ),
  );
};

export const GET_MEMBERS_ENTRY_DETAILS = 'publicityActions/GET_MEMBERS_ENTRY_DETAILS';

export const RECEIVE_MEMBERS_ENTRY_DETAILS = 'publicityActions/RECEIVE_MEMBERS_ENTRY_DETAILS';
export const receiveMembersEntryDetails = createAction(RECEIVE_MEMBERS_ENTRY_DETAILS);

/**
 * Gets the users personal details for a given entry
 * @param {string} entryType
 * @param {int} id
 */
export const getMembersEntryDetails = (entryType, id, isCouplesCompetition = false) => async (
  dispatch,
  getState,
) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const endpoint = isCouplesCompetition ? 'couples-details' : 'details';

  const { data } = await dispatch(
    apiGet(
      GET_MEMBERS_ENTRY_DETAILS,
      GATEWAY_PUBLICITY_AUTH,
      `/${entryType}/${id}/${endpoint}?memberId=${userId}`,
    ),
  );

  dispatch(receiveMembersEntryDetails({ id, entryType, data }));
};

export const RECEIVE_PUBLICITY_ENTRY_QUESTIONS =
  'publicityActions/RECEIVE_PUBLICITY_ENTRY_QUESTIONS';
export const receivePublicityEntryQuestions = createAction(RECEIVE_PUBLICITY_ENTRY_QUESTIONS);

export const GET_PUBLICITY_ENTRY_QUESTIONS = 'publicityActions/GET_PUBLICITY_ENTRY_QUESTIONS';

/**
 * Gets the questionnaire for the currently active success story or competition entry
 * @param {string} entryType
 * @param {int} entryId
 */
export const getPublicityEntryQuestions = (entryType, entryId) => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());
  const { data } = await dispatch(
    apiGet(
      GET_PUBLICITY_ENTRY_QUESTIONS,
      GATEWAY_PUBLICITY_AUTH,
      `/${entryType}/${entryId}/questionnaire?memberId=${userId}`,
    ),
  );

  dispatch(receivePublicityEntryQuestions({ entryId, entryType, data }));

  return data;
};

export const POST_PUBLICITY_ENTRY_ANSWER = 'publicityActions/POST_PUBLICITY_ENTRY_ANSWER';

export const SET_PUBLICITY_ENTRY_ANSWER = 'publicityActions/SET_PUBLICITY_ENTRY_ANSWER';
export const setPublicityEntryAnswer = createAction(SET_PUBLICITY_ENTRY_ANSWER);

/**
 * Saves a questionnaire answer to the database
 * @param {int} sectionId
 * @param {int} questionId
 * @param {string} answerText
 * @param {string} entryType
 * @param {int} entryId
 */
export const postPublicityEntryAnswer = (
  sectionId,
  questionId,
  answerText,
  entryType,
  entryId,
) => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const idType =
    entryType === PublicityEntryTypes.COMPETITION ? 'competitionEntryId' : 'successStoryId';

  const { data } = await dispatch(
    apiPost(POST_PUBLICITY_ENTRY_ANSWER, GATEWAY_PUBLICITY_AUTH, `/answers?memberId=${userId}`, {
      questionId,
      answerText,
      [idType]: entryId,
    }),
  );

  dispatch(
    setPublicityEntryAnswer({
      sectionId,
      questionId,
      answerId: data,
      answerText,
      entryType,
      entryId,
    }),
  );

  return data;
};

/**
 * Updates the answer to a question
 * @param {int} sectionId
 * @param {int} questionId
 * @param {int} answerId
 * @param {string} answerText
 * @param {string} entryType
 * @param {int} entryId
 */
export const updatePublicityEntryAnswer = (
  sectionId,
  questionId,
  answerId,
  answerText,
  entryType,
  entryId,
) => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const idType =
    entryType === PublicityEntryTypes.COMPETITION ? 'competitionEntryId' : 'successStoryId';

  const { data } = await dispatch(
    apiPut(POST_PUBLICITY_ENTRY_ANSWER, GATEWAY_PUBLICITY_AUTH, `/answers?memberId=${userId}`, {
      answerId,
      answerText,
      [idType]: entryId,
    }),
  );

  dispatch(
    setPublicityEntryAnswer({ sectionId, questionId, answerId, answerText, entryType, entryId }),
  );

  return data;
};

export const RECEIVE_PUBLICITY_ENTRY_PHOTOS = 'publicityActions/RECEIVE_PUBLICITY_ENTRY_PHOTOS';
export const receivePublicityEntryPhotos = createAction(RECEIVE_PUBLICITY_ENTRY_PHOTOS);

export const GET_PUBLICITY_ENTRY_PHOTOS = 'publicityActions/GET_PUBLICITY_ENTRY_PHOTOS';

/**
 * Gets the photos for the given competition or success story entry
 * @param {string} entryType
 * @param {int} entryId
 */
export const getPublicityEntryPhotos = (entryType, entryId) => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const idType =
    entryType === PublicityEntryTypes.COMPETITION ? 'competitionEntryId' : 'successStoryId';

  const { data } = await dispatch(
    apiGet(GET_PUBLICITY_ENTRY_PHOTOS, GATEWAY_PUBLICITY_AUTH, `/publicity-photos`, {
      memberId: userId,
      [idType]: entryId,
    }),
  );

  dispatch(receivePublicityEntryPhotos({ entryId, entryType, data }));

  return data;
};

export const SET_PUBLICITY_ENTRY_COMPLETE = 'publicityActions/SET_PUBLICITY_ENTRY_COMPLETE';

export const UPDATE_PUBLICITY_ENTRY_STATE = 'publicityActions/UPDATE_PUBLICITY_ENTRY_STATE';
export const updatePublicityEntryState = createAction(UPDATE_PUBLICITY_ENTRY_STATE);

/**
 * Sets a competition or success stories status to complete
 * @param {string} entryType
 * @param {int} entryId
 */
export const setPublicityEntryComplete = (entryType, entryId) => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const response = await dispatch(
    apiPut(
      SET_PUBLICITY_ENTRY_COMPLETE,
      GATEWAY_PUBLICITY_AUTH,
      `/${entryType}/${entryId}/complete?memberId=${userId}`,
    ),
  ).then(() => dispatch(updatePublicityEntryState({ entryType, entryId, submitted: true })));

  return response;
};

export const POST_PUBLICITY_PHOTO = 'publicityActions/POST_PUBLICITY_PHOTO';

export const ADD_PUBLICITY_ENTRY_PHOTOS = 'publicityActions/ADD_PUBLICITY_ENTRY_PHOTOS';
export const addPublicityEntryPhotos = createAction(ADD_PUBLICITY_ENTRY_PHOTOS);

/**
 * Uploads a photo for a competition entry or success story
 * @param {string} base64
 * @param {string} entryType
 * @param {int} entryId
 */
export const postPublicityPhoto = (base64, entryType, entryId) => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const idType =
    entryType === PublicityEntryTypes.COMPETITION ? 'competitionEntryId' : 'successStoryId';

  const { data } = await dispatch(
    apiPost(POST_PUBLICITY_PHOTO, GATEWAY_PUBLICITY_AUTH, `/publicity-photos?memberId=${userId}`, {
      base64,
      [idType]: entryId,
    }),
  );

  return data;
};

export const DELETE_PUBLICITY_ENTRY_PHOTO = 'publicityActions/DELETE_PUBLICITY_ENTRY_PHOTO';

export const REMOVE_PUBLICITY_ENTRY_PHOTO = 'publicityActions/REMOVE_PUBLICITY_ENTRY_PHOTO';
export const removePublicityEntryPhoto = createAction(REMOVE_PUBLICITY_ENTRY_PHOTO);

export const deletePublicityEntryPhoto = (photoId, entryType, entryId) => async (
  dispatch,
  getState,
) => {
  await authenticate();
  const userId = userIdSelector(getState());

  await dispatch(
    apiDelete(
      DELETE_PUBLICITY_ENTRY_PHOTO,
      GATEWAY_PUBLICITY_AUTH,
      `/publicity-photos/${photoId}?memberId=${userId}`,
    ),
  );

  dispatch(removePublicityEntryPhoto({ photoId, entryType, entryId }));
};

export const PATCH_PUBLICITY_ENTRY_PHOTO = 'publicityActions/PATCH_PUBLICITY_ENTRY_PHOTO';

export const SET_PUBLICITY_PHOTO_CAPTION = 'publicityActions/SET_PUBLICITY_PHOTO_CAPTION';
export const setPublicityPhotoCaption = createAction(SET_PUBLICITY_PHOTO_CAPTION);

export const patchPublicityEntryPhoto = (photoId, caption, entryType, entryId) => async (
  dispatch,
  getState,
) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const response = await dispatch(
    apiPatch(
      PATCH_PUBLICITY_ENTRY_PHOTO,
      GATEWAY_PUBLICITY_AUTH,
      `/publicity-photos/${photoId}?memberId=${userId}`,
      {
        caption,
      },
    ),
  );

  dispatch(setPublicityPhotoCaption({ photoId, caption, entryType, entryId }));

  return response;
};

export const GET_COMPETITION_BANNER_INFO = 'publicityActions/GET_COMPETITION_BANNER_INFO';

export const RECEIVE_COMPETITION_BANNER_INFO = 'publicityActions/RECEIVE_COMPETITION_BANNER_INFO';
export const receiveCompetitionBannerInfo = createAction(RECEIVE_COMPETITION_BANNER_INFO);

export const getCompetitionBannerInfo = () => async (dispatch, getState) => {
  await authenticate();
  const userId = userIdSelector(getState());

  const response = await dispatch(
    apiGet(
      GET_COMPETITION_BANNER_INFO,
      GATEWAY_PUBLICITY_AUTH,
      `/competition-entries/banner?memberId=${userId}`,
    ),
  ).catch(error => {
    // 404 is expected behavior if user does not have an active competition
    if (error?.response?.status === 404) {
      return null;
    }

    return error;
  });

  const data = response?.data || false;

  dispatch(receiveCompetitionBannerInfo(data));

  return data;
};