RC-10: add new values, reducers and selectors for history and favorites to user slice

This commit is contained in:
2023-08-27 11:57:28 +01:00
parent a5b30367cb
commit 317617c3ce
2 changed files with 139 additions and 24 deletions

View File

@@ -6,6 +6,63 @@ import { showMessage } from 'app/store/fuse/messageSlice';
import { logoutUser, setUser } from 'app/store/userSlice'; import { logoutUser, setUser } from 'app/store/userSlice';
import { authService, firebase } from '../services'; import { authService, firebase } from '../services';
const cards = [
{
id: '123',
image:
'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80',
title: '6 Via delle Crosarolle, Crosarolle, Veneto, Crosarolle, Veneto',
category: 'buy',
status: 'new',
favorite: false,
update: '12.12.2022',
statistics: [
{ subject: 'Monthly Cash Flow', value: '$ 78,000', mode: 'extra_positive' },
{ subject: 'Cash on Cash Return', value: '78%', mode: 'positive' },
{ subject: 'Selling Prise', value: '$500,000', mode: '' },
{ subject: 'Cash Out of Pocket', value: '$125,000', mode: '' },
{ subject: 'Annual Revenue', value: '$5,000', mode: '' },
{ subject: 'Annual Net Profit', value: '+$50,000', mode: 'extra_positive' },
],
},
{
id: '456',
image:
'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80',
title: '6 Via delle Crosarolle, Crosarolle, Veneto',
category: 'buy',
status: 'new',
favorite: false,
update: '12.12.2022',
statistics: [
{ subject: 'Monthly Cash Flow', value: '$ 78,000', mode: 'extra_negative' },
{ subject: 'Cash on Cash Return', value: '78%', mode: 'negative' },
{ subject: 'Selling Prise', value: '$500,000', mode: '' },
{ subject: 'Cash Out of Pocket', value: '$125,000', mode: '' },
{ subject: 'Annual Revenue', value: '$5,000', mode: '' },
{ subject: 'Annual Net Profit', value: '+$50,000', mode: 'extra_negative' },
],
},
{
id: '789',
image:
'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80',
title: '6 Via delle Crosarolle, Crosarolle, Veneto',
category: 'rent',
status: 'new',
favorite: false,
update: '12.12.2022',
statistics: [
{ subject: 'Monthly Cash Flow', value: '$ 78,000', mode: 'positive' },
{ subject: 'Cash on Cash Return', value: '78%', mode: 'positive' },
{ subject: 'Selling Prise', value: '$500,000', mode: '' },
{ subject: 'Cash Out of Pocket', value: '$125,000', mode: '' },
{ subject: 'Annual Revenue', value: '$5,000', mode: '' },
{ subject: 'Annual Net Profit', value: '+$50,000', mode: 'extra_positive' },
],
},
];
const AuthContext = React.createContext(); const AuthContext = React.createContext();
function AuthProvider({ children }) { function AuthProvider({ children }) {
@@ -25,14 +82,19 @@ function AuthProvider({ children }) {
authService.onAuthStateChanged((authUser) => { authService.onAuthStateChanged((authUser) => {
dispatch(showMessage({ message: 'Signing...' })); dispatch(showMessage({ message: 'Signing...' }));
if (authUser) { if (authUser) {
const storageUser = JSON.parse(localStorage.user ?? '{}');
authService authService
.getUserData(authUser.uid) .getUserData(authUser.uid)
.then((user) => { .then((user) => {
if (user) { if (user) {
success(user, 'Signed in'); success({ ...user, ...storageUser }, 'Signed in');
} else { } else {
// First login
const { displayName, photoURL, email } = authUser; const { displayName, photoURL, email } = authUser;
success({ role: 'user', data: { displayName, photoURL, email } }, 'Signed in'); success(
{ role: 'user', data: { displayName, photoURL, email }, ...storageUser },
'Signed in'
);
} }
}) })
.catch((error) => { .catch((error) => {

View File

@@ -1,35 +1,86 @@
/* eslint import/no-extraneous-dependencies: off */ import browserHistory from '@history';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import history from '@history';
import _ from '@lodash'; import _ from '@lodash';
import { setInitialSettings } from 'app/store/fuse/settingsSlice'; import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { showMessage } from 'app/store/fuse/messageSlice';
import settingsConfig from 'app/configs/settingsConfig'; import settingsConfig from 'app/configs/settingsConfig';
import { showMessage } from 'app/store/fuse/messageSlice';
import { setInitialSettings } from 'app/store/fuse/settingsSlice';
import { authService } from '../services'; import { authService } from '../services';
export const setUser = createAsyncThunk('user/setUser', async (user, { dispatch, getState }) => { export const setUser = createAsyncThunk('user/setUser', async (user) => {
/* // You can redirect the logged-in user to a specific route depending on his role
You can redirect the logged-in user to a specific route depending on his role
*/
if (user.loginRedirectUrl) { if (user.loginRedirectUrl) {
settingsConfig.loginRedirectUrl = user.loginRedirectUrl; // for example 'apps/academy' settingsConfig.loginRedirectUrl = user.loginRedirectUrl; // for example 'apps/academy'
} }
return user; return _.merge({}, initialState, user);
}); });
export const updateUserSettings = createAsyncThunk( export const updateUserSettings = createAsyncThunk(
'user/updateSettings', 'user/updateSettings',
async (settings, { dispatch, getState }) => { async (settings, { dispatch, getState }) => {
const { user } = getState(); const { user } = getState();
const newUser = _.merge({}, user, { data: { ...settings } }); const newUser = _.omit(_.merge({}, user, { data: { ...settings } }), 'history');
dispatch(updateUserData(newUser)); dispatch(updateUserData(newUser))
.then(() => {
dispatch(showMessage({ message: 'User data saved' }));
})
.catch((error) => {
dispatch(showMessage({ message: error.message }));
});
return newUser; return newUser;
} }
); );
export const updateUserFavorites = createAsyncThunk(
'user/updateFavorites',
async (item, { dispatch, getState }) => {
const { user } = getState();
const hasItemInFavorites = user.favorites.find(
(favoriteItem) => favoriteItem.id === item.id && item.favorite
);
const hasItemInHistory = user.history.find((history) => history.id === item.id);
const favorites = hasItemInFavorites
? user.favorites.filter((favorite) => favorite.id !== item.id)
: [...user.favorites, { ...item, favorite: true }];
if (hasItemInHistory) {
const history = user.history.map((historyItem) => {
if (historyItem.id === item.id) {
return { ...historyItem, favorite: !hasItemInFavorites };
}
return historyItem;
});
dispatch(updateUserHistory(history));
}
const newUserData = _.omit({ ...user, favorites }, 'history');
dispatch(updateUserData(newUserData))
.then(() => {
if (hasItemInFavorites) {
dispatch(showMessage({ message: 'The property is removed from favorites' }));
} else {
dispatch(showMessage({ message: 'The property is saved to favorites' }));
}
})
.catch((error) => {
dispatch(showMessage({ message: error.message }));
});
return favorites;
}
);
export const updateUserHistory = (history) => (dispatch) => {
localStorage.setItem('user', JSON.stringify({ history }));
dispatch(userHistoryUpdated(history));
};
export const logoutUser = () => async (dispatch, getState) => { export const logoutUser = () => async (dispatch, getState) => {
const { user } = getState(); const { user } = getState();
@@ -38,7 +89,7 @@ export const logoutUser = () => async (dispatch, getState) => {
return null; return null;
} }
history.push({ browserHistory.push({
pathname: '/', pathname: '/',
}); });
@@ -53,14 +104,8 @@ export const updateUserData = (user) => async (dispatch, getState) => {
return; return;
} }
authService // eslint-disable-next-line consistent-return
.updateUserData(user) return authService.updateUserData(user);
.then(() => {
dispatch(showMessage({ message: 'User data saved' }));
})
.catch((error) => {
dispatch(showMessage({ message: error.message }));
});
}; };
const initialState = { const initialState = {
@@ -69,6 +114,8 @@ const initialState = {
displayName: 'John Doe', displayName: 'John Doe',
email: 'johndoe@withinpixels.com', email: 'johndoe@withinpixels.com',
}, },
history: [],
favorites: [],
}; };
const userSlice = createSlice({ const userSlice = createSlice({
@@ -76,15 +123,21 @@ const userSlice = createSlice({
initialState, initialState,
reducers: { reducers: {
userLoggedOut: (state, action) => initialState, userLoggedOut: (state, action) => initialState,
userHistoryUpdated: (state, action) => ({ ...state, history: action.payload }),
}, },
extraReducers: { extraReducers: {
[updateUserSettings.fulfilled]: (state, action) => action.payload, [updateUserSettings.fulfilled]: (state, action) => action.payload,
[updateUserFavorites.fulfilled]: (state, action) => ({ ...state, favorites: action.payload }),
[setUser.fulfilled]: (state, action) => action.payload, [setUser.fulfilled]: (state, action) => action.payload,
}, },
}); });
export const { userLoggedOut } = userSlice.actions; export const { userLoggedOut, userHistoryUpdated } = userSlice.actions;
export const selectUser = ({ user }) => user; export const selectUser = ({ user }) => user;
export const selectUserHistory = ({ user }) => user.history;
export const selectUserFavorites = ({ user }) => user.favorites;
export default userSlice.reducer; export default userSlice.reducer;