Skip to content

Commit ba87b8b

Browse files
Merge pull request #298 from cmu15122/jtromero/working
Add 213 request timer feature
2 parents 9330897 + 4e89b8c commit ba87b8b

25 files changed

+849
-1127
lines changed

client/package-lock.json

Lines changed: 370 additions & 374 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/src/components/home/HomeMain.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import React, {useState, useEffect, useContext} from 'react';
1+
import React, { useState, useEffect, useContext } from 'react';
22

33
import SharedMain from './shared/SharedMain';
44
import StudentMain from './student/StudentMain';
55
import TAMain from './ta/TAMain';
66
import Footer from './Footer';
7-
import {Container} from '@mui/material';
7+
import { Container } from '@mui/material';
88

9-
import {UserDataContext} from '../../contexts/UserDataContext';
9+
import { UserDataContext } from '../../contexts/UserDataContext';
10+
import { ensureSocketConnected } from '../../services/SocketsService';
1011

1112
function HomeMain() {
12-
const {userData} = useContext(UserDataContext);
13+
const { userData } = useContext(UserDataContext);
1314

1415
const gitHubLink = 'https://github.com/cmu15122/q-issues/issues';
1516

@@ -26,21 +27,34 @@ function HomeMain() {
2627
useEffect(() => {
2728
if (userData.isAuthenticated) {
2829
if (userData.isTA) {
29-
setMainPage(<TAMain/>);
30-
} else { // is student
31-
setMainPage(<StudentMain/>);
30+
setMainPage(<TAMain />);
31+
} else {
32+
// is student
33+
setMainPage(<StudentMain />);
3234
}
3335
} else {
3436
// you are not logged in
3537
setMainPage(null);
3638
}
3739
}, [userData.isAuthenticated, userData.isTA]);
3840

41+
useEffect(() => {
42+
const interval = setInterval(() => {
43+
ensureSocketConnected();
44+
}, 1000);
45+
46+
return () => {
47+
clearInterval(interval);
48+
};
49+
}, []);
50+
3951
return (
40-
<Container sx={{display: 'flex', minHeight: '100vh', flexDirection: 'column'}}>
41-
<SharedMain/>
52+
<Container
53+
sx={{ display: 'flex', minHeight: '100vh', flexDirection: 'column' }}
54+
>
55+
<SharedMain />
4256
{mainPage}
43-
<Footer gitHubLink={gitHubLink}/>
57+
<Footer gitHubLink={gitHubLink} />
4458
</Container>
4559
);
4660
}

client/src/components/home/ta/EntryTails.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { StudentStatusValues } from '../../../services/StudentStatus';
1111
import { UserDataContext } from '../../../contexts/UserDataContext';
1212

1313
export default function EntryTails(props) {
14-
const { student } = props;
14+
const { student, currentTime } = props;
1515
const { userData } = useContext(UserDataContext);
1616

1717
const showApproval = props.showCooldownApproval;
@@ -53,7 +53,7 @@ export default function EntryTails(props) {
5353
alignItems="center"
5454
sx={{ mr: { xs: 1, sm: 2, lg: 3 }, ml: { xs: 1, sm: 2 }, my: 1.5 }}
5555
>
56-
<StudentStatus student={student} />
56+
<StudentStatus student={student} currentTime={currentTime} />
5757
{getCorrectTail(status)}
5858
</Stack>
5959
);

client/src/components/home/ta/StudentEntries.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ export default function StudentEntries(props) {
1919
const { userData } = useContext(UserDataContext);
2020
const { allStudents, setAllStudents } = useContext(AllStudentsContext);
2121

22+
// Add a current time state that will be passed to all StudentStatus components
23+
const [currentTime, setCurrentTime] = useState(Date.now());
24+
25+
// Update the current time every second
26+
useEffect(() => {
27+
const intervalId = setInterval(() => {
28+
setCurrentTime(Date.now());
29+
}, 1000);
30+
31+
return () => clearInterval(intervalId);
32+
}, []);
33+
2234
/* BEGIN FILTER LOGIC */
2335

2436
const [isHelping, setIsHelping] = useState(false);
@@ -229,6 +241,7 @@ export default function StudentEntries(props) {
229241
handleFix={handleFix}
230242
removeStudent={removeStudent}
231243
handleClickUnfreeze={handleClickUnfreeze}
244+
currentTime={currentTime}
232245
/>
233246
))}
234247
</BaseTable>

client/src/components/home/ta/StudentEntry.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export default function StudentEntry(props) {
1919
removeStudent,
2020
handleClickUnfreeze,
2121
handleFix,
22+
currentTime,
2223
} = props;
2324

2425
const [confirmRemove, setConfirmRemove] = useState(false);
@@ -111,6 +112,7 @@ export default function StudentEntry(props) {
111112
handleFix: handleFix,
112113
showCooldownApproval: showCooldownApproval,
113114
approveCooldownOverride: approveCooldownOverride,
115+
currentTime: currentTime,
114116
})}
115117
</TableCell>
116118
</ItemRow>

client/src/components/home/ta/TailOptions/ActionsHelp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React from 'react';
22
import { Button, Stack } from '@mui/material';
33

44
import PersistentOptions from './PersistentOptions';

client/src/components/home/ta/TailOptions/ExtraStudentOptions.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Divider, Menu, MenuItem, IconButton, Typography } from '@mui/material';
33
import SettingsIcon from '@mui/icons-material/Settings';
44
import { Help } from '@mui/icons-material';
55
import ChatIcon from '@mui/icons-material/Chat';
6-
import HomeService from '../../../../services/HomeService';
76

87
import MessageDialog from '../dialogs/MessageDialog';
98
import { StudentStatusValues } from '../../../../services/StudentStatus';

client/src/components/home/ta/TailOptions/StudentStatus.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,59 @@ import { Typography, useTheme } from '@mui/material';
33

44
import { StudentStatusValues } from '../../../../services/StudentStatus';
55
import { UserDataContext } from '../../../../contexts/UserDataContext';
6+
import { QueueDataContext } from '../../../../contexts/QueueDataContext';
67

78
export default function StudentStatus(props) {
8-
const { student } = props;
9+
const { student, currentTime } = props;
910
const theme = useTheme();
1011

1112
const { userData } = useContext(UserDataContext);
13+
const { queueData } = useContext(QueueDataContext);
1214

1315
const status = student.status;
1416

17+
const formatTime = (seconds) => {
18+
// Handle negative or zero seconds
19+
if (seconds <= 0) return '0:00';
20+
21+
const minutes = Math.floor(seconds / 60);
22+
const remainingSeconds = seconds % 60;
23+
return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;
24+
};
25+
26+
// Calculate elapsed time based on the provided currentTime
27+
const getElapsedTime = () => {
28+
if (
29+
status === StudentStatusValues.BEING_HELPED &&
30+
student.helpingTAInfo?.helpStartTime
31+
) {
32+
const startTime = new Date(student.helpingTAInfo.helpStartTime).getTime();
33+
return Math.floor((currentTime - startTime) / 1000);
34+
}
35+
return 0;
36+
};
37+
1538
const chooseText = (status) => {
1639
switch (status) {
1740
case StudentStatusValues.BEING_HELPED: {
1841
if (student.helpingTAInfo?.taAndrewID === userData.andrewID) {
42+
// Show self timer if enabled
43+
if (
44+
userData.taSettings?.showSelfTimer &&
45+
student.helpingTAInfo?.helpStartTime
46+
) {
47+
return `You have been helping for ${formatTime(getElapsedTime())}`;
48+
}
1949
return 'You are helping';
2050
} else {
51+
// Show others timer if enabled (both user setting and admin setting)
52+
if (
53+
userData.taSettings?.showOthersTimer &&
54+
queueData.allowShowOthersTimer &&
55+
student.helpingTAInfo?.helpStartTime
56+
) {
57+
return `${student?.helpingTAInfo?.taPrefName} has been helping for ${formatTime(getElapsedTime())}`;
58+
}
2159
return `${student?.helpingTAInfo?.taPrefName} is Helping`;
2260
}
2361
}

client/src/components/settings/SettingsMain.tsx

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
1-
import React, {useContext} from 'react';
2-
import {
3-
Typography,
4-
} from '@mui/material';
1+
import React, { useContext } from 'react';
2+
import { Typography } from '@mui/material';
53

64
import AdminMain from './admin/AdminMain';
75
import VideoChatSettings from './VideoChatSettings';
86
import NotificationSettings from './NotificationSettings';
9-
import {UserDataContext} from '../../contexts/UserDataContext';
7+
import TimerSettings from './TimerSettings';
8+
import { UserDataContext } from '../../contexts/UserDataContext';
109

1110
function Main(props) {
12-
const {userData} = useContext(UserDataContext);
11+
const { userData } = useContext(UserDataContext);
1312

1413
return (
1514
<div>
16-
<Typography variant="h3" textAlign='center' sx={{mt: 4, mb: 2}} fontWeight='bold'>
15+
<Typography
16+
variant="h3"
17+
textAlign="center"
18+
sx={{ mt: 4, mb: 2 }}
19+
fontWeight="bold"
20+
>
1721
Settings
1822
</Typography>
19-
{
20-
!userData.isOwner && <VideoChatSettings/>
21-
}
22-
{
23-
!userData.isOwner && <NotificationSettings/>
24-
}
23+
{!userData.isOwner && <VideoChatSettings />}
24+
{!userData.isOwner && <NotificationSettings />}
25+
{!userData.isOwner && <TimerSettings />}
2526

26-
{
27-
userData.isAdmin && <AdminMain/>
28-
}
27+
{userData.isAdmin && <AdminMain />}
2928
</div>
3029
);
3130
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { useState, useEffect, useContext } from 'react';
2+
import {
3+
CardContent,
4+
Checkbox,
5+
FormControlLabel,
6+
Grid,
7+
Typography,
8+
} from '@mui/material';
9+
10+
import BaseCard from '../common/cards/BaseCard';
11+
12+
import SettingsService from '../../services/SettingsService';
13+
import { UserDataContext } from '../../contexts/UserDataContext';
14+
import { QueueDataContext } from '../../contexts/QueueDataContext';
15+
16+
export default function TimerSettings(props) {
17+
const { userData } = useContext(UserDataContext);
18+
const { queueData } = useContext(QueueDataContext);
19+
20+
const [showSelfTimer, setShowSelfTimer] = useState(false);
21+
const [showOthersTimer, setShowOthersTimer] = useState(false);
22+
23+
useEffect(() => {
24+
setShowSelfTimer(userData.taSettings?.showSelfTimer || false);
25+
setShowOthersTimer(userData.taSettings?.showOthersTimer || false);
26+
}, [userData]);
27+
28+
const updateTimerSettings = (selfTimer, othersTimer) => {
29+
SettingsService.updateTimerSettings({
30+
showSelfTimer: selfTimer,
31+
showOthersTimer: othersTimer,
32+
});
33+
};
34+
35+
return (
36+
<BaseCard>
37+
<CardContent>
38+
<Typography
39+
sx={{ fontWeight: 'bold', ml: 1, mt: 1 }}
40+
variant="body1"
41+
gutterBottom
42+
>
43+
Timer Settings
44+
</Typography>
45+
<Grid container spacing={1}>
46+
<Grid className="d-flex" item sx={{ mb: -1 }} xs={12}>
47+
<FormControlLabel
48+
control={
49+
<Checkbox
50+
size="small"
51+
sx={{ ml: 1 }}
52+
checked={showSelfTimer ?? false}
53+
onChange={(e) => {
54+
const isShowSelfTimer = e.target.checked;
55+
setShowSelfTimer(isShowSelfTimer);
56+
updateTimerSettings(isShowSelfTimer, showOthersTimer);
57+
}}
58+
/>
59+
}
60+
label={<div>Show timer when I&apos;m helping a student</div>}
61+
/>
62+
</Grid>
63+
{queueData.allowShowOthersTimer && (
64+
<Grid className="d-flex" item xs={12}>
65+
<FormControlLabel
66+
control={
67+
<Checkbox
68+
size="small"
69+
sx={{ ml: 1 }}
70+
checked={showOthersTimer ?? false}
71+
disabled={!queueData.allowShowOthersTimer}
72+
onChange={(e) => {
73+
const isShowOthersTimer = e.target.checked;
74+
setShowOthersTimer(isShowOthersTimer);
75+
updateTimerSettings(showSelfTimer, isShowOthersTimer);
76+
}}
77+
/>
78+
}
79+
label={
80+
<div>Show timers when other TAs are helping students</div>
81+
}
82+
/>
83+
</Grid>
84+
)}
85+
</Grid>
86+
</CardContent>
87+
</BaseCard>
88+
);
89+
}

0 commit comments

Comments
 (0)