Skip to content

Commit 61a3485

Browse files
authored
Merge pull request #2241 from Northeastern-Electric-Racing/#2238-attendee-tracking
#2238 Attendee Tracking
2 parents 45dc328 + a35762a commit 61a3485

1 file changed

Lines changed: 51 additions & 48 deletions

File tree

src/frontend/src/pages/AdminToolsPage/AdminToolsAttendeeDesignReviewInfo.tsx

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,69 @@
11
import React, { useState } from 'react';
2-
import {
3-
TextField,
4-
FormControl,
5-
FormLabel,
6-
Select,
7-
MenuItem,
8-
SelectChangeEvent,
9-
TableCell,
10-
TableRow,
11-
Grid,
12-
Typography
13-
} from '@mui/material';
2+
import { TextField, FormControl, FormLabel, TableCell, TableRow, Grid, Typography } from '@mui/material';
143
import AdminToolTable from './AdminToolTable';
4+
import { useAllTeams } from '../../hooks/teams.hooks';
5+
import LoadingIndicator from '../../components/LoadingIndicator';
6+
import ErrorPage from '../ErrorPage';
7+
import { fullNamePipe } from '../../utils/pipes';
8+
import { useAllUsers } from '../../hooks/users.hooks';
9+
import { useAllDesignReviews } from '../../hooks/design-reviews.hooks';
10+
import { DesignReviewStatus } from 'shared';
1511

1612
const AdminToolsAttendeeDesignReviewInfo: React.FC = () => {
17-
const [selectedTeam, setSelectedTeam] = useState('');
1813
const [searchQuery, setSearchQuery] = useState('');
1914

20-
// TODO: to be deleted later, this is just stub data for filter options
21-
const teams = ['All', 'Team A', 'Team B', 'Team C'];
15+
const { data: allTeams, isLoading: teamsIsLoading, isError: teamsIsError, error: teamsError } = useAllTeams();
16+
const { data: allUsers, isLoading: usersIsLoading, isError: usersIsError, error: usersError } = useAllUsers();
17+
const {
18+
data: allDesignReviews,
19+
isLoading: designReviewsIsLoading,
20+
isError: designReviewsIsError,
21+
error: designReviewsError
22+
} = useAllDesignReviews();
2223

23-
// TODO: Stub data for team members, replace with dynamic data here
24-
const teamMembers = [
25-
{ name: 'Batman', reviewsAttended: 2, missedReviews: 4 },
26-
{ name: 'Superman', reviewsAttended: 4, missedReviews: 1 }
27-
];
24+
if (!allTeams || teamsIsLoading || !allUsers || usersIsLoading || !allDesignReviews || designReviewsIsLoading)
25+
return <LoadingIndicator />;
26+
if (teamsIsError) return <ErrorPage message={teamsError.message} />;
27+
if (usersIsError) return <ErrorPage message={usersError.message} />;
28+
if (designReviewsIsError) return <ErrorPage message={designReviewsError.message} />;
2829

29-
// TODO: Filtering team members based on search query here
30-
const filteredMembers = teamMembers.filter((member) => member.name.toLowerCase().includes(searchQuery.toLowerCase()));
31-
32-
// TODO: Filtering for teams backend logic comes here
33-
const handleTeamChange = (event: SelectChangeEvent) => {
34-
setSelectedTeam(event.target.value as string);
35-
};
30+
const filteredMembers = allUsers.filter((member) =>
31+
fullNamePipe(member).toLowerCase().includes(searchQuery.toLowerCase())
32+
);
3633

3734
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
3835
setSearchQuery(event.target.value);
3936
};
4037

38+
const attendanceDict: Map<number, number> = new Map();
39+
const missedDict: Map<number, number> = new Map();
40+
41+
allDesignReviews.forEach((review) => {
42+
if (review.status === DesignReviewStatus.DONE) {
43+
review.attendees.forEach((member) => {
44+
if (attendanceDict.has(member.userId)) {
45+
attendanceDict.set(member.userId, attendanceDict.get(member.userId)! + 1);
46+
} else {
47+
attendanceDict.set(member.userId, 1);
48+
}
49+
});
50+
review.requiredMembers.forEach((member) => {
51+
if (!review.attendees.map((user) => user.userId).includes(member.userId)) {
52+
if (missedDict.has(member.userId)) {
53+
missedDict.set(member.userId, missedDict.get(member.userId)! + 1);
54+
} else {
55+
missedDict.set(member.userId, 1);
56+
}
57+
}
58+
});
59+
}
60+
});
61+
4162
const attendeeRows = filteredMembers.map((member, index) => (
4263
<TableRow key={index}>
43-
<TableCell sx={{ border: '2px solid black' }}>{member.name}</TableCell>
44-
<TableCell sx={{ border: '2px solid black' }}>{member.reviewsAttended}</TableCell>
45-
<TableCell sx={{ border: '2px solid black' }}>{member.missedReviews}</TableCell>
64+
<TableCell sx={{ border: '2px solid black' }}>{fullNamePipe(member)}</TableCell>
65+
<TableCell sx={{ border: '2px solid black' }}>{attendanceDict.get(member.userId) ?? 0}</TableCell>
66+
<TableCell sx={{ border: '2px solid black' }}>{missedDict.get(member.userId) ?? 0}</TableCell>
4667
</TableRow>
4768
));
4869

@@ -55,24 +76,6 @@ const AdminToolsAttendeeDesignReviewInfo: React.FC = () => {
5576
<FormLabel htmlFor="search-by-name">Search by team member name</FormLabel>
5677
<TextField id="search-by-name" variant="outlined" value={searchQuery} onChange={handleSearchChange} fullWidth />
5778
</FormControl>
58-
<FormControl fullWidth sx={{ marginBottom: 2 }}>
59-
<FormLabel id="team-select-label">Team</FormLabel>
60-
<Select
61-
labelId="team-select-label"
62-
id="team-select"
63-
value={selectedTeam}
64-
onChange={handleTeamChange}
65-
displayEmpty
66-
fullWidth
67-
>
68-
{teams.map((team) => (
69-
<MenuItem key={team} value={team}>
70-
{team}
71-
</MenuItem>
72-
))}
73-
{/* TODO: we'll have to change this here as well for backend logic, above is just a stub implementation. */}
74-
</Select>
75-
</FormControl>
7679
<AdminToolTable
7780
columns={[
7881
{ name: 'Team Member Name', width: '33%' },

0 commit comments

Comments
 (0)