Skip to content

Commit e6bc4dc

Browse files
Merge pull request #3478 from OneCommunityGlobal/strallia-hours-completed
Strallia - refactor Total Org Summary to use backend data
2 parents 7899b7f + 11a6f66 commit e6bc4dc

5 files changed

Lines changed: 52 additions & 101 deletions

File tree

src/components/TotalOrgSummary/HoursCompleted/HoursCompletedBarChart.jsx

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export default function HoursCompletedBarChart({ isLoading, data, darkMode }) {
1212
}
1313
return { height: '347px' };
1414
};
15+
1516
const [cardSize, setCardSize] = useState(initialCardSize);
17+
1618
const updateCardSize = () => {
1719
if (window.innerWidth <= 680) {
1820
setCardSize({ height: '300px' });
@@ -22,6 +24,7 @@ export default function HoursCompletedBarChart({ isLoading, data, darkMode }) {
2224
setCardSize({ height: '347px' });
2325
}
2426
};
27+
2528
useEffect(() => {
2629
window.addEventListener('resize', updateCardSize);
2730
updateCardSize();
@@ -30,20 +33,32 @@ export default function HoursCompletedBarChart({ isLoading, data, darkMode }) {
3033
};
3134
}, []);
3235

33-
const { taskHours, projectHours, lastTaskHours, lastProjectHours } = data;
34-
// const taskPercentage = parseFloat(taskHours) / (parseFloat(taskHours) + parseFloat(projectHours));
35-
// const taskChangePercentage = parseFloat(taskHours - lastTaskHours) / parseFloat(lastTaskHours);
36-
// const projectChangePercentage =
37-
// parseFloat(projectHours - lastProjectHours) / parseFloat(lastProjectHours);
38-
const taskPercentage = taskHours / (taskHours + projectHours);
39-
const taskChangePercentage = (taskHours - lastTaskHours) / lastTaskHours;
40-
const projectChangePercentage = (projectHours - lastProjectHours) / lastProjectHours;
36+
if (isLoading) {
37+
return (
38+
<div className="d-flex justify-content-center align-items-center">
39+
<div className="w-100vh">
40+
<Loading />
41+
</div>
42+
</div>
43+
);
44+
}
45+
46+
const { taskHours, projectHours } = data;
47+
const taskPercentage = taskHours.submittedToCommittedHoursPercentage;
48+
const projectPercentage = projectHours.submittedToCommittedHoursPercentage;
49+
const taskChangePercentage = taskHours.comparisonPercentage;
50+
const projectChangePercentage = projectHours.comparisonPercentage;
4151
const stats = [
42-
{ name: 'Task', amount: taskHours, percentage: taskPercentage, change: taskChangePercentage },
52+
{
53+
name: 'Task',
54+
amount: taskHours.count,
55+
percentage: taskPercentage,
56+
change: taskChangePercentage,
57+
},
4358
{
4459
name: 'Project',
45-
amount: projectHours,
46-
percentage: 1.0 - taskPercentage,
60+
amount: projectHours.count,
61+
percentage: projectPercentage,
4762
change: projectChangePercentage,
4863
},
4964
];
@@ -108,21 +123,13 @@ export default function HoursCompletedBarChart({ isLoading, data, darkMode }) {
108123

109124
return (
110125
<div style={{ height: cardSize.height }}>
111-
{isLoading ? (
112-
<div className="d-flex justify-content-center align-items-center">
113-
<div className="w-100vh">
114-
<Loading />
115-
</div>
116-
</div>
117-
) : (
118-
<TinyBarChart
119-
chartData={chartData}
120-
maxY={maxY}
121-
tickInterval={tickInterval}
122-
renderCustomizedLabel={renderCustomizedLabel}
123-
darkMode={darkMode}
124-
/>
125-
)}
126+
<TinyBarChart
127+
chartData={chartData}
128+
maxY={maxY}
129+
tickInterval={tickInterval}
130+
renderCustomizedLabel={renderCustomizedLabel}
131+
darkMode={darkMode}
132+
/>
126133
</div>
127134
);
128135
}

src/components/TotalOrgSummary/HoursWorkList/HoursWorkList.jsx

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,18 @@
1-
import { useState, useEffect } from 'react';
2-
3-
function HoursWorkList({ usersTimeEntries = [] }) {
4-
const [workedData, setWorkedData] = useState([]);
5-
6-
useEffect(() => {
7-
if (!Array.isArray(usersTimeEntries) || usersTimeEntries.length === 0) {
8-
return;
9-
}
10-
11-
const ranges = [
12-
{ name: '0 - 9.99', min: 0, max: 9.99, color: '#0088FE' },
13-
{ name: '10 - 19.99', min: 10, max: 19.99, color: '#00C49F' },
14-
{ name: '20 - 29.99', min: 20, max: 29.99, color: '#FFBB28' },
15-
{ name: '30 - 39.99', min: 30, max: 39.99, color: '#FF8042' },
16-
{ name: '40+', min: 40, max: Infinity, color: '#800080' },
17-
];
18-
19-
const arrData = ranges.map(range => {
20-
const value = usersTimeEntries.reduce((acc, curr) => {
21-
const hours = Number(curr.hours) || 0;
22-
const minutes = Number(curr.minutes) || 0;
23-
const total = hours + minutes / 60;
24-
if (total >= range.min && total < range.max) {
25-
return acc + total;
26-
}
27-
return acc;
28-
}, 0);
29-
30-
return {
31-
name: range.name,
32-
value,
33-
color: range.color,
34-
};
35-
});
36-
37-
setWorkedData(arrData);
38-
}, [usersTimeEntries]);
1+
function HoursWorkList() {
2+
const ranges = [
3+
{ name: '10-19.99', min: 10, max: 19.99, color: '#0088FE' },
4+
{ name: '20-29.99', min: 20, max: 29.99, color: '#00C49F' },
5+
{ name: '30-34.99', min: 30, max: 34.99, color: '#FFBB28' },
6+
{ name: '35-39.99', min: 35, max: 39.99, color: '#FF8042' },
7+
{ name: '40+', min: 40, max: Infinity, color: '#800080' },
8+
];
399

4010
return (
4111
<div>
4212
<h6 style={{ color: 'grey' }}>Hours Worked</h6>
4313
<div>
4414
<ul className="list-unstyled">
45-
{workedData.map(item => (
15+
{ranges.map(item => (
4616
<li key={item.name} className="text-secondary d-flex align-items-center">
4717
<div
4818
className="me-2"

src/components/TotalOrgSummary/NumbersVolunteerWorked/NumbersVolunteerWorked.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import '../TotalOrgSummary.css';
22

3-
export default function NumbersVolunteerWorked({ isLoading, usersTimeEntries, darkMode }) {
3+
export default function NumbersVolunteerWorked({ isLoading, data, darkMode }) {
44
return (
55
<div>
66
<p
77
className={`${
88
darkMode ? 'text-light' : 'text-dark'
99
} component-border component-pie-chart-label p-2`}
1010
>
11-
{isLoading ? '...' : usersTimeEntries.length} Volunteers worked 1+ hours over assigned time
11+
{isLoading ? '...' : data.count} Volunteers worked 1+ hours over assigned time
1212
</p>
1313
</div>
1414
);

src/components/TotalOrgSummary/TotalOrgSummary.jsx

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import hasPermission from 'utils/permissions';
99
import { getAllUserProfile } from 'actions/userManagement';
1010
import { getAllUsersTimeEntries } from 'actions/allUsersTimeEntries';
1111
import { getTimeEntryForOverDate } from 'actions/index';
12-
import { getTaskAndProjectStats, getTotalOrgSummary } from 'actions/totalOrgSummary';
12+
import { getTotalOrgSummary } from 'actions/totalOrgSummary';
1313

1414
import '../Header/DarkMode.css';
1515
import './TotalOrgSummary.css';
@@ -105,11 +105,10 @@ const aggregateTimeEntries = userTimeEntries => {
105105
};
106106

107107
function TotalOrgSummary(props) {
108-
const { darkMode, error, allUserProfiles, volunteerOverview } = props;
108+
const { darkMode, error, allUserProfiles } = props;
109109
const [usersId, setUsersId] = useState([]);
110110
const [usersTimeEntries, setUsersTimeEntries] = useState([]);
111111
const [usersOverTimeEntries, setUsersOverTimeEntries] = useState([]);
112-
const [taskProjectHours, setTaskProjectHours] = useState([]);
113112
const [isVolunteerFetchingError, setIsVolunteerFetchingError] = useState(false);
114113
const [volunteerStats, setVolunteerStats] = useState(null);
115114
const comparisonStartDate = '2025-01-16';
@@ -168,28 +167,6 @@ function TotalOrgSummary(props) {
168167
});
169168
}
170169
}, [allUsersTimeEntries, usersId, fromOverDate, toOverDate]);
171-
useEffect(() => {
172-
async function fetchData() {
173-
const {
174-
taskHours: { count: taskHours },
175-
projectHours: { count: projectHours },
176-
} = await props.getTaskAndProjectStats(fromDate, toDate);
177-
const {
178-
taskHours: { count: lastTaskHours },
179-
projectHours: { count: lastProjectHours },
180-
} = await props.getTaskAndProjectStats(fromOverDate, toOverDate);
181-
182-
if (taskHours && projectHours) {
183-
setTaskProjectHours({
184-
taskHours,
185-
projectHours,
186-
lastTaskHours,
187-
lastProjectHours,
188-
});
189-
}
190-
}
191-
fetchData();
192-
}, [fromDate, toDate, fromOverDate, toOverDate]);
193170

194171
useEffect(() => {
195172
const fetchVolunteerStats = async () => {
@@ -308,12 +285,13 @@ function TotalOrgSummary(props) {
308285
usersTimeEntries={usersTimeEntries}
309286
usersOverTimeEntries={usersOverTimeEntries}
310287
hoursData={volunteerStats?.volunteerHoursStats}
288+
totalHoursData={volunteerStats?.totalHoursWorked}
311289
/>
312290
<div className="d-flex flex-column align-items-center justify-content-center">
313-
<HoursWorkList darkMode={darkMode} usersTimeEntries={usersTimeEntries} />
291+
<HoursWorkList />
314292
<NumbersVolunteerWorked
315293
isLoading={isLoading}
316-
usersTimeEntries={usersTimeEntries}
294+
data={volunteerStats?.volunteersOverAssignedTime}
317295
darkMode={darkMode}
318296
/>
319297
</div>
@@ -342,7 +320,7 @@ function TotalOrgSummary(props) {
342320
<div className="mt-4">
343321
<HoursCompletedBarChart
344322
isLoading={isLoading}
345-
data={taskProjectHours}
323+
data={volunteerStats?.taskAndProjectStats}
346324
darkMode={darkMode}
347325
/>
348326
</div>
@@ -383,7 +361,7 @@ function TotalOrgSummary(props) {
383361
</div>
384362
<WorkDistributionBarChart
385363
isLoading={isLoading}
386-
workDistributionStats={volunteerOverview?.workDistributionStats}
364+
workDistributionStats={volunteerStats?.workDistributionStats}
387365
/>
388366
</div>
389367
</Col>
@@ -394,7 +372,7 @@ function TotalOrgSummary(props) {
394372
</div>
395373
<RoleDistributionPieChart
396374
isLoading={isLoading}
397-
roleDistributionStats={volunteerOverview?.roleDistributionStats}
375+
roleDistributionStats={volunteerStats?.roleDistributionStats}
398376
darkMode={darkMode}
399377
/>
400378
</div>
@@ -435,7 +413,6 @@ function TotalOrgSummary(props) {
435413
const mapStateToProps = state => ({
436414
error: state.error,
437415
loading: state.loading,
438-
volunteerOverview: state.totalOrgSummary.volunteerOverview,
439416
role: state.auth.user.role,
440417
auth: state.auth,
441418
darkMode: state.theme.darkMode,
@@ -445,7 +422,6 @@ const mapStateToProps = state => ({
445422
const mapDispatchToProps = dispatch => ({
446423
getTotalOrgSummary: (startDate, endDate, comparisonStartDate, comparisonEndDate) =>
447424
dispatch(getTotalOrgSummary(startDate, endDate, comparisonStartDate, comparisonEndDate)),
448-
getTaskAndProjectStats: () => dispatch(getTaskAndProjectStats(fromDate, toDate)),
449425
hasPermission: permission => dispatch(hasPermission(permission)),
450426
getAllUserProfile: () => dispatch(getAllUserProfile()),
451427
});

src/components/TotalOrgSummary/VolunteerRolesTeamDynamics/WorkDistributionBarChart.jsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ export default function WorkDistributionBarChart({ isLoading, workDistributionSt
4242
);
4343
}
4444

45-
// TODO: workDistributionStats should not require a filter. Backend api needs a fix to not return a null _id field.
4645
const data = workDistributionStats
47-
.filter(item => item._id)
4846
.sort((a, b) => a._id.localeCompare(b._id))
4947
.map(item => {
5048
return { ...item, totalHours: Number(item.totalHours.toFixed(2)) };

0 commit comments

Comments
 (0)