11import 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' ;
143import 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
1612const 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