UNPKG

topcoder-react-lib

Version:
533 lines (487 loc) 13.6 kB
/** * @module "reducers.members" * @desc Reducer for the Redux store segment that holds members data. * @todo Document state segment structure. */ import _ from 'lodash'; import { handleActions } from 'redux-actions'; import logger from '../utils/logger'; import actions from '../actions/members'; import { fireErrorMessage } from '../utils/errors'; /** * Drops information about a member. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onDrop(state, { payload }) { if (!state[payload]) return state; return _.omit(state, payload); } /** * Drops all loaded information on members. * @return {Object} New state. */ function onDropAll() { return {}; } /** * Inits the loading of member achievements. * @param {Object} state * @param {String} action.handle * @param {String} action.uuid * @return {Object} New state. */ function onGetAchievementsInit(state, action) { const { handle, uuid } = action.payload; let res = state[handle]; res = res ? _.clone(res) : {}; res.achievements = { loadingUuid: uuid }; return { ...state, [handle]: res }; } /** * Finalizes the loading of member achievements. * @param {Object} state * @param {Object} error * @param {Array} payload.data * @param {String} payload.handle * @param {String} payload.uuid * @return {Object} New state. */ function onGetAchievementsDone(state, { error, payload }) { if (error) { logger.error('Failed to load member achievements', payload); fireErrorMessage('Failed to load member achievements'); return state; } const { data, handle, uuid } = payload; if (uuid !== _.get(state[handle], 'achievements.loadingUuid')) return state; return { ...state, [handle]: { ...state[handle], achievements: { data, timestamp: Date.now() }, }, }; } /** * Initializes the loading of member financial information. * @param {Object} state * @param {String} action.payload.handle * @param {String} action.payload.uuid * @return {Object} New state. */ function onGetFinancesInit(state, action) { const { handle, uuid } = action.payload; const envelop = { ...(state[handle] || {}), finances: { loadingUuid: uuid, timestamp: 0, }, }; return { ...state, [handle]: envelop, }; } /** * Finalizes a pending loading of member financial information. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetFinancesDone(state, { error, payload }) { if (error) { logger.error('Failed to get user financial info', payload); fireErrorMessage('Failed to get user financial info', ''); return state; } const { data, handle, uuid } = payload; if (uuid !== _.get(state[handle], 'finances.loadingUuid')) return state; return { ...state, [handle]: { ...state[handle], finances: { data, loadingUuid: '', timestamp: Date.now(), }, }, }; } /** * Inits the loading of member stats. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetStatsInit(state, action) { const { handle, uuid } = action.payload; let res = state[handle]; res = res ? _.clone(res) : {}; res.stats = { loadingUuid: uuid }; return { ...state, [handle]: res, }; } /** * Finalizes the loading of member stats. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetStatsDone(state, { error, payload }) { if (error) { logger.error('Failed to get member stats', payload); fireErrorMessage('Failed to get member stats', ''); return state; } const { data, handle, uuid } = payload; if (uuid !== _.get(state[handle], 'stats.loadingUuid')) return state; return { ...state, [handle]: { ...state[handle], stats: { data, timestamp: Date.now() }, }, }; } /** * Inits the loading of member stats history. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetStatsHistoryInit(state, action) { const { handle, uuid } = action.payload; let res = state[handle]; res = res ? _.clone(res) : {}; res.statsHistory = { loadingUuid: uuid }; return { ...state, [handle]: res, }; } /** * Finalizes the loading of member stats history. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetStatsHistoryDone(state, { error, payload }) { if (error) { logger.error('Failed to get member statsHistory', payload); fireErrorMessage('Failed to get member statsHistory', ''); return state; } const { data, handle, uuid } = payload; if (uuid !== _.get(state[handle], 'statsHistory.loadingUuid')) return state; return { ...state, [handle]: { ...state[handle], statsHistory: { data, timestamp: Date.now() }, }, }; } /** * Inits the loading of member stats distribution. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetStatsDistributionInit(state, action) { const { handle, uuid } = action.payload; let res = state[handle]; res = res ? _.clone(res) : {}; res.statsDistribution = { loadingUuid: uuid }; return { ...state, [handle]: res, }; } /** * Finalizes the loading of member stats distribution. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetStatsDistributionDone(state, { error, payload }) { if (error) { logger.error('Failed to get member statsDistribution', payload); fireErrorMessage('Failed to get member statsDistribution', ''); return state; } const { data, handle, uuid } = payload; if (uuid !== _.get(state[handle], 'statsDistribution.loadingUuid')) return state; return { ...state, [handle]: { ...state[handle], statsDistribution: { data, timestamp: Date.now() }, }, }; } /** * Inits the loading of member active challenges. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetActiveChallengesInit(state, action) { const { handle } = action.payload; return { ...state, [handle]: { ...state[handle], activeChallengesCount: null }, }; } /** * Finalizes the loading of member active challenges. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetActiveChallengesDone(state, { error, payload }) { if (error) { logger.error('Failed to get member active challenges', payload); fireErrorMessage('Failed to get member active challenges', ''); return state; } const { handle, challenges } = payload; return { ...state, [handle]: { ...state[handle], activeChallengesCount: challenges.length, }, }; } /** * Inits the loading of member subtrack challenges. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetSubtrackChallengesInit(state, { payload }) { const { handle, uuid, pageNum } = payload; return { ...state, [handle]: { ...state[handle], loadingSubTrackChallengesUUID: uuid, subtrackChallengesHasMore: false, ...(pageNum === 1 ? { subtrackChallenges: [] } : {}), }, }; } /** * Finalizes the loading of member subtrack challenges. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetSubtrackChallengesDone(state, { error, payload }) { const { uuid, challenges, refresh, handle, error: payloadError, } = payload; if (error || payloadError) { logger.error('Failed to get member subtrack challenges', payload); fireErrorMessage('Failed to get member subtrack challenges', ''); return { ...state, [handle]: { ...state[handle], subtrackChallengesHasMore: false, loadingSubTrackChallengesUUID: '', }, }; } if (uuid !== state[handle].loadingSubTrackChallengesUUID) return state; return { ...state, [handle]: { ...state[handle], subtrackChallenges: (state[handle].subtrackChallenges && !refresh) ? [...state[handle].subtrackChallenges, ...challenges] : challenges, // if current query returns 0 item, mark it completed subtrackChallengesHasMore: challenges && challenges.length > 0, loadingSubTrackChallengesUUID: '', }, }; } /** * Inits the loading of member SRMs. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetUserSRMInit(state, { payload }) { const { handle, uuid } = payload; return { ...state, [handle]: { ...state[handle], loadingSRMUUID: uuid }, }; } /** * Finalizes the loading of member SRMs. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetUserSRMDone(state, { error, payload }) { if (error) { logger.error('Failed to get member SRMs', payload); fireErrorMessage('Failed to get member SRMs', ''); return state; } const { uuid, srms, refresh, handle, } = payload; if (uuid !== state[handle].loadingSRMUUID) return state; return { ...state, [handle]: { ...state[handle], userSRMs: (state[handle].userSRMs && !refresh) ? [...state[handle].userSRMs, ...srms] : srms, userSRMHasMore: srms && srms.length > 0, // if current query returns 0 item, mark it completed loadingSRMUUID: '', }, }; } /** * Inits the loading of member marathons. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetUserMarathonInit(state, { payload }) { const { handle, uuid } = payload; return { ...state, [handle]: { ...state[handle], loadingMarathonUUID: uuid }, }; } /** * Finalizes the loading of member marathons. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetUserMarathonDone(state, { error, payload }) { if (error) { logger.error('Failed to get member marathons', payload); fireErrorMessage('Failed to get member marathons', ''); return state; } const { uuid, marathons, refresh, handle, } = payload; if (uuid !== state[handle].loadingMarathonUUID) return state; return { ...state, [handle]: { ...state[handle], userMarathons: (state[handle].userMarathons && !refresh) ? [...state[handle].userMarathons, ...marathons.challenges] : marathons.challenges, // if current query returns 0 item, mark it completed userMarathonHasMore: marathons && marathons.challenges && marathons.challenges.length > 0, loadingMarathonUUID: '', }, }; } /** * Inits the loading of user challenge resources. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetUserResourcesInit(state, { payload }) { const { uuid } = payload; return { ...state, userResources: { resources: [], loadingUserResources: uuid }, }; } /** * Finalizes the loading of user challenge resources. * @param {Object} state * @param {Object} action * @return {Object} New state. */ function onGetUserResourcesDone(state, { error, payload }) { if (error) { logger.error('Failed to get user resources', payload); fireErrorMessage('Failed to get user resources', ''); return state; } const { uuid, resources } = payload; if (uuid !== state.userResources.loadingUserResources) return state; return { ...state, userResources: { resources, loadingUserResources: '' }, }; } /** * Creates a new Members reducer with the specified initial state. * @param {Object} initialState Optional. Initial state. * @return {Function} Members reducer. */ function create(initialState = {}) { const a = actions.members; return handleActions({ [a.drop]: onDrop, [a.dropAll]: onDropAll, [a.getAchievementsInit]: onGetAchievementsInit, [a.getAchievementsDone]: onGetAchievementsDone, [a.getAchievementsV3Done]: onGetAchievementsDone, [a.getFinancesInit]: onGetFinancesInit, [a.getFinancesDone]: onGetFinancesDone, [a.getStatsInit]: onGetStatsInit, [a.getStatsDone]: onGetStatsDone, [a.getStatsHistoryInit]: onGetStatsHistoryInit, [a.getStatsHistoryDone]: onGetStatsHistoryDone, [a.getStatsDistributionInit]: onGetStatsDistributionInit, [a.getStatsDistributionDone]: onGetStatsDistributionDone, [a.getActiveChallengesInit]: onGetActiveChallengesInit, [a.getActiveChallengesDone]: onGetActiveChallengesDone, [a.getSubtrackChallengesInit]: onGetSubtrackChallengesInit, [a.getSubtrackChallengesDone]: onGetSubtrackChallengesDone, [a.getUserSrmInit]: onGetUserSRMInit, [a.getUserSrmDone]: onGetUserSRMDone, [a.getUserMarathonInit]: onGetUserMarathonInit, [a.getUserMarathonDone]: onGetUserMarathonDone, [a.getUserResourcesInit]: onGetUserResourcesInit, [a.getUserResourcesDone]: onGetUserResourcesDone, }, initialState); } /** * Factory which creates a new reducer with its initial state tailored to the * given options object, if specified (for server-side rendering). If options * object is not specified, it creates just the default reducer. Accepted options are: * @return {Promise} * @resolves {Function(state, action): state} New reducer. */ export function factory() { return Promise.resolve(create()); } /** * @static * @member default * @desc Reducer with default initial state. */ export default create();