Fix(challenges): completed marked at render
Mark challenge completed using derived data in a selector instead of manipulating the data on user load
This commit is contained in:
@ -95,10 +95,6 @@ export const updateUserLang = createAction(
|
|||||||
(username, lang) => ({ username, lang })
|
(username, lang) => ({ username, lang })
|
||||||
);
|
);
|
||||||
export const updateAppLang = createAction(types.updateAppLang);
|
export const updateAppLang = createAction(types.updateAppLang);
|
||||||
// updateCompletedChallenges(username: String) => Action
|
|
||||||
export const updateCompletedChallenges = createAction(
|
|
||||||
types.updateCompletedChallenges
|
|
||||||
);
|
|
||||||
|
|
||||||
// used when server needs client to redirect
|
// used when server needs client to redirect
|
||||||
export const delayedRedirect = createAction(types.delayedRedirect);
|
export const delayedRedirect = createAction(types.delayedRedirect);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import types from './types';
|
import types from './types';
|
||||||
|
|
||||||
const { updateUserPoints, updateCompletedChallenges } = types;
|
const { updateUserPoints } = types;
|
||||||
const initialState = {
|
const initialState = {
|
||||||
superBlock: {},
|
superBlock: {},
|
||||||
block: {},
|
block: {},
|
||||||
@ -15,22 +15,6 @@ export default function entities(state = initialState, action) {
|
|||||||
type,
|
type,
|
||||||
payload: { email, username, points, flag, languageTag } = {}
|
payload: { email, username, points, flag, languageTag } = {}
|
||||||
} = action;
|
} = action;
|
||||||
if (type === updateCompletedChallenges) {
|
|
||||||
const username = action.payload;
|
|
||||||
const completedChallengeMap = state.user[username].challengeMap || {};
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
challenge: Object.keys(state.challenge)
|
|
||||||
.reduce((map, key) => {
|
|
||||||
const challenge = state.challenge[key];
|
|
||||||
map[key] = {
|
|
||||||
...challenge,
|
|
||||||
isCompleted: !!completedChallengeMap[challenge.id]
|
|
||||||
};
|
|
||||||
return map;
|
|
||||||
}, {})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (action.meta && action.meta.entities) {
|
if (action.meta && action.meta.entities) {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -3,7 +3,6 @@ import types from './types';
|
|||||||
import {
|
import {
|
||||||
addUser,
|
addUser,
|
||||||
updateThisUser,
|
updateThisUser,
|
||||||
updateCompletedChallenges,
|
|
||||||
createErrorObservable,
|
createErrorObservable,
|
||||||
showSignIn,
|
showSignIn,
|
||||||
updateTheme,
|
updateTheme,
|
||||||
@ -24,7 +23,6 @@ export default function getUserSaga(action$, getState, { services }) {
|
|||||||
const isNightMode = user.theme === 'night';
|
const isNightMode = user.theme === 'night';
|
||||||
return Observable.of(
|
return Observable.of(
|
||||||
addUser(entities),
|
addUser(entities),
|
||||||
updateCompletedChallenges(result),
|
|
||||||
updateThisUser(result),
|
updateThisUser(result),
|
||||||
isNightMode ? updateTheme(user.theme) : null,
|
isNightMode ? updateTheme(user.theme) : null,
|
||||||
isNightMode ? addThemeToBody(user.theme) : null
|
isNightMode ? addThemeToBody(user.theme) : null
|
||||||
|
@ -12,7 +12,6 @@ export default createTypes([
|
|||||||
'updateUserFlag',
|
'updateUserFlag',
|
||||||
'updateUserEmail',
|
'updateUserEmail',
|
||||||
'updateUserLang',
|
'updateUserLang',
|
||||||
'updateCompletedChallenges',
|
|
||||||
'showSignIn',
|
'showSignIn',
|
||||||
'loadCurrentChallenge',
|
'loadCurrentChallenge',
|
||||||
'updateMyCurrentChallenge',
|
'updateMyCurrentChallenge',
|
||||||
|
@ -8,24 +8,35 @@ import debug from 'debug';
|
|||||||
|
|
||||||
import { updateCurrentChallenge } from '../../redux/actions';
|
import { updateCurrentChallenge } from '../../redux/actions';
|
||||||
import { makePanelHiddenSelector } from '../../redux/selectors';
|
import { makePanelHiddenSelector } from '../../redux/selectors';
|
||||||
|
import { userSelector } from '../../../../redux/selectors';
|
||||||
import { closeMapDrawer } from '../../../../redux/actions';
|
import { closeMapDrawer } from '../../../../redux/actions';
|
||||||
|
|
||||||
const bindableActions = { closeMapDrawer, updateCurrentChallenge };
|
const bindableActions = { closeMapDrawer, updateCurrentChallenge };
|
||||||
const makeMapStateToProps = () => createSelector(
|
const makeMapStateToProps = () => createSelector(
|
||||||
|
userSelector,
|
||||||
(_, props) => props.dashedName,
|
(_, props) => props.dashedName,
|
||||||
state => state.entities.challenge,
|
state => state.entities.challenge,
|
||||||
makePanelHiddenSelector(),
|
makePanelHiddenSelector(),
|
||||||
(dashedName, challengeMap, isHidden) => {
|
(
|
||||||
|
{ user: { challengeMap: userChallengeMap } },
|
||||||
|
dashedName,
|
||||||
|
challengeMap,
|
||||||
|
isHidden
|
||||||
|
) => {
|
||||||
const challenge = challengeMap[dashedName] || {};
|
const challenge = challengeMap[dashedName] || {};
|
||||||
|
let isCompleted = false;
|
||||||
|
if (userChallengeMap) {
|
||||||
|
isCompleted = !!userChallengeMap[challenge.id];
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
dashedName,
|
dashedName,
|
||||||
challenge,
|
challenge,
|
||||||
isHidden,
|
isHidden,
|
||||||
|
isCompleted,
|
||||||
title: challenge.title,
|
title: challenge.title,
|
||||||
block: challenge.block,
|
block: challenge.block,
|
||||||
isLocked: challenge.isLocked,
|
isLocked: challenge.isLocked,
|
||||||
isRequired: challenge.isRequired,
|
isRequired: challenge.isRequired,
|
||||||
isCompleted: challenge.isCompleted,
|
|
||||||
isComingSoon: challenge.isComingSoon,
|
isComingSoon: challenge.isComingSoon,
|
||||||
isDev: debug.enabled('fcc:*')
|
isDev: debug.enabled('fcc:*')
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user