Skip to content

Commit b6a32db

Browse files
committed
Implement end collaboration session for both users, fix minor bugs with text html
1 parent 3ee517c commit b6a32db

File tree

6 files changed

+332
-205
lines changed

6 files changed

+332
-205
lines changed

apps/frontend/src/app/collaboration/[id]/page.tsx

Lines changed: 93 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,23 @@ import {
2222
ClockCircleOutlined,
2323
CodeOutlined,
2424
FileDoneOutlined,
25+
InfoCircleFilled,
2526
MessageOutlined,
2627
PlayCircleOutlined,
2728
SendOutlined,
2829
} from "@ant-design/icons";
2930
import { ProgrammingLanguageOptions } from "@/utils/SelectOptions";
30-
import CollaborativeEditor from "@/components/CollaborativeEditor/CollaborativeEditor";
31+
import CollaborativeEditor, {
32+
CollaborativeEditorHandle,
33+
} from "@/components/CollaborativeEditor/CollaborativeEditor";
3134

3235
interface CollaborationProps {}
3336

3437
export default function CollaborationPage(props: CollaborationProps) {
3538
const router = useRouter();
3639

40+
const editorRef = useRef<CollaborativeEditorHandle>(null);
41+
3742
const [isLoading, setIsLoading] = useState<boolean>(false);
3843

3944
// Code Editor States
@@ -50,7 +55,7 @@ export default function CollaborationPage(props: CollaborationProps) {
5055
undefined
5156
);
5257
const [currentUser, setCurrentUser] = useState<string | undefined>(undefined);
53-
const [matchedUser, setMatchedUser] = useState<string>("Not Connected");
58+
const [matchedUser, setMatchedUser] = useState<string>("Loading...");
5459
const [sessionDuration, setSessionDuration] = useState<number>(() => {
5560
const storedTime = localStorage.getItem("session-duration");
5661
return storedTime ? parseInt(storedTime) : 0;
@@ -67,8 +72,12 @@ export default function CollaborationPage(props: CollaborationProps) {
6772
undefined
6873
);
6974

70-
// Modal state
75+
// End Button Modal state
7176
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
77+
// Session End Modal State
78+
const [isSessionEndModalOpen, setIsSessionEndModalOpen] =
79+
useState<boolean>(false);
80+
const [countDown, setCountDown] = useState<number>(5);
7281

7382
// Stops the session duration stopwatch
7483
const stopStopwatch = () => {
@@ -121,7 +130,7 @@ export default function CollaborationPage(props: CollaborationProps) {
121130

122131
// Set states from localstorage
123132
setCollaborationId(collabId);
124-
// setMatchedUser(matchedUser); // TODO: remove after being handled in collabeditor
133+
setMatchedUser(matchedUser);
125134
setCurrentUser(currentUser);
126135

127136
// Fetch question and set question states
@@ -136,6 +145,19 @@ export default function CollaborationPage(props: CollaborationProps) {
136145
startStopwatch();
137146
}, []);
138147

148+
// useEffect for timer
149+
useEffect(() => {
150+
if (isSessionEndModalOpen && countDown > 0) {
151+
const timer = setInterval(() => {
152+
setCountDown((prevCountDown) => prevCountDown - 1);
153+
}, 1000);
154+
155+
return () => clearInterval(timer); // Clean up on component unmount or when countdown changes
156+
} else if (countDown === 0) {
157+
router.push("/matching"); // Redirect to matching page
158+
}
159+
}, [isSessionEndModalOpen, countDown]);
160+
139161
// Tabs component items for testcases
140162
const items: TabsProps["items"] = [
141163
{
@@ -166,23 +188,76 @@ export default function CollaborationPage(props: CollaborationProps) {
166188
];
167189

168190
// Handles the cleaning of localstorage variables, stopping the timer & signalling collab user on webrtc
169-
const handleCloseCollaboration = () => {
191+
// type: "initiator" | "peer"
192+
const handleCloseCollaboration = (type: string) => {
170193
// Stop stopwatch
171194
stopStopwatch();
195+
if (editorRef.current && type === "initiator") {
196+
editorRef.current.endSession(); // Call the method on the editor
197+
}
198+
199+
// Trigger modal open showing session end details
200+
setIsSessionEndModalOpen(true);
201+
172202
// Remove localstorage variables for collaboration
173203
localStorage.removeItem("session-duration"); // TODO: Remove this after collaboration backend data stored
174204
localStorage.removeItem("user");
175205
localStorage.removeItem("collabId");
176206
localStorage.removeItem("docRefId");
177-
178-
// Redirect back to matching page
179-
router.push("/matching");
207+
localStorage.removeItem("matchedUser");
180208
};
181209

182210
return (
183211
<Layout className="collaboration-layout">
184212
<Header selectedKey={undefined} />
185213
<Content className="collaboration-content">
214+
<Modal
215+
height={500}
216+
title={"Session Ended"}
217+
footer={null}
218+
open={isSessionEndModalOpen}
219+
width={400}
220+
closable={false}
221+
>
222+
<p className="session-modal-description">
223+
The collaboration session has ended. You will be redirected in{" "}
224+
{countDown}
225+
seconds
226+
</p>
227+
<p className="session-modal-question">
228+
Question:{" "}
229+
<span className="session-modal-title">{questionTitle}</span>
230+
</p>
231+
<p className="session-modal-difficulty">
232+
Difficulty:{" "}
233+
<Tag
234+
className="complexity-tag"
235+
style={{
236+
color:
237+
complexity === "easy"
238+
? "#2DB55D"
239+
: complexity === "medium"
240+
? "orange"
241+
: "red",
242+
}}
243+
>
244+
{complexity &&
245+
complexity.charAt(0).toUpperCase() + complexity.slice(1)}
246+
</Tag>
247+
</p>
248+
<p className="session-modal-duration">
249+
Duration:{" "}
250+
<span className="session-modal-time">
251+
{formatTime(sessionDuration)}
252+
</span>
253+
</p>
254+
<p className="session-modal-matched-user">
255+
Matched User:{" "}
256+
<span className="session-modal-matched-user-name">
257+
{matchedUser}
258+
</span>
259+
</p>
260+
</Modal>
186261
<Row gutter={0} className="collab-row">
187262
<Col span={7} className="first-col">
188263
<Row className="question-row">
@@ -205,7 +280,7 @@ export default function CollaborationPage(props: CollaborationProps) {
205280
</Tag>
206281
</div>
207282
<div className="question-topic">
208-
<text className="topic-label">Topics: </text>
283+
<span className="topic-label">Topics: </span>
209284
{categories.map((category) => (
210285
<Tag key={category}>{category}</Tag>
211286
))}
@@ -254,10 +329,12 @@ export default function CollaborationPage(props: CollaborationProps) {
254329
</div>
255330
{collaborationId && currentUser && selectedLanguage && (
256331
<CollaborativeEditor
332+
ref={editorRef}
257333
user={currentUser}
258334
collaborationId={collaborationId}
259335
language={selectedLanguage}
260336
setMatchedUser={setMatchedUser}
337+
handleCloseCollaboration={handleCloseCollaboration}
261338
/>
262339
)}
263340
</div>
@@ -276,36 +353,36 @@ export default function CollaborationPage(props: CollaborationProps) {
276353
title={"End Session"}
277354
okText={"End"}
278355
okButtonProps={{ danger: true }}
279-
onOk={handleCloseCollaboration}
356+
onOk={() => handleCloseCollaboration("initiator")}
280357
open={isModalOpen}
281358
onCancel={() => setIsModalOpen(false)}
282359
width={400}
283360
>
284361
<p className="modal-description">
285362
Are you sure you want to quit the existing collaboration
286-
session?
363+
session? This will end the session for both users!
287364
</p>
288365
</Modal>
289366
<Button
290367
danger
291368
onClick={() => setIsModalOpen(true)}
292369
className="session-end-button"
293370
>
294-
End
371+
End for All
295372
</Button>
296373
</div>
297374

298375
<div className="session-duration">
299376
Duration:
300-
<text className="session-duration-timer">
377+
<span className="session-duration-timer">
301378
{formatTime(sessionDuration)}
302-
</text>
379+
</span>
303380
</div>
304381
<div className="session-matched-user-label">
305382
Matched User:
306-
<text className="session-matched-user-name">
383+
<span className="session-matched-user-name">
307384
{matchedUser}
308-
</text>
385+
</span>
309386
</div>
310387
</div>
311388
</Row>

apps/frontend/src/app/collaboration/[id]/styles.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,22 @@
178178
.modal-description {
179179
margin-bottom: 2rem;
180180
}
181+
182+
.session-modal-question,
183+
.session-modal-difficulty,
184+
.session-modal-duration,
185+
.session-modal-matched-user {
186+
font-weight: bold;
187+
}
188+
189+
.session-modal-time,
190+
.session-modal-title {
191+
font-weight: normal;
192+
}
193+
.session-modal-matched-user-name {
194+
color: #e0afa0;
195+
}
196+
197+
.info-modal-icon {
198+
color: red;
199+
}

apps/frontend/src/app/matching/MatchingModal.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ const MatchingModal: React.FC<MatchingModalProps> = ({
100100
localStorage.setItem("user", matchingState.info.myName);
101101
localStorage.setItem("collabId", matchingState.info.matchId);
102102
localStorage.setItem("docRefId", matchingState.info.docRefId);
103-
103+
localStorage.setItem(
104+
"matchedUser",
105+
matchingState.info.partnerName
106+
);
104107
// Redirect to collaboration page
105108
router.push(`/collaboration/${matchingState.info.matchId}`);
106109
}}

apps/frontend/src/app/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,24 @@ const HomePage = () => {
1414

1515
const closeMatchingModal = () => {
1616
setMatchingModalOpen(false);
17-
}
17+
};
1818

1919
return (
2020
<Layout className="layout">
2121
<Header selectedKey={undefined} />
2222
<Content className="content">
23-
<MatchingModal isOpen={matchingModalOpen} close={closeMatchingModal}/>
23+
<MatchingModal isOpen={matchingModalOpen} close={closeMatchingModal} />
2424
<div className="home-content-card">
2525
<div className="left-panel">
2626
<div className="logo-container">
2727
<div className="logo1-title">Peer</div>
2828
<div className="logo2-title">Prep</div>
2929
</div>
3030
<div className="slogan">
31-
<text className="slogan-1">
31+
<span className="slogan-1">
3232
A better way to prepare for coding interviews with
33-
</text>
34-
<text className="slogan-2"> peers</text>
33+
</span>
34+
<span className="slogan-2"> peers</span>
3535
</div>
3636
<div className="button-container">
3737
<Button

apps/frontend/src/app/question/[id]/page.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ export default function QuestionPage() {
102102
<h3 className="problem-description-title">
103103
{questionTitle}
104104
</h3>
105-
<text className="problem-solve-status">
105+
<span className="problem-solve-status">
106106
Solved&nbsp;
107107
<CheckCircleOutlined />
108-
</text>
108+
</span>
109109
</div>
110110
<div className="complexity-div">
111111
<Tag
@@ -125,13 +125,13 @@ export default function QuestionPage() {
125125
</Tag>
126126
</div>
127127
<div id="tag-container" className="tag-container">
128-
<text className="topic-label">Topics: </text>
128+
<span className="topic-label">Topics: </span>
129129
{categories.map((category) => (
130130
<Tag key={category}>{category}</Tag>
131131
))}
132132
</div>
133133
<div className="description-text">
134-
<text>{description}</text>
134+
<span>{description}</span>
135135
</div>
136136
</div>
137137
</Row>
@@ -174,9 +174,9 @@ export default function QuestionPage() {
174174
</div>
175175
<div className="language-select">
176176
<div>
177-
<text className="language-text">
177+
<span className="language-text">
178178
Select Language:&nbsp;
179-
</text>
179+
</span>
180180
<Select
181181
className="select-language-button"
182182
defaultValue={selectedItem}
@@ -206,15 +206,15 @@ export default function QuestionPage() {
206206
</div>
207207
<div className="session-details-text-div">
208208
<div className="session-details-text">
209-
<text className="session-headers">Start Time: </text>
209+
<span className="session-headers">Start Time: </span>
210210
01:23:45
211211
<br />
212-
<text className="session-headers">
212+
<span className="session-headers">
213213
Session Duration:{" "}
214-
</text>
214+
</span>
215215
01:23:45
216216
<br />
217-
<text className="session-headers">Matched with: </text>
217+
<span className="session-headers">Matched with: </span>
218218
John Doe
219219
</div>
220220
</div>

0 commit comments

Comments
 (0)