Skip to content

Commit 293f7f5

Browse files
JihengLixnscdev
andauthored
Judge dashboard change and debug (#501)
* change judging and organizer logic and ui * remove all groups from dropdown in judging page * remove time constraint of judging * debug the judging dashboard, change the get judgingsession method, add have judged property to judging session dto * typo * let organizers to set time for one judge to score one team, changed the corresponding backend and database * fix type error * fix the bug: we should clear all the elements in judging session whenever we update the settings * fix bugs in hacker page --------- Co-authored-by: Isaac Liu <69013063+xnscdev@users.noreply.github.com>
1 parent 7247341 commit 293f7f5

File tree

12 files changed

+119
-141
lines changed

12 files changed

+119
-141
lines changed

components/Organizer/ScheduleTab/ScheduleTab.tsx

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,26 @@ const ScheduleTab = () => {
1313
const [timesJudged, setTimesJudged] = useState<number>(1);
1414
const [maxTimesJudged, setMaxTimesJudged] = useState<number>(0);
1515
const [potentialSchedule, setPotentialSchedule] = useState<JudgingSessionData[] | undefined>(undefined);
16+
const [hackathonSettings, setHackathonSettings] = useState<HackathonSettingsData | undefined>(undefined);
1617

1718
const { baseTheme } = useContext(ThemeContext);
1819

20+
// Get hackathon settings
21+
useEffect(() => {
22+
const fetchHackathonSettings = async () => {
23+
const res = await fetch('/api/hackathon-settings');
24+
if (res.ok) {
25+
const settings = await res.json();
26+
setHackathonSettings(settings as HackathonSettingsData);
27+
}
28+
};
29+
fetchHackathonSettings();
30+
}, []);
31+
32+
const TimeForJudgeToScoreOneTeam = parseInt(hackathonSettings?.JUDGING_TIME_PER_TEAM as string, 10);
33+
const JudgingDuration = hackathonSettings?.JUDGING_DURATION as number;
34+
const MaximumNumberOfTeamsOneJudgeCanFinishInJudgingTime = JudgingDuration / TimeForJudgeToScoreOneTeam;
35+
1936
// Get judging sessions
2037
const { data: judgingSessions, error: judgingSessionsError } = useCustomSWR<JudgingSessionData[]>({
2138
url: '/api/judging-sessions',
@@ -37,13 +54,6 @@ const ScheduleTab = () => {
3754
errorMessage: 'Failed to get list of teams.',
3855
});
3956

40-
// Get hackathon settings
41-
const { data: hackathonSettings, error: hackathonError } = useCustomSWR<HackathonSettingsData>({
42-
url: '/api/hackathon-settings',
43-
method: RequestType.GET,
44-
errorMessage: 'Failed to get hackathon times.',
45-
});
46-
4757
// Confirm potential schedule
4858
const handleConfirmPotentialSchedules = (potentialSchedule: JudgingSessionData[] | undefined) => {
4959
// Exit early if we don't have data yet
@@ -67,33 +77,23 @@ const ScheduleTab = () => {
6777
let judgingTimes = generateTimes(
6878
new Date(hackathonSettings?.JUDGING_START as string),
6979
new Date(hackathonSettings?.JUDGING_END as string),
70-
10
80+
TimeForJudgeToScoreOneTeam
7181
);
7282
setPotentialSchedule(matchTeams(teams, judges, judgingTimes, timesJudged));
7383
};
7484

7585
useEffect(() => {
7686
if (!teamsData || !judgesData) return;
77-
setMaxTimesJudged(Math.floor((judgesData?.length * 12) / teamsData?.length));
78-
}, [teamsData, judgesData]);
87+
setMaxTimesJudged(
88+
Math.floor((judgesData?.length * MaximumNumberOfTeamsOneJudgeCanFinishInJudgingTime) / teamsData?.length)
89+
);
90+
}, [teamsData, judgesData, hackathonSettings]);
7991

8092
useEffect(() => {
8193
// Exit early if we don't have data yet
8294
if (!judgingSessions) return;
83-
84-
// Sort judging sessions by time
85-
const time = new Date('2022-10-23T11:00:00').getTime();
86-
87-
// Set the data after filtering it by time
88-
setPotentialSchedule(
89-
judgingSessions.filter(judgingSession => {
90-
let time = new Date(judgingSession.time as string);
91-
return (
92-
new Date(hackathonSettings?.JUDGING_START as string) <= time &&
93-
time <= new Date(hackathonSettings?.JUDGING_END as string)
94-
);
95-
})
96-
);
95+
// Set the data
96+
setPotentialSchedule(judgingSessions);
9797
}, [judgingSessions, hackathonSettings]);
9898

9999
// Combine all the loading, null, and error states
@@ -162,6 +162,7 @@ const ScheduleTab = () => {
162162
handleChange={function (value: SetStateAction<string>): void {
163163
throw new Error('Function not implemented.');
164164
}}
165+
TimeForJudgeToScoreOneTeam={TimeForJudgeToScoreOneTeam}
165166
sessionTimeStart={new Date(hackathonSettings?.JUDGING_START as string)}
166167
sessionTimeEnd={new Date(hackathonSettings?.JUDGING_END as string)}
167168
/>

components/Organizer/SettingsTab/HackathonSettings.tsx

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, DatePicker, Select, Space } from 'antd';
1+
import { Button, DatePicker, Input, Select, Space } from 'antd';
22
import dayjs from 'dayjs';
33
import React, { useContext, useEffect, useState } from 'react';
44
import { handleSubmitFailure, handleSubmitSuccess } from '../../../lib/helpers';
@@ -89,6 +89,7 @@ const HackathonSettings = () => {
8989
setHackathonSetting(settings as HackathonSettingsData);
9090
setStatusMessage('Successfully saved to database!');
9191
handleSubmitSuccess('Successfully saved to database!');
92+
window.location.reload();
9293
} else {
9394
setStatusMessage('Failed to save to database!');
9495
handleSubmitFailure('Failed to save to database!');
@@ -114,14 +115,16 @@ const HackathonSettings = () => {
114115
};
115116

116117
const handleJudgingChange = (_: any, dateStrings: [string, string]) => {
117-
const newJudgingStart = dayjs(dateStrings[0], { utc: true }).format('MM/DD/YYYY hh:mm A');
118-
const newJudgingEnd = dayjs(dateStrings[1], { utc: true }).format('MM/DD/YYYY hh:mm A');
118+
const newJudgingStart = dayjs(dateStrings[0], { utc: true });
119+
const newJudgingEnd = dayjs(dateStrings[1], { utc: true });
120+
const judgingDuration = newJudgingEnd.diff(newJudgingStart, 'minute');
119121
setHackathonSetting(prev => {
120122
if (prev)
121123
return {
122124
...prev,
123-
JUDGING_START: newJudgingStart,
124-
JUDGING_END: newJudgingEnd,
125+
JUDGING_START: newJudgingStart.format('MM/DD/YYYY hh:mm A'),
126+
JUDGING_END: newJudgingEnd.format('MM/DD/YYYY hh:mm A'),
127+
JUDGING_DURATION: judgingDuration,
125128
};
126129
return undefined;
127130
});
@@ -161,6 +164,26 @@ const HackathonSettings = () => {
161164
defaultValue={[dayjs(hackathonSetting?.JUDGING_START), dayjs(hackathonSetting?.JUDGING_END)]}
162165
/>
163166

167+
<br />
168+
169+
<div>Time for Judge to Score One Team (minutes):</div>
170+
<Input
171+
value={hackathonSetting?.JUDGING_TIME_PER_TEAM}
172+
onChange={e => {
173+
setHackathonSetting(prev => {
174+
if (prev) {
175+
return {
176+
...prev,
177+
JUDGING_TIME_PER_TEAM: e.target.value,
178+
};
179+
}
180+
return prev;
181+
});
182+
}}
183+
placeholder="Enter time in minutes"
184+
style={{ width: 138 }}
185+
/>
186+
164187
<br />
165188
<br />
166189

components/hacker/HackerDash.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ export default function HackerDash({ userApplicationStatus, setUserApplicationSt
769769
<div style={{ padding: '20px' }}>
770770
<Header user={user} signOut={signOut} setting={setting as HackathonSettingsData} />
771771

772-
<TeamManagement />
772+
{/* <TeamManagement /> */}
773773
<JudgingSchedule judgingSessionData={judgingSessionData} />
774774
<Leaderboard />
775775

components/hacker/JudgingSchedule.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,23 @@ const JudgingSchedule = ({ judgingSessionData }: JudgingScheduleProps) => {
3434
return (
3535
<div className={styles.Container}>
3636
Judging Schedule
37-
<div className={styles.Description}>
38-
You will be assigned a table and judge for judging. Please be at your table at the time indicated below.
39-
</div>
37+
<div className={styles.Description}>You will be assigned a table and judge for judging.</div>
4038
{judgingSessionData?.length === 0 ? (
4139
<div className={styles.Placeholder}>Schedule will show up here when hacking ends!</div>
4240
) : (
4341
<div className={styles.TableContainer}>
4442
<table>
4543
<thead>
4644
<tr>
47-
<th>Time</th>
45+
{/* <th>Time</th> */}
4846
<th>Table</th>
4947
<th>Judge</th>
5048
</tr>
5149
</thead>
5250
<tbody>
5351
{judgingSessionData?.map(entry => (
5452
<tr key={entry.time.toString()}>
55-
<td>{renderJudgingTime(entry.time.toString())}</td>
53+
{/* <td>{renderJudgingTime(entry.time.toString())}</td> */}
5654
<td>{entry.team.locationNum}</td>
5755
<td>{entry.judge.name}</td>
5856
</tr>

components/judges/JudgeDash.tsx

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ async function handleSubmit(
4545
mutate('/api/teams');
4646
mutate('/api/judging-form');
4747
handleSubmitSuccess(`Successfully ${isNewForm ? 'submitted' : 'updated'}!`);
48+
if (isNewForm) window.location.reload();
4849
setIsNewForm(false);
4950
} else {
5051
handleSubmitFailure(await res.text());
@@ -54,8 +55,6 @@ async function handleSubmit(
5455
export default function JudgeDash() {
5556
const { data: session, status } = useSession();
5657
const [teamID, setTeamID] = useState('');
57-
const [currentScheduleItem, setCurrentScheduleItem] = useState<JudgingSessionData | undefined>(undefined);
58-
const [nextScheduleItem, setNextScheduleItem] = useState<JudgingSessionData | undefined>(undefined);
5958
const [isNewForm, setIsNewForm] = useState(false);
6059
const [nextIndex, setNextIndex] = useState(-1);
6160
const { mutate } = useSWRConfig();
@@ -132,51 +131,6 @@ export default function JudgeDash() {
132131
return (await res.json()) as JudgingSessionData[];
133132
});
134133

135-
// Initialize state if data was just received
136-
useEffect(() => {
137-
if (nextIndex === -1 && scheduleData) {
138-
const now = Date.now();
139-
let index = scheduleData.findIndex(el => now < new Date(el.time as string).getTime());
140-
if (index === -1) index = scheduleData.length;
141-
let currentlyGoingTime = new Date(scheduleData[index - 1]?.time as string).getTime() + judgingLength;
142-
setNextScheduleItem(scheduleData[index]);
143-
setCurrentScheduleItem(now < currentlyGoingTime ? scheduleData[index - 1] : undefined);
144-
setNextIndex(index);
145-
}
146-
}, [scheduleData, nextIndex, judgingLength]);
147-
148-
// Loop to manage current schedule state
149-
useEffect(() => {
150-
const interval = setInterval(() => {
151-
const now = Date.now();
152-
if (scheduleData && nextIndex > -1) {
153-
// Data has been received and state is initialized
154-
let time2 = new Date(scheduleData[scheduleData.length - 1]?.time as string).getTime() + judgingLength;
155-
if (now <= time2) {
156-
// Not yet done judging
157-
let time3 = new Date((currentScheduleItem?.time as string) || 0).getTime() + judgingLength;
158-
159-
if (
160-
nextIndex < scheduleData.length &&
161-
now >= new Date((nextScheduleItem?.time as string) || 0).getTime()
162-
) {
163-
// Next event should be current
164-
setNextScheduleItem(scheduleData[nextIndex + 1]);
165-
setCurrentScheduleItem(scheduleData[nextIndex]);
166-
setNextIndex(nextIndex + 1);
167-
} else if (now > time3) {
168-
// Next event has not yet arrived but current event is over
169-
setCurrentScheduleItem(undefined);
170-
}
171-
} else {
172-
// Done judging
173-
setCurrentScheduleItem(undefined);
174-
}
175-
}
176-
}, 1000);
177-
return () => clearInterval(interval);
178-
});
179-
180134
const handleTeamChange: Dispatch<SetStateAction<string>> = e => {
181135
setTeamID(e);
182136
setTimeout(() => {
@@ -204,9 +158,7 @@ export default function JudgeDash() {
204158
</div>
205159
</div>
206160
</div>
207-
{scheduleData && (
208-
<JudgeSchedule data={scheduleData} cutoffIndex={nextIndex} handleChange={handleTeamChange} />
209-
)}
161+
{scheduleData && <JudgeSchedule data={scheduleData} handleChange={handleTeamChange} />}
210162
<br />
211163
<br />
212164
{teamsData && <TeamSelect teamsData={teamsData} currentTeamID={teamID} handleChange={handleTeamChange} />}

components/judges/TeamSelect.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,6 @@ export default function TeamSelect(props: TeamSelectProps) {
6363
))}
6464
</OptGroup>
6565
)}
66-
<OptGroup label="All Teams">
67-
{teamsData.map(team => (
68-
<Option value={team._id} key={`${team._id}ALL`}>
69-
{team.haveJudged ? withCheckMark(team.name) : team.name}
70-
</Option>
71-
))}
72-
</OptGroup>
7366
</Select>
7467
</Space>
7568
);

0 commit comments

Comments
 (0)