Skip to content

Commit 2d59d81

Browse files
authored
Merge pull request #87 from jolynloh/FE/collabPage
Collab page session controls
2 parents 97b1f73 + ee62911 commit 2d59d81

File tree

6 files changed

+197
-14
lines changed

6 files changed

+197
-14
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Button, Stack } from "@mui/material";
2+
import Stopwatch from "../Stopwatch";
3+
import { useMatch } from "../../contexts/MatchContext";
4+
import { USE_MATCH_ERROR_MESSAGE } from "../../utils/constants";
5+
import { useEffect, useState } from "react";
6+
import {
7+
extractHoursFromTime,
8+
extractMinutesFromTime,
9+
extractSecondsFromTime,
10+
} from "../../utils/sessionTime";
11+
12+
const CollabSessionControls: React.FC = () => {
13+
const [time, setTime] = useState<number>(0);
14+
15+
useEffect(() => {
16+
let intervalId = setInterval(
17+
() => setTime((prevTime) => prevTime + 1),
18+
1000
19+
);
20+
21+
return () => clearInterval(intervalId);
22+
}, [time]);
23+
24+
const match = useMatch();
25+
if (!match) {
26+
throw new Error(USE_MATCH_ERROR_MESSAGE);
27+
}
28+
const { handleEndSessionClick } = match;
29+
30+
return (
31+
<Stack direction={"row"} alignItems={"center"} spacing={2}>
32+
<Stopwatch time={time} />
33+
<Button
34+
sx={{
35+
border: 1.5,
36+
borderRadius: 4,
37+
}}
38+
variant="outlined"
39+
color="success"
40+
onClick={() => {
41+
console.log(
42+
`Time taken: ${extractHoursFromTime(
43+
time
44+
)} hrs ${extractMinutesFromTime(
45+
time
46+
)} mins ${extractSecondsFromTime(time)} secs`
47+
);
48+
}} // TODO: implement submit function with time taken pop-up
49+
>
50+
Submit
51+
</Button>
52+
<Button
53+
sx={{
54+
border: 1.5,
55+
borderRadius: 4,
56+
}}
57+
variant="outlined"
58+
color="error"
59+
onClick={() => handleEndSessionClick()}
60+
>
61+
End Session
62+
</Button>
63+
</Stack>
64+
);
65+
};
66+
67+
export default CollabSessionControls;

frontend/src/components/Navbar/index.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
} from "../../utils/constants";
2424
import { isMatchingPage, isCollabPage } from "../../utils/url";
2525
import { useMatch } from "../../contexts/MatchContext";
26+
import CollabSessionControls from "../CollabSessionControls";
2627

2728
type NavbarItem = { label: string; link: string; needsLogin: boolean };
2829

@@ -83,15 +84,9 @@ const Navbar: React.FC<NavbarProps> = (props) => {
8384
PeerPrep
8485
</Typography>
8586
{isCollabPage(path) ? (
86-
<Stack direction={"row"} alignItems={"center"} spacing={2}>
87-
<Button
88-
variant="outlined"
89-
color="error"
90-
onClick={() => stopMatch()}
91-
>
92-
Stop matching
93-
</Button>
94-
</Stack>
87+
<>
88+
<CollabSessionControls />
89+
</>
9590
) : !isMatchingPage(path) ? (
9691
<Stack direction={"row"} alignItems={"center"} spacing={2}>
9792
{navbarItems
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {
2+
extractHoursFromTime,
3+
extractMinutesFromTime,
4+
extractSecondsFromTime,
5+
} from "../../utils/sessionTime";
6+
7+
interface StopwatchProps {
8+
time: number;
9+
}
10+
11+
const Stopwatch: React.FC<StopwatchProps> = (props) => {
12+
const { time } = props;
13+
14+
const hours = extractHoursFromTime(time);
15+
const minutes = extractMinutesFromTime(time);
16+
const seconds = extractSecondsFromTime(time);
17+
18+
return (
19+
<div>
20+
<p style={{ color: "black", fontWeight: "bold" }}>
21+
{hours.toString().padStart(2, "0")}:
22+
{minutes.toString().padStart(2, "0")}:
23+
{seconds.toString().padStart(2, "0")}
24+
</p>
25+
</div>
26+
);
27+
};
28+
29+
export default Stopwatch;

frontend/src/contexts/MatchContext.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,15 @@ type MatchContextType = {
8282
matchOfferTimeout: () => void;
8383
verifyMatchStatus: () => void;
8484
getMatchId: () => string | null;
85+
handleEndSessionClick: () => void;
86+
handleRejectEndSession: () => void;
87+
handleConfirmEndSession: () => void;
8588
matchUser: MatchUser | null;
8689
matchCriteria: MatchCriteria | null;
8790
partner: MatchUser | null;
8891
matchPending: boolean;
8992
loading: boolean;
93+
isEndSessionModalOpen: boolean;
9094
questionId: string | null;
9195
};
9296

@@ -114,6 +118,9 @@ const MatchProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
114118
const [loading, setLoading] = useState<boolean>(true);
115119
const [questionId, setQuestionId] = useState<string | null>(null);
116120

121+
const [isEndSessionModalOpen, setIsEndSessionModalOpen] =
122+
useState<boolean>(false);
123+
117124
const navigator = useContext(UNSAFE_NavigationContext).navigator as History;
118125

119126
useEffect(() => {
@@ -485,6 +492,19 @@ const MatchProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
485492
return matchId;
486493
};
487494

495+
const handleEndSessionClick = () => {
496+
setIsEndSessionModalOpen(true);
497+
}
498+
499+
const handleRejectEndSession = () => {
500+
setIsEndSessionModalOpen(false);
501+
};
502+
503+
const handleConfirmEndSession = () => {
504+
stopMatch();
505+
setIsEndSessionModalOpen(false);
506+
};
507+
488508
return (
489509
<MatchContext.Provider
490510
value={{
@@ -497,11 +517,15 @@ const MatchProvider: React.FC<{ children?: React.ReactNode }> = (props) => {
497517
matchOfferTimeout,
498518
verifyMatchStatus,
499519
getMatchId,
520+
handleEndSessionClick,
521+
handleRejectEndSession,
522+
handleConfirmEndSession,
500523
matchUser,
501524
matchCriteria,
502525
partner,
503526
matchPending,
504527
loading,
528+
isEndSessionModalOpen,
505529
questionId,
506530
}}
507531
>

frontend/src/pages/CollabSandbox/index.tsx

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import AppMargin from "../../components/AppMargin";
2-
import { Box } from "@mui/material";
2+
import {
3+
Box,
4+
Button,
5+
Dialog,
6+
DialogActions,
7+
DialogContent,
8+
DialogContentText,
9+
DialogTitle,
10+
} from "@mui/material";
311
import classes from "./index.module.css";
412
import { useMatch } from "../../contexts/MatchContext";
513
import { USE_MATCH_ERROR_MESSAGE } from "../../utils/constants";
@@ -17,7 +25,17 @@ const CollabSandbox: React.FC = () => {
1725
if (!match) {
1826
throw new Error(USE_MATCH_ERROR_MESSAGE);
1927
}
20-
const { verifyMatchStatus, getMatchId, partner, loading, questionId } = match;
28+
29+
const {
30+
verifyMatchStatus,
31+
getMatchId,
32+
handleRejectEndSession,
33+
handleConfirmEndSession,
34+
partner,
35+
loading,
36+
isEndSessionModalOpen,
37+
questionId,
38+
} = match;
2139
const [state, dispatch] = useReducer(reducer, initialState);
2240
const { selectedQuestion } = state;
2341

@@ -53,10 +71,54 @@ const CollabSandbox: React.FC = () => {
5371
<AppMargin classname={`${classes.fullheight} ${classes.flex}`}>
5472
{/* <Stack spacing={2} alignItems={"center"}>
5573
<Typography variant="h1">Successfully matched!</Typography>
56-
<Button variant="outlined" color="error" onClick={() => stopMatch()}>
57-
End Session
58-
</Button>
5974
</Stack> */}
75+
<Dialog
76+
sx={{
77+
"& .MuiDialog-paper": {
78+
padding: "20px",
79+
},
80+
}}
81+
open={isEndSessionModalOpen}
82+
onClose={handleRejectEndSession}
83+
>
84+
<DialogTitle sx={{ textAlign: "center", fontSize: 20 }}>
85+
{"End Session?"}
86+
</DialogTitle>
87+
<DialogContent>
88+
<DialogContentText sx={{ textAlign: "center", fontSize: 16 }}>
89+
Are you sure you want to end session?
90+
<br />
91+
You will lose your current progress.
92+
</DialogContentText>
93+
</DialogContent>
94+
<DialogActions
95+
sx={{
96+
justifyContent: "center",
97+
paddingBottom: "20px",
98+
}}
99+
>
100+
<Button
101+
sx={{
102+
width: "250px",
103+
}}
104+
variant="contained"
105+
color="secondary"
106+
onClick={handleRejectEndSession}
107+
>
108+
Back
109+
</Button>
110+
<Button
111+
sx={{
112+
width: "250px",
113+
}}
114+
variant="contained"
115+
onClick={handleConfirmEndSession}
116+
>
117+
Confirm
118+
</Button>
119+
</DialogActions>
120+
</Dialog>
121+
60122
<Box sx={{ display: "flex", flex: 1 }}>
61123
<Box sx={(theme) => ({ flex: 1, marginRight: theme.spacing(2) })}>
62124
<QuestionDetailComponent

frontend/src/utils/sessionTime.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const extractHoursFromTime = (time: number) => Math.floor(time / 3600);
2+
3+
export const extractMinutesFromTime = (time: number) =>
4+
Math.floor((time % 3600) / 60); // after extracting hours
5+
6+
export const extractSecondsFromTime = (time: number) => time % 60; // after extracting hours and minutes

0 commit comments

Comments
 (0)