Skip to content

Commit 6550764

Browse files
Merge pull request #4949 from OneCommunityGlobal/development
Frontend Release to Main [4.80]
2 parents 23564b1 + f5c2a56 commit 6550764

49 files changed

Lines changed: 6936 additions & 4587 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import axios from 'axios';
2+
import configureMockStore from 'redux-mock-store';
3+
import thunk from 'redux-thunk';
4+
5+
import * as types from '../../constants/WeeklySummaryEmailBccConstants';
6+
import { updateWeeklySummaryEmailAssignment } from '../weeklySummaryEmailBCCAction';
7+
8+
vi.mock('axios');
9+
10+
const mockStore = configureMockStore([thunk]);
11+
12+
describe('updateWeeklySummaryEmailAssignment action creator', () => {
13+
it('dispatches updated assignment when API returns wrapped assignment payload', async () => {
14+
const store = mockStore({});
15+
const updatedAssignment = {
16+
_id: 'assignment-id',
17+
email: 'updated@example.com',
18+
assignedTo: { _id: 'user-id', firstName: 'Updated', lastName: 'User' },
19+
};
20+
21+
axios.put.mockResolvedValue({
22+
status: 200,
23+
data: { assignment: updatedAssignment },
24+
});
25+
26+
await store.dispatch(updateWeeklySummaryEmailAssignment('assignment-id', 'updated@example.com'));
27+
28+
expect(store.getActions()).toContainEqual({
29+
type: types.UPDATE_WEEKLY_SUMMARY_EMAIL_ASSIGNMENT,
30+
payload: updatedAssignment,
31+
});
32+
});
33+
34+
it('dispatches updated assignment when API returns assignment directly', async () => {
35+
const store = mockStore({});
36+
const updatedAssignment = {
37+
_id: 'assignment-id',
38+
email: 'updated@example.com',
39+
};
40+
41+
axios.put.mockResolvedValue({
42+
status: 200,
43+
data: updatedAssignment,
44+
});
45+
46+
await store.dispatch(updateWeeklySummaryEmailAssignment('assignment-id', 'updated@example.com'));
47+
48+
expect(store.getActions()).toContainEqual({
49+
type: types.UPDATE_WEEKLY_SUMMARY_EMAIL_ASSIGNMENT,
50+
payload: updatedAssignment,
51+
});
52+
});
53+
54+
it('dispatches error action when update fails', async () => {
55+
const store = mockStore({});
56+
const error = new Error('Network Error');
57+
58+
axios.put.mockRejectedValue(error);
59+
60+
await store.dispatch(updateWeeklySummaryEmailAssignment('assignment-id', 'updated@example.com'));
61+
62+
expect(store.getActions()).toContainEqual({
63+
type: types.WEEKLY_SUMMARY_EMAIL_ASSIGNMENT_ERROR,
64+
payload: error,
65+
});
66+
});
67+
});

src/actions/bmdashboard/equipmentActions.js

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const setErrors = payload => {
3232
};
3333

3434
export const fetchEquipmentById = equipmentId => {
35-
const url = ENDPOINTS.BM_EQUIPMENT_BY_ID(equipmentId);
35+
const url = `${ENDPOINTS.BM_EQUIPMENT_BY_ID(equipmentId)}`;
3636
return async dispatch => {
3737
axios
3838
.get(url)
@@ -83,12 +83,12 @@ export const purchaseEquipment = async body => {
8383
export const updateMultipleEquipmentLogs = (projectId, bulkArr) => dispatch => {
8484
axios
8585
.put(
86-
`${ENDPOINTS.BM_EQUIPMENT_LOGS}?project=${projectId}`,
86+
`${ENDPOINTS.BM_EQUIPMENT_LOGS}?project=${projectId}`,
8787
bulkArr
8888
)
8989
.then(res => {
90-
dispatch(setEquipments(res.data));
91-
toast.success('Equipment logs updated successfully!');
90+
dispatch(setEquipments(res.data));
91+
toast.success('Equipment logs updated successfully!');
9292
return res.data;
9393
})
9494
.catch(err => {
@@ -98,6 +98,71 @@ export const updateMultipleEquipmentLogs = (projectId, bulkArr) => dispatch => {
9898
});
9999
}
100100

101+
export const updateEquipment = (equipmentId, updateData) => async (dispatch, getState) => {
102+
const url = `${ENDPOINTS.BM_EQUIPMENT_STATUS_UPDATE(equipmentId)}`;
103+
104+
try {
105+
const state = getState();
106+
let currentUserId = state?.auth?.user?.userid;
107+
108+
if (!currentUserId) {
109+
currentUserId = state?.auth?.user?._id ||
110+
state?.auth?.user?.id ||
111+
state?.auth?._id ||
112+
state?.auth?.id;
113+
}
114+
115+
if (!currentUserId) {
116+
const storedUserId = localStorage.getItem('userId');
117+
if (storedUserId) {
118+
currentUserId = storedUserId;
119+
}
120+
}
121+
122+
if (!currentUserId) {
123+
const errorMsg = 'User not authenticated. Please log in.';
124+
toast.error(errorMsg);
125+
throw new Error(errorMsg);
126+
}
127+
128+
const statusUpdateData = {
129+
condition: updateData.condition,
130+
lastUsedBy: updateData.lastUsedBy,
131+
lastUsedFor: updateData.lastUsedFor,
132+
replacementRequired: updateData.replacementRequired,
133+
description: updateData.description || '',
134+
notes: updateData.notes || '',
135+
createdBy: currentUserId,
136+
};
137+
138+
const res = await axios.put(url, statusUpdateData);
139+
140+
dispatch(setEquipment(res.data));
141+
toast.success('Equipment status updated successfully!');
142+
dispatch(fetchEquipmentById(equipmentId));
143+
144+
return res.data;
145+
} catch (err) {
146+
147+
let errorMessage = 'Failed to update equipment status.';
148+
149+
if (err.response) {
150+
errorMessage = err.response.data?.error ||
151+
err.response.data?.message ||
152+
err.response.statusText ||
153+
errorMessage;
154+
dispatch(setErrors(err.response.data));
155+
} else if (err.request) {
156+
errorMessage = 'No response from server. Please check your connection.';
157+
} else {
158+
errorMessage = err.message;
159+
}
160+
161+
toast.error(errorMessage);
162+
throw err;
163+
}
164+
};
165+
101166
export const updateEquipmentById = (equipmentId, updatedFields) => async dispatch => {
102167
dispatch({ type: UPDATE_EQUIPMENT_START });
103168
try {

src/actions/weeklySummaryEmailBCCAction.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ const weeklySummaryEmailBccError = error => ({
2424
payload: error,
2525
});
2626

27+
const updateWeeklySummaryEmailBcc = assignment => ({
28+
type: types.UPDATE_WEEKLY_SUMMARY_EMAIL_ASSIGNMENT,
29+
payload: assignment,
30+
});
31+
2732
// fetch all assignments
2833
export const getAllWeeklySummaryEmailAssignments = () => {
2934
const url = ENDPOINTS.WEEKLY_SUMMARY_EMAIL_BCC();
@@ -79,11 +84,17 @@ export const updateWeeklySummaryEmailAssignment = (id, email) => async dispatch
7984
try {
8085
const response = await axios.put(ENDPOINTS.UPDATE_WEEKLY_SUMMARY_EMAIL_BCC(id), { email });
8186
if (response.status === 200) {
82-
dispatch(getAllWeeklySummaryEmailAssignments());
87+
const updated = response?.data?.assignment || response?.data || { _id: id, email };
88+
if (updated && updated._id) {
89+
dispatch(updateWeeklySummaryEmailBcc(updated));
90+
} else {
91+
dispatch(getAllWeeklySummaryEmailAssignments());
92+
}
8393
} else {
8494
dispatch(weeklySummaryEmailBccError(response.data));
8595
}
8696
} catch (error) {
8797
dispatch(weeklySummaryEmailBccError(error));
8898
}
8999
};
100+

src/components/BMDashboard/BMDashboard.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Container } from 'reactstrap';
44
import { fetchBMProjects } from '../../actions/bmdashboard/projectActions';
55
import ProjectsList from './Projects/ProjectsList';
66
import ProjectSelectForm from './Projects/ProjectSelectForm';
7+
import ProjectStatusDonutChart from './ProjectStatus/ProjectStatusDonutChart';
78
import BMError from './shared/BMError';
89
import styles from './BMDashboard.module.css';
910

@@ -200,6 +201,7 @@ export function BMDashboard() {
200201
) : (
201202
<>
202203
<ProjectSelectForm />
204+
<ProjectStatusDonutChart />
203205
<ProjectsList />
204206
</>
205207
)}

0 commit comments

Comments
 (0)