Skip to content

Commit 34140f7

Browse files
Merge pull request #3187 from OneCommunityGlobal/Shashank_fix_Profile_Page_issues
Shashank_Fix_Profile_Page
2 parents 3f87e9f + 62fe694 commit 34140f7

11 files changed

Lines changed: 630 additions & 333 deletions

File tree

src/actions/userManagement.js

Lines changed: 69 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ import {
1414
CHANGE_USER_PROFILE_PAGE,
1515
START_USER_INFO_UPDATE,
1616
FINISH_USER_INFO_UPDATE,
17-
ERROR_USER_INFO_UPDATE
17+
ERROR_USER_INFO_UPDATE,
1818
} from '../constants/userManagement';
1919
import { ENDPOINTS } from '../utils/URL';
2020
import { UserStatus } from '../utils/enums';
2121
import { getTimeEndDateEntriesByPeriod, getTimeStartDateEntriesByPeriod } from './timeEntries';
2222

23-
2423
/**
2524
* fetching all user profiles
2625
*/
@@ -50,32 +49,40 @@ export const updateUserStatus = (user, status, reactivationDate) => {
5049
userProfile.reactivationDate = reactivationDate;
5150
const patchData = { status, reactivationDate };
5251
return async dispatch => {
53-
if (status === UserStatus.InActive) {
54-
try {
55-
//Check for last week of work
56-
const lastEnddate = await dispatch(getTimeEndDateEntriesByPeriod(user._id, user.createdDate, userProfile.toDate));
57-
if (lastEnddate !== "N/A") { //if work exists, set EndDate to that week
52+
// Optimistic update
53+
dispatch(userProfileUpdateAction(userProfile));
54+
55+
try {
56+
if (status === UserStatus.InActive) {
57+
// Check for the last week of work
58+
const lastEnddate = await dispatch(
59+
getTimeEndDateEntriesByPeriod(user._id, user.createdDate, userProfile.toDate),
60+
);
61+
if (lastEnddate !== 'N/A') {
62+
//if work exists, set EndDate to that week
5863
patchData.endDate = moment(lastEnddate).format('YYYY-MM-DDTHH:mm:ss');
5964
userProfile.endDate = moment(lastEnddate).format('YYYY-MM-DDTHH:mm:ss');
60-
} else { //No work exists, set end date to start date
65+
} else {
66+
//No work exists, set end date to start date
6167
patchData.endDate = moment(user.createdDate);
6268
userProfile.endDate = moment(user.createdDate);
6369
}
64-
65-
const updateProfilePromise = axios.patch(ENDPOINTS.USER_PROFILE(user._id), patchData);
66-
updateProfilePromise.then(res => {
67-
dispatch(userProfileUpdateAction(userProfile));
68-
});
69-
} catch (error) {
70-
console.error("Error updating user status:", error);
70+
} else {
71+
// User is active
72+
patchData.endDate = undefined;
73+
userProfile.endDate = undefined;
7174
}
72-
} else {//user is active
73-
patchData.endDate = undefined;
74-
userProfile.endDate = undefined;
75-
const updateProfilePromise = axios.patch(ENDPOINTS.USER_PROFILE(user._id), patchData);
76-
updateProfilePromise.then(res => {
77-
dispatch(userProfileUpdateAction(userProfile));
78-
});
75+
76+
// Perform the API call
77+
await axios.patch(ENDPOINTS.USER_PROFILE(user._id), patchData);
78+
79+
// Ensure the dispatched action is final (optional if optimistic update is sufficient)
80+
dispatch(userProfileUpdateAction(userProfile));
81+
} catch (error) {
82+
console.error('Error updating user status:', error);
83+
84+
// Rollback to previous state on error
85+
dispatch(userProfileUpdateAction(user));
7986
}
8087
};
8188
};
@@ -105,18 +112,19 @@ export const updateRehireableStatus = (user, isRehireable) => {
105112
*/
106113
export const toggleVisibility = (user, isVisible) => {
107114
const userProfile = { ...user };
108-
userProfile.isVisible = isVisible
115+
userProfile.isVisible = isVisible;
109116
const requestData = { isVisible };
110117

111-
const toggleVisibilityPromise = axios.patch(ENDPOINTS.TOGGLE_VISIBILITY(user._id), requestData)
118+
const toggleVisibilityPromise = axios.patch(ENDPOINTS.TOGGLE_VISIBILITY(user._id), requestData);
112119
return async dispatch => {
113-
toggleVisibilityPromise.then(res => {
114-
dispatch(userProfileUpdateAction(userProfile));
115-
}).catch(err => {
116-
console.error("failed to toggle visibility: ", err);
117-
});
120+
toggleVisibilityPromise
121+
.then(res => {
122+
dispatch(userProfileUpdateAction(userProfile));
123+
})
124+
.catch(err => {
125+
console.error('failed to toggle visibility: ', err);
126+
});
118127
};
119-
120128
};
121129

122130
/**
@@ -220,24 +228,29 @@ export const updateUserFinalDayStatus = (user, status, finalDayDate) => {
220228
};
221229

222230
export const updateUserFinalDayStatusIsSet = (user, status, finalDayDate, isSet) => {
223-
const userProfile = { ...user };
224-
userProfile.endDate = finalDayDate;
225-
userProfile.isActive = status === 'Active';
226-
userProfile.isSet = isSet === 'FinalDay';
227-
const patchData = { status, endDate: finalDayDate, isSet };
228-
if (finalDayDate === undefined) {
229-
patchData.endDate = undefined;
230-
userProfile.endDate = undefined;
231-
} else {
232-
userProfile.endDate = moment(finalDayDate).add(1, 'days').format('YYYY-MM-DD');
233-
patchData.endDate = moment(finalDayDate).add(1, 'days').format('YYYY-MM-DD');
234-
}
235-
236-
const updateProfilePromise = axios.patch(ENDPOINTS.USER_PROFILE(user._id), patchData);
237231
return async dispatch => {
238-
updateProfilePromise.then(res => {
239-
dispatch(userProfileUpdateAction(userProfile));
240-
});
232+
try {
233+
// Prepare patch data
234+
const patchData = {
235+
status,
236+
endDate: finalDayDate ? moment(finalDayDate).add(1, 'days').format('YYYY-MM-DD') : undefined,
237+
isSet,
238+
};
239+
240+
// Make the API request
241+
const response = await axios.patch(ENDPOINTS.USER_PROFILE(user._id), patchData);
242+
243+
// Update the Redux store with the response data
244+
const updatedUserProfile = {
245+
...user,
246+
...response.data, // Use the updated data from the API
247+
};
248+
249+
dispatch(userProfileUpdateAction(updatedUserProfile));
250+
} catch (error) {
251+
console.error('Error updating user profile:', error);
252+
throw new Error('Failed to update user profile.');
253+
}
241254
};
242255
};
243256

@@ -265,7 +278,6 @@ export const getUserProfileBasicInfo = () => {
265278
};
266279
};
267280

268-
269281
/**
270282
* Set a flag that starts fetching user profile basic info
271283
*/
@@ -297,21 +309,21 @@ export const userProfilesBasicInfoFetchErrorAction = payload => {
297309
};
298310
};
299311

300-
export const enableEditUserInfo = (value) => (dispatch, getState) => {
312+
export const enableEditUserInfo = value => (dispatch, getState) => {
301313
dispatch({ type: ENABLE_USER_PROFILE_EDIT, payload: value });
302-
}
314+
};
303315

304-
export const disableEditUserInfo = (value) => (dispatch, getState) => {
316+
export const disableEditUserInfo = value => (dispatch, getState) => {
305317
dispatch({ type: DISABLE_USER_PROFILE_EDIT, payload: value });
306-
}
318+
};
307319

308-
export const changePagination = (value) => (dispatch, getState) => {
320+
export const changePagination = value => (dispatch, getState) => {
309321
dispatch({ type: CHANGE_USER_PROFILE_PAGE, payload: value });
310-
}
322+
};
311323

312-
export const updateUserInfomation = (value) => (dispatch, getState) => {
313-
dispatch({ type: START_USER_INFO_UPDATE, payload: value })
314-
}
324+
export const updateUserInfomation = value => (dispatch, getState) => {
325+
dispatch({ type: START_USER_INFO_UPDATE, payload: value });
326+
};
315327

316328
// export const updateUserInformation=(value)=>async(dispatch,getState)=>{
317329
// try {
@@ -324,4 +336,3 @@ export const updateUserInfomation = (value) => (dispatch, getState) => {
324336
// dispatch({type:ERROR_USER_INFO_UPDATE})
325337
// }
326338
// }
327-

src/components/UserManagement/PauseAndResumeButton.jsx

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
22
import { useDispatch } from 'react-redux';
33
import { Button } from 'reactstrap';
44
import { toast } from 'react-toastify';
5-
import { PAUSE, RESUME } from '../../languages/en/ui';
5+
import { PAUSE, RESUME, PROCESSING } from '../../languages/en/ui';
66
import { UserStatus } from '../../utils/enums';
77
import ActivationDatePopup from './ActivationDatePopup';
88
import { updateUserStatus } from '../../actions/userManagement';
@@ -18,6 +18,7 @@ function PauseAndResumeButton(props) {
1818
const { darkMode } = props;
1919
const [activationDateOpen, setActivationDateOpen] = useState(false);
2020
const [isActive, setIsActive] = useState(true);
21+
const [isLoading, setIsLoading] = useState(false); // Added loading state
2122

2223
const activationDatePopupClose = () => {
2324
setActivationDateOpen(false);
@@ -33,26 +34,42 @@ function PauseAndResumeButton(props) {
3334
* Call back on Pause confirmation button click to trigger the action to update user status
3435
*/
3536
const pauseUser = async reActivationDate => {
36-
await updateUserStatus(props.userProfile, UserStatus.InActive, reActivationDate)(dispatch);
37-
setIsActive(false);
38-
setActivationDateOpen(false);
39-
setTimeout(async () => {
40-
await props.loadUserProfile();
37+
setIsLoading(true); // Start loading indicator
38+
try {
39+
await updateUserStatus(props.userProfile, UserStatus.InActive, reActivationDate)(dispatch);
40+
setIsActive(false);
41+
setActivationDateOpen(false);
42+
43+
// Optimistically update the UI
4144
toast.success('Your Changes were saved successfully.');
42-
}, 1000);
45+
} catch (error) {
46+
toast.error('Failed to update the user status.');
47+
console.error(error);
48+
} finally {
49+
setIsLoading(false); // Stop loading indicator
50+
await props.loadUserProfile(); // Ensure state sync
51+
}
4352
};
4453

4554
/**
4655
* Call back on Pause or Resume button click to trigger the action to update user status
4756
*/
4857
const onPauseResumeClick = async (user, status) => {
4958
if (status === UserStatus.Active) {
50-
await updateUserStatus(user, status, Date.now())(dispatch);
51-
setIsActive(status);
52-
setTimeout(async () => {
53-
await props.loadUserProfile();
59+
setIsLoading(true); // Start loading indicator
60+
try {
61+
await updateUserStatus(user, status, Date.now())(dispatch);
62+
setIsActive(true);
63+
64+
// Optimistically update the UI
5465
toast.success('Your Changes were saved successfully.');
55-
}, 1000);
66+
} catch (error) {
67+
toast.error('Failed to update the user status.');
68+
console.error(error);
69+
} finally {
70+
setIsLoading(false); // Stop loading indicator
71+
await props.loadUserProfile(); // Ensure state sync
72+
}
5673
} else {
5774
setActivationDateOpen(true);
5875
}
@@ -67,6 +84,7 @@ function PauseAndResumeButton(props) {
6784
<Button
6885
outline={!darkMode}
6986
color={isActive ? 'warning' : 'success'}
87+
disabled={isLoading} // Disable the button while loading
7088
className={`btn ${darkMode ? '' : `btn-outline-${isActive ? 'warning' : 'success'}`} ${
7189
props.isBigBtn ? '' : 'btn-sm'
7290
} mr-1`}
@@ -76,7 +94,7 @@ function PauseAndResumeButton(props) {
7694
style={darkMode ? boxStyleDark : boxStyle}
7795
data-testid="pause-resume-button"
7896
>
79-
{isActive ? PAUSE : RESUME}
97+
{isLoading ? PROCESSING : isActive ? PAUSE : RESUME} {/* Show loading state */}
8098
</Button>
8199
</>
82100
);

src/components/UserManagement/SetUpFinalDayButton.jsx

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { toast } from 'react-toastify';
55
import { updateUserFinalDayStatusIsSet } from '../../actions/userManagement';
66
import { boxStyle, boxStyleDark } from '../../styles';
77
import SetUpFinalDayPopUp from './SetUpFinalDayPopUp';
8-
import { SET_FINAL_DAY, CANCEL } from '../../languages/en/ui';
8+
import { SET_FINAL_DAY, CANCEL , PROCESSING } from '../../languages/en/ui';
99
import { FinalDay } from '../../utils/enums';
1010
/**
1111
* @param {*} props
@@ -18,28 +18,36 @@ function SetUpFinalDayButton(props) {
1818
const [isSet, setIsSet] = useState(false);
1919
const [finalDayDateOpen, setFinalDayDateOpen] = useState(false);
2020
const dispatch = useDispatch();
21+
const [isLoading, setIsLoading] = useState(false); // Added loading state
2122

2223
useEffect(() => {
2324
if (props.userProfile?.endDate !== undefined) setIsSet(true);
2425
}, []);
2526

2627
const onFinalDayClick = async () => {
27-
const activeStatus = props.userProfile.isActive ? 'Active' : 'Inactive';
28-
if (isSet) {
29-
// updateUserFinalDayStatus(props.userProfile, activeStatus, undefined)(dispatch);
30-
setIsSet(!isSet);
31-
setTimeout(async () => {
32-
await props.loadUserProfile();
28+
setIsLoading(true); // Start loading indicator
29+
try {
30+
const activeStatus = props.userProfile.isActive ? 'Active' : 'Inactive';
31+
32+
if (isSet) {
3333
await updateUserFinalDayStatusIsSet(
3434
props.userProfile,
3535
activeStatus,
3636
undefined,
3737
FinalDay.NotSetFinalDay,
3838
)(dispatch);
39+
40+
setIsSet(false);
41+
await props.loadUserProfile(); // Ensure state sync
3942
toast.success("This user's final day has been deleted.");
40-
}, 1000);
41-
} else {
42-
setFinalDayDateOpen(true);
43+
} else {
44+
setFinalDayDateOpen(true);
45+
}
46+
} catch (error) {
47+
console.error('Error handling final day click:', error);
48+
toast.error("An error occurred while updating the user's final day.");
49+
} finally {
50+
setIsLoading(false); // Stop loading indicator
4351
}
4452
};
4553

@@ -48,19 +56,25 @@ function SetUpFinalDayButton(props) {
4856
};
4957

5058
const deactiveUser = async finalDayDate => {
51-
// await updateUserFinalDayStatus(props.userProfile, 'Active', finalDayDate)(dispatch);
52-
setIsSet(true);
53-
setFinalDayDateOpen(false);
54-
setTimeout(async () => {
55-
await props.loadUserProfile();
59+
setIsLoading(true); // Start loading indicator
60+
try {
5661
await updateUserFinalDayStatusIsSet(
5762
props.userProfile,
5863
'Active',
5964
finalDayDate,
6065
FinalDay.FinalDay,
6166
)(dispatch);
67+
68+
setIsSet(true);
69+
setFinalDayDateOpen(false);
70+
await props.loadUserProfile(); // Ensure state sync
6271
toast.success("This user's final day has been set.");
63-
}, 1000);
72+
} catch (error) {
73+
console.error('Error setting the final day:', error);
74+
toast.error("An error occurred while setting the user's final day.");
75+
} finally {
76+
setIsLoading(false); // Stop loading indicator
77+
}
6478
};
6579

6680
return (
@@ -81,7 +95,7 @@ function SetUpFinalDayButton(props) {
8195
}}
8296
style={darkMode ? boxStyleDark : boxStyle}
8397
>
84-
{isSet ? CANCEL : SET_FINAL_DAY}
98+
{isLoading ? PROCESSING : isSet ? CANCEL : SET_FINAL_DAY} {/* Show loading state */}
8599
</Button>
86100
</>
87101
);

0 commit comments

Comments
 (0)