sagas/auth.js

import {
  takeEvery, put, call, select,
} from 'redux-saga/effects';
/**
 * @namespace sagas/auth
 */
import Constants, { GAME_TYPE } from '../constants';
import { requestPost, requestGet } from '../utils/request';
import { parseNum } from '../utils/parser';

import {
  SET_LOADER,
  SET_USER_DATA,
  UPDATE_BALANCE,
  CHECK_SESSION,
  PLACEBET,
  LOGOUT_SUCCESS,
  LOGIN,
  LOGOUT,
  LOGIN_ERROR,
  SHOW_ERROR_MODAL,
  GET_BALANCE,
  GET_LOYALTY,
  SET_LOYALTY,
  OPEN_MODAL,
  GO_TO_MY_ACCOUNT_MENU,
  GO_TO_MY_ACCOUNT_MENU_SUCCESS,
  GET_OPEN_BETS,
  UPDATE_LAST_UPDATED_BALANCE_TIMESTAMP,
  SET_BALANCE_LOADING,
  CLEAR_NUM_OF_BETS,
  SET_INITIALISE_BET,
  CLEAR_SELECTIONS,
  REMOVE_ALL_TICKETS_FROM_COUNT,
  CLEAR_ALL_PLACED_SELECTIONS,
} from '../reducers';

import { getUser, getTargetPageAfterLogin } from '../store/common';
import {
  getGameType,
  getHaveLiveMatches,
} from '../store/bets';
import { getPlacebetAfterLogin } from '../store/placebet';
import { delay, sortFreeBets } from '../utils/common';

/**
 * @memberof sagas/auth
 * @typedef "user/response.data"
 * @type {object}
 * @property {object} user User information.
 * @property {string} sessionId
 * @property {Array} freeBets User's free bets. One free bet contain exparation date, stake and id

 */

/**
 * Check user session
 *
 * @memberof sagas/auth
 * @async
 * @yields {call} /session/checksession
 * @yields {put} SET_LOADER
 * @yields {put} SET_USER_DATA
 * @yields {put} GET_LOYALTY
 * @yields {put} SHOW_ERROR_MODAL
 */
function* checkSession() {
  let response;
  try {
    response = yield call(requestPost, Constants.API_URLS.CHECK_SESSION, null, true);

    if (response.status === -1) {
      yield put({
        type: SET_LOADER,
        payload: {
          isLoading: false,
        },
      });
    } else {
      response.data.user.balance.amount = parseNum(response.data.user.balance.amount);
      response.data.user.balance.bonusAmount = parseNum(response.data.user.balance.bonusAmount);
      yield put({
        type: SET_USER_DATA,
        payload: {
          user: response.data.user,
          sessionId: response.data.sessionId,
          freeBets: sortFreeBets(response.data.freeBets),
        },
      });
      if (response.data.hasNewFreeBets) {
        yield put({
          type: OPEN_MODAL,
          payload: {
            modal: Constants.MODALS.FREE_BETS,
          },
        });
      }
      yield put({
        type: GET_LOYALTY,
        payload: {
        },
      });
      yield put({
        type: GET_OPEN_BETS,
      });
    }
  } catch (error) {
    yield put({
      type: SHOW_ERROR_MODAL,
      payload: {
        activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
        message: error.message,
      },
    });
  }
}

/**
 * @memberof sagas/auth
 * @typedef "getBalanceAndBonus/response.data"
 * @type {object}
 * @property {number} amount
 * @property {number} bonusAmount
 * @property {string} currency
 */
/**
 * Update balance
 *
 * @memberof sagas/auth
 * @async
 * @yields {call} /user/balance
 * @yields {select} getUser
 * @yields {put} UPDATE_BALANCE
 * @yields {put} SHOW_ERROR_MODAL
 */
function* getBalanceAndBonus() {
  let response;
  yield put({
    type: SET_BALANCE_LOADING,
    payload: {
      isLoading: true,
    },
  });
  try {
    response = yield call(requestGet, Constants.API_URLS.GET_BALANCE, true);

    if (response.status === -1) {
      throw new Error(response.error.message);
    } else {
      const user = yield select(getUser);

      user.balance.amount = parseNum(response.data.amount);
      user.balance.bonusAmount = parseNum(response.data.bonusAmount);

      yield put({
        type: UPDATE_BALANCE,
        payload: {
          user,
        },
      });
      yield put({
        type: UPDATE_LAST_UPDATED_BALANCE_TIMESTAMP,
      });
    }
  } catch (error) {
    yield put({
      type: SHOW_ERROR_MODAL,
      payload: {
        activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
        message: error.message,
      },
    });
  } finally {
    yield put({
      type: SET_BALANCE_LOADING,
      payload: {
        isLoading: false,
      },
    });
  }
}

/**
 * @memberof sagas/auth
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {string} action.payload.username
 * @property {string} action.payload.password
 *
 * @yields {put} SET_LOADER
 * @yields {call} /session/login
 * @yields {put} LOGIN_ERROR
 * @yields {select} getPlacebetAfterLogin
 * @yields {select} getRoundId
 * @yields {select} getLiveId
 * @yields {select} getHaveLiveMatches
 * @yields {select} getTargetPageAfterLogin
 * @yields {put} SET_USER_DATA
 * @yields {put} GET_LOYALTY
 * @yields {put} PLACEBET
 * @yields {put} GET_PLACED_BETS
 * @yields {put} OPEN_MODAL
 * @yields {put} SHOW_ERROR_MODAL
 */
function* login(action) {
  let response;
  try {
    yield put({
      type: SET_LOADER,
      payload: {
        isLoading: true,
      },
    });
    response = yield call(requestPost, Constants.API_URLS.LOGIN, action.payload);
    if (response.status === -1) {
      yield put({
        type: LOGIN_ERROR,
        payload: {
          loginError: response.error.message,
        },
      });
    } else {
      const placebetAfterLogin = yield select(getPlacebetAfterLogin);
      const haveLiveMatches = yield select(getHaveLiveMatches);
      let targetPageAfterLogin = yield select(getTargetPageAfterLogin);
      if (haveLiveMatches && targetPageAfterLogin === Constants.PAGES.BETS) {
        targetPageAfterLogin = Constants.PAGES.LIVE;
      }
      if (!placebetAfterLogin && targetPageAfterLogin === Constants.PAGES.BETSLIP) {
        targetPageAfterLogin = Constants.PAGES.BETS;
      }
      const gameType = yield select(getGameType);
      if (gameType === null) {
        targetPageAfterLogin = Constants.PAGES.LEAGUE_SELECTION;
      }
      response.data.user.balance.amount = parseNum(response.data.user.balance.amount);
      response.data.user.balance.bonusAmount = parseNum(response.data.user.balance.bonusAmount);

      yield put({
        type: SET_USER_DATA,
        payload: {
          user: response.data.user,
          sessionId: response.data.sessionId,
          freeBets: sortFreeBets(response.data.freeBets),
          targetPageAfterLogin,
        },
      });
      yield put({
        type: GET_LOYALTY,
      });

      if (placebetAfterLogin) {
        yield put({
          type: PLACEBET,
          payload: placebetAfterLogin,
        });
      }
      yield put({
        type: GET_OPEN_BETS,
      });

      if (response.data.freeBets.length > 0) {
        yield put({
          type: OPEN_MODAL,
          payload: {
            modal: Constants.MODALS.FREE_BETS,
          },
        });
      }
    }
  } catch (error) {
    yield put({
      type: SHOW_ERROR_MODAL,
      payload: {
        activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
        message: error.message,
      },
    });
  }
}

/**
 * @memberof sagas/auth
 * @async
 * @yields {put} LOGOUT_SUCCESS
 * @yields {call} /session/logout
 * @yields {put} SHOW_ERROR_MODAL
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {string} [action.payload.gameType]
 */
function* logout(action) {
  const gameType = yield select(getGameType);
  try {
    yield put({
      type: LOGOUT_SUCCESS,
      payload: {
        isSessionBreak: action.payload.isSessionBreak || false,
      },
    });

    yield put({
      type: REMOVE_ALL_TICKETS_FROM_COUNT,
      payload: {},
    });

    yield put({
      type: CLEAR_ALL_PLACED_SELECTIONS,
      payload: {},
    });

    yield put({
      type: CLEAR_NUM_OF_BETS,
      payload: {
        numberOfBets: 0,
      },
    });

    yield put({
      type: SET_INITIALISE_BET,
      payload: {
        initialBetsLoaded: false,
      },
    });

    if (gameType === GAME_TYPE.TURBO) {
      yield put({
        type: CLEAR_SELECTIONS,
      });
    }

    yield call(requestPost, Constants.API_URLS.LOGOUT, {});
  } catch (error) {
    yield put({
      type: SHOW_ERROR_MODAL,
      payload: {
        activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
        message: error.message,
      },
    });
  }
}
/**
 * @memberof sagas/auth
 * @typedef "loyalty/response.data"
 * @type {object}
 * @property {number} bonusAmount
 * @property {Time} expirationDate
 * @property {number} bonusLevelId
 * @property {string} bonusName
 * @property {number} completionPercentage
 * @property {boolean} active
 * @property {string} maxBonusDuration

 */
/**
 * Get bonus for user
 *
 * @memberof sagas/auth
 * @async
 * @yields {call} delay 3000
 * @yields {call} /loyalty/userbonus
 * @yields {put} SET_LOYALTY
 * @yields {put} SHOW_ERROR_MODAL
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {boolean} [action.payload.isAfterPlacebet] Optional param to see if we come
 *  from placebet so we should wait 3 seconds for loyalty to get updated
 */
function* getLoyalty(action) {
  if (action.payload && action.payload.isAfterPlacebet === true) {
    yield call(delay, 3000);
  }

  let response;
  try {
    response = yield call(requestGet, Constants.API_URLS.LOYALTY, true);

    if (response.status === 1) {
      response.data.bonusAmount = parseNum(response.data.bonusAmount);
      yield put({
        type: SET_LOYALTY,
        payload: {
          bonus: response.data,
        },
      });
    }
  } catch (error) {
    yield put({
      type: SHOW_ERROR_MODAL,
      payload: {
        activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
        message: error.message,
      },
    });
  }
}

/**
 * Get src for iframe
 *
 * @memberof sagas/auth
 * @async
 * @param {object} action
 * @property {object} action
 * @property {object} action.payload
 * @property {string} action.payload.destination
 */
function* goToMyAccount(action) {
  let response;
  try {
    response = yield call(requestGet, `${Constants.API_URLS.GET_MY_ACC_DESTINATION}?destination=${action.payload.destination}`, true);

    if (response.status === 1) {
      yield put({
        type: GO_TO_MY_ACCOUNT_MENU_SUCCESS,
        payload: {
          selectedItem: response.data.url,
        },
      });
    }
  } catch (error) {
    yield put({
      type: SHOW_ERROR_MODAL,
      payload: {
        activeModal: error.modal || Constants.MODALS.GENERAL_ERROR,
        message: error.message,
      },
    });
  }
}
/**
 * @memberof sagas/auth
 * @async
 * @returns {void}
 */
export default function* authSaga() {
  yield takeEvery(CHECK_SESSION, checkSession);
  yield takeEvery(GET_BALANCE, getBalanceAndBonus);
  yield takeEvery(LOGIN, login);
  yield takeEvery(LOGOUT, logout);
  yield takeEvery(GET_LOYALTY, getLoyalty);
  yield takeEvery(GO_TO_MY_ACCOUNT_MENU, goToMyAccount);
}