From fb9595e96f449dcee2a35e2cd2777000676d6e72 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:48:38 +0800 Subject: [PATCH 01/11] Make AI Chat remember past messages --- collab-service/app/controller/ai-controller.js | 12 +++++------- collab-service/app/model/repository.js | 12 ++++++------ frontend/components/collab/chat.tsx | 12 ++++++------ frontend/lib/api/openai/send-ai-message.ts | 11 +++++++---- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/collab-service/app/controller/ai-controller.js b/collab-service/app/controller/ai-controller.js index 338b76e248..5bdb8ab5fc 100644 --- a/collab-service/app/controller/ai-controller.js +++ b/collab-service/app/controller/ai-controller.js @@ -2,17 +2,15 @@ import { sendAiMessage } from "../model/repository.js"; // send ai message export async function sendAiMessageController(req, res) { - const { message } = req.body; - if (!message) { + const { messages } = req.body; + if (!messages) { return res.status(400).json({ error: "Message content is required" }); } - const data = await sendAiMessage(message); - const aiResponse = - data.choices?.[0]?.message?.content || "No response from AI"; + const returnMessage = await sendAiMessage(messages); - if (aiResponse) { - res.status(200).json({ data }); + if (returnMessage) { + res.status(200).json({ returnMessage: returnMessage }); } else { res.status(500).json({ error: "Failed to retrieve AI response" }); } diff --git a/collab-service/app/model/repository.js b/collab-service/app/model/repository.js index 99df6956f6..d78f1a2ca0 100644 --- a/collab-service/app/model/repository.js +++ b/collab-service/app/model/repository.js @@ -114,22 +114,22 @@ export async function getQuestionIdByRoomId(roomId) { } } -export async function sendAiMessage(message) { +export async function sendAiMessage(messages) { try { - console.log("sending to openai"); const response = await fetch("https://api.openai.com/v1/chat/completions", { method: "POST", headers: { - 'Content-Type': "application/json", - 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`, + "Content-Type": "application/json", + Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, }, body: JSON.stringify({ model: "gpt-3.5-turbo", - messages: [{ role: "user", content: message }], + messages: messages, }), }); const data = await response.json(); - return data; + const returnMessage = data.choices[0].message.content; + return returnMessage; } catch (error) { console.error("Error in sending AI message:", error); } diff --git a/frontend/components/collab/chat.tsx b/frontend/components/collab/chat.tsx index 41f11dfd5e..08f66204a7 100644 --- a/frontend/components/collab/chat.tsx +++ b/frontend/components/collab/chat.tsx @@ -12,7 +12,7 @@ import { useAuth } from "@/app/auth/auth-context"; import LoadingScreen from "@/components/common/loading-screen"; import { sendAiMessage } from "@/lib/api/openai/send-ai-message"; -interface Message { +export interface Message { id: string; userId: string; text: string; @@ -92,15 +92,15 @@ export default function Chat({ roomId }: { roomId: string }) { }); } else { setAiMessages((prev) => [...prev, message]); - const response = await sendAiMessage(newMessage); + setNewMessage(""); + const response = await sendAiMessage(aiMessages.concat(message)); const data = await response.json(); const aiMessage = { id: crypto.randomUUID(), userId: "ai", - text: - data.data.choices && data.data.choices[0]?.message?.content - ? data.data.choices[0].message.content - : "An error occurred. Please try again.", + text: data.returnMessage + ? data.returnMessage + : "An error occurred. Please try again.", timestamp: new Date(), }; setAiMessages((prev) => [...prev, aiMessage]); diff --git a/frontend/lib/api/openai/send-ai-message.ts b/frontend/lib/api/openai/send-ai-message.ts index 67af8f0330..511e31ba0e 100644 --- a/frontend/lib/api/openai/send-ai-message.ts +++ b/frontend/lib/api/openai/send-ai-message.ts @@ -1,8 +1,11 @@ import { collabServiceUri } from "@/lib/api/api-uri"; +import { Message } from "@/components/collab/chat"; -export const sendAiMessage = async (message: string) => { - console.log(`{collabServiceUri(window.location.hostname)}/send-ai-message`); - console.log(message); +export const sendAiMessage = async (messages: Message[]) => { + const apiMessages = messages.map((msg) => ({ + role: `${msg.userId === "ai" ? "assistant" : "user"}`, + content: msg.text, + })); const response = await fetch( `${collabServiceUri(window.location.hostname)}/collab/send-ai-message`, { @@ -10,7 +13,7 @@ export const sendAiMessage = async (message: string) => { headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ message: message }), + body: JSON.stringify({ messages: apiMessages }), } ); return response; From e197d3614487ae37e3b927cda5a459da3372961a Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:59:15 +0800 Subject: [PATCH 02/11] Fix strange error --- collab-service/app/controller/ai-controller.js | 3 +-- frontend/components/collab/chat.tsx | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/collab-service/app/controller/ai-controller.js b/collab-service/app/controller/ai-controller.js index 5bdb8ab5fc..ebe772d2a9 100644 --- a/collab-service/app/controller/ai-controller.js +++ b/collab-service/app/controller/ai-controller.js @@ -8,9 +8,8 @@ export async function sendAiMessageController(req, res) { } const returnMessage = await sendAiMessage(messages); - if (returnMessage) { - res.status(200).json({ returnMessage: returnMessage }); + res.status(200).json({ data: returnMessage }); } else { res.status(500).json({ error: "Failed to retrieve AI response" }); } diff --git a/frontend/components/collab/chat.tsx b/frontend/components/collab/chat.tsx index 08f66204a7..75de680139 100644 --- a/frontend/components/collab/chat.tsx +++ b/frontend/components/collab/chat.tsx @@ -98,9 +98,7 @@ export default function Chat({ roomId }: { roomId: string }) { const aiMessage = { id: crypto.randomUUID(), userId: "ai", - text: data.returnMessage - ? data.returnMessage - : "An error occurred. Please try again.", + text: data.data ? data.data : "An error occurred. Please try again.", timestamp: new Date(), }; setAiMessages((prev) => [...prev, aiMessage]); From 2736aee2f273648cc810c0f7392384994bce28a7 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:08:06 +0800 Subject: [PATCH 03/11] Move getQuestion to collab room Pass question into question display instead. Use Question schema instead of creating a new interface --- frontend/components/collab/collab-room.tsx | 48 ++++++++++++++++- .../components/collab/question-display.tsx | 51 ++----------------- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/frontend/components/collab/collab-room.tsx b/frontend/components/collab/collab-room.tsx index 474ee5c9ee..5cc87a7b4b 100644 --- a/frontend/components/collab/collab-room.tsx +++ b/frontend/components/collab/collab-room.tsx @@ -1,11 +1,51 @@ -import React from "react"; +"use client"; + +import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { X } from "lucide-react"; import Chat from "./chat"; import QuestionDisplay from "./question-display"; import CodeEditor from "./code-editor"; +import LoadingScreen from "@/components/common/loading-screen"; +import { getQuestion } from "@/lib/api/question-service/get-question"; +import { useAuth } from "@/app/auth/auth-context"; +import { getQuestionId } from "@/lib/api/collab-service/get-questionId"; +import { Question } from "@/lib/schemas/question-schema"; export default function CollabRoom({ roomId }: { roomId: string }) { + const auth = useAuth(); + const token = auth?.token; + + const [question, setQuestion] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function fetchQuestion() { + try { + // Call to the collab microservice to get questionId by roomId + const response = await getQuestionId(roomId); + const data = await response.json(); + + if (data.questionId) { + // Fetch the question details using the questionId + if (token) { + const questionResponse = await getQuestion(token, data.questionId); + const questionData = await questionResponse.json(); + setQuestion(questionData); + } else { + console.error("Token is not available"); + } + } + } catch (error) { + console.error("Error fetching question:", error); + } finally { + setLoading(false); + } + } + + fetchQuestion(); + }, [roomId]); + return (
@@ -17,7 +57,11 @@ export default function CollabRoom({ roomId }: { roomId: string }) {
- + {loading ? ( + + ) : ( + + )}
diff --git a/frontend/components/collab/question-display.tsx b/frontend/components/collab/question-display.tsx index 3cff6b4ba2..66b0e74f62 100644 --- a/frontend/components/collab/question-display.tsx +++ b/frontend/components/collab/question-display.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React from "react"; import { Card, CardContent, @@ -8,10 +8,7 @@ import { CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; -import LoadingScreen from "@/components/common/loading-screen"; -import { getQuestion } from "@/lib/api/question-service/get-question"; -import { useAuth } from "@/app/auth/auth-context"; -import { getQuestionId } from "@/lib/api/collab-service/get-questionId"; +import { Question } from "@/lib/schemas/question-schema"; const difficultyColors = { Easy: "bg-green-500", @@ -19,49 +16,7 @@ const difficultyColors = { Hard: "bg-red-500", }; -interface Question { - title: string; - categories: string; - complexity: keyof typeof difficultyColors; - description: string; -} - -export default function QuestionDisplay({ roomId }: { roomId: string }) { - const auth = useAuth(); - const token = auth?.token; - const [question, setQuestion] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - async function fetchQuestion() { - try { - // Call to the collab microservice to get questionId by roomId - const response = await getQuestionId(roomId); - const data = await response.json(); - - if (data.questionId) { - // Fetch the question details using the questionId - if (token) { - const questionResponse = await getQuestion(token, data.questionId); - const questionData = await questionResponse.json(); - setQuestion(questionData); - } else { - console.error("Token is not available"); - } - } - } catch (error) { - console.error("Error fetching question:", error); - } finally { - setLoading(false); - } - } - - fetchQuestion(); - }, [roomId]); - - if (loading) { - return ; - } +export default function QuestionDisplay({ question }: { question: Question | null }) { if (!question) { return
Question not found
; From 1247d6a2365dd24fc5c53317eafdf03e1ed97260 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 01:54:10 +0800 Subject: [PATCH 04/11] Add context to AI Chat Made AI Chat aware of user's code and question --- frontend/components/collab/chat.tsx | 101 ++++++++++++++++----- frontend/components/collab/code-editor.tsx | 11 ++- frontend/components/collab/collab-room.tsx | 7 +- frontend/lib/api/openai/send-ai-message.ts | 2 +- 4 files changed, 94 insertions(+), 27 deletions(-) diff --git a/frontend/components/collab/chat.tsx b/frontend/components/collab/chat.tsx index 75de680139..6cd84a3188 100644 --- a/frontend/components/collab/chat.tsx +++ b/frontend/components/collab/chat.tsx @@ -11,6 +11,7 @@ import { io, Socket } from "socket.io-client"; import { useAuth } from "@/app/auth/auth-context"; import LoadingScreen from "@/components/common/loading-screen"; import { sendAiMessage } from "@/lib/api/openai/send-ai-message"; +import { Question } from "@/lib/schemas/question-schema"; export interface Message { id: string; @@ -19,7 +20,15 @@ export interface Message { timestamp: Date; } -export default function Chat({ roomId }: { roomId: string }) { +export default function Chat({ + roomId, + question, + code, +}: { + roomId: string; + question: Question | null; + code: string; +}) { const auth = useAuth(); const own_user_id = auth?.user?.id; const [socket, setSocket] = useState(null); @@ -30,6 +39,31 @@ export default function Chat({ roomId }: { roomId: string }) { const [isConnected, setIsConnected] = useState(false); const lastMessageRef = useRef(null); + useEffect(() => { + const greeting = + "Hello! I am your AI assistant! You can ask me for help with the question or any other programming related queries."; + const greetingMessage = { + id: crypto.randomUUID(), + userId: "assistant", + text: greeting, + timestamp: new Date(), + }; + setAiMessages((prev) => [...prev, greetingMessage]); + }, []); + + useEffect(() => { + if (question) { + const context = `${question.title}: ${question.description}. Your job is to assist a student who is solving this problem. Provide hints and guide them through the problem solving process if they ask for it. Do not answer irrelevant questions, try to keep the student focussed on the task.`; + const systemMessage = { + id: crypto.randomUUID(), + userId: "system", + text: context, + timestamp: new Date(), + }; + setAiMessages((prev) => [...prev, systemMessage]); + } + }, [question]); + useEffect(() => { if (!auth?.user?.id) return; // Avoid connecting if user is not authenticated @@ -93,14 +127,23 @@ export default function Chat({ roomId }: { roomId: string }) { } else { setAiMessages((prev) => [...prev, message]); setNewMessage(""); - const response = await sendAiMessage(aiMessages.concat(message)); + const attachedCode = { + id: crypto.randomUUID(), + userId: "system", + text: `This is the student's current code now: ${code}. Take note of any changes and be prepared to explain, correct or fix any issues in the code if the student asks.`, + timestamp: new Date(), + }; + const response = await sendAiMessage( + aiMessages.concat(attachedCode).concat(message) + ); const data = await response.json(); const aiMessage = { id: crypto.randomUUID(), - userId: "ai", + userId: "assistant", text: data.data ? data.data : "An error occurred. Please try again.", timestamp: new Date(), }; + setAiMessages((prev) => [...prev, attachedCode]); setAiMessages((prev) => [...prev, aiMessage]); } @@ -114,23 +157,33 @@ export default function Chat({ roomId }: { roomId: string }) { }); }; - const renderMessage = (message: Message, isOwnMessage: boolean) => ( -
-
{message.text}
-
- {formatTimestamp(message.timestamp)} -
-
- ); + const renderMessage = ( + message: Message, + isOwnMessage: boolean, + isSystem: boolean + ) => { + if (isSystem) { + return null; + } else { + return ( +
+
{message.text}
+
+ {formatTimestamp(message.timestamp)} +
+
+ ); + } + }; if (!own_user_id) { return ; @@ -160,7 +213,7 @@ export default function Chat({ roomId }: { roomId: string }) {
{partnerMessages.map((msg) => - renderMessage(msg, msg.userId === own_user_id) + renderMessage(msg, msg.userId === own_user_id, false) )}
@@ -170,7 +223,11 @@ export default function Chat({ roomId }: { roomId: string }) {
{aiMessages.map((msg) => - renderMessage(msg, msg.userId === own_user_id) + renderMessage( + msg, + msg.userId === own_user_id, + msg.userId === "system" + ) )}
diff --git a/frontend/components/collab/code-editor.tsx b/frontend/components/collab/code-editor.tsx index c2fee0f63e..d4b2eef235 100644 --- a/frontend/components/collab/code-editor.tsx +++ b/frontend/components/collab/code-editor.tsx @@ -40,7 +40,13 @@ const languages: Record = { }, }; -export default function CodeEditor({ roomId }: { roomId: string }) { +export default function CodeEditor({ + roomId, + setCode, +}: { + roomId: string; + setCode: (value: string) => void; +}) { const monaco = useMonaco(); const [language, setLanguage] = useState("Javascript"); const [theme, setTheme] = useState("light"); @@ -139,6 +145,9 @@ export default function CodeEditor({ roomId }: { roomId: string }) { onMount={(editor) => { setEditor(editor); }} + onChange={(value) => { + setCode(value); + }} theme={theme === "dark" ? "vs-dark" : "light"} />
diff --git a/frontend/components/collab/collab-room.tsx b/frontend/components/collab/collab-room.tsx index 5cc87a7b4b..038ad561aa 100644 --- a/frontend/components/collab/collab-room.tsx +++ b/frontend/components/collab/collab-room.tsx @@ -18,6 +18,7 @@ export default function CollabRoom({ roomId }: { roomId: string }) { const [question, setQuestion] = useState(null); const [loading, setLoading] = useState(true); + const [code, setCode] = useState(""); useEffect(() => { async function fetchQuestion() { @@ -60,11 +61,11 @@ export default function CollabRoom({ roomId }: { roomId: string }) { {loading ? ( ) : ( - + )} - +
- +
); diff --git a/frontend/lib/api/openai/send-ai-message.ts b/frontend/lib/api/openai/send-ai-message.ts index 511e31ba0e..1b1522b3cc 100644 --- a/frontend/lib/api/openai/send-ai-message.ts +++ b/frontend/lib/api/openai/send-ai-message.ts @@ -3,7 +3,7 @@ import { Message } from "@/components/collab/chat"; export const sendAiMessage = async (messages: Message[]) => { const apiMessages = messages.map((msg) => ({ - role: `${msg.userId === "ai" ? "assistant" : "user"}`, + role: `${(msg.userId === "assistant" || msg.userId === "system") ? msg.userId : "user"}`, content: msg.text, })); const response = await fetch( From 42f0cc32fdce8369c6b627c61256a0c347498eb3 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 01:55:52 +0800 Subject: [PATCH 05/11] Run prettier fix --- frontend/components/collab/collab-room.tsx | 6 +++--- frontend/components/collab/question-display.tsx | 7 +++++-- frontend/lib/api/openai/send-ai-message.ts | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frontend/components/collab/collab-room.tsx b/frontend/components/collab/collab-room.tsx index 038ad561aa..7f7cddf120 100644 --- a/frontend/components/collab/collab-room.tsx +++ b/frontend/components/collab/collab-room.tsx @@ -61,11 +61,11 @@ export default function CollabRoom({ roomId }: { roomId: string }) { {loading ? ( ) : ( - + )} - + - + ); diff --git a/frontend/components/collab/question-display.tsx b/frontend/components/collab/question-display.tsx index 66b0e74f62..1ed97a35af 100644 --- a/frontend/components/collab/question-display.tsx +++ b/frontend/components/collab/question-display.tsx @@ -16,8 +16,11 @@ const difficultyColors = { Hard: "bg-red-500", }; -export default function QuestionDisplay({ question }: { question: Question | null }) { - +export default function QuestionDisplay({ + question, +}: { + question: Question | null; +}) { if (!question) { return
Question not found
; } diff --git a/frontend/lib/api/openai/send-ai-message.ts b/frontend/lib/api/openai/send-ai-message.ts index 1b1522b3cc..adf692d25f 100644 --- a/frontend/lib/api/openai/send-ai-message.ts +++ b/frontend/lib/api/openai/send-ai-message.ts @@ -3,7 +3,7 @@ import { Message } from "@/components/collab/chat"; export const sendAiMessage = async (messages: Message[]) => { const apiMessages = messages.map((msg) => ({ - role: `${(msg.userId === "assistant" || msg.userId === "system") ? msg.userId : "user"}`, + role: `${msg.userId === "assistant" || msg.userId === "system" ? msg.userId : "user"}`, content: msg.text, })); const response = await fetch( From db0a2684b6080ef41cbf4c604c2f727c186c9eca Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 02:18:47 +0800 Subject: [PATCH 06/11] Run prettier fix --- frontend/components/collab/question-display.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/components/collab/question-display.tsx b/frontend/components/collab/question-display.tsx index 1776ce9915..7694c85159 100644 --- a/frontend/components/collab/question-display.tsx +++ b/frontend/components/collab/question-display.tsx @@ -17,19 +17,17 @@ const difficultyColors = { Hard: "bg-red-500", }; - export default function QuestionDisplay({ roomId, className, date, - question + question, }: { roomId: string; className?: string; date?: Date; question: Question | null; }) { - if (!question) { return
Question not found
; } From 70ac0f212645a8d20865b12270489c44f060f008 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 02:21:48 +0800 Subject: [PATCH 07/11] Update welcome message --- frontend/components/collab/chat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/collab/chat.tsx b/frontend/components/collab/chat.tsx index 8863510707..93e10babdf 100644 --- a/frontend/components/collab/chat.tsx +++ b/frontend/components/collab/chat.tsx @@ -59,7 +59,7 @@ export default function Chat({ useEffect(() => { const greeting = - "Hello! I am your AI assistant! You can ask me for help with the question or any other programming related queries."; + "Hello! I am your AI assistant! You can ask me for help with the question or any other programming related queries while you are coding."; const greetingMessage = { id: uuidv4(), userId: "assistant", From d953fee652806d17e3e951bf46ea80ba856ce2fb Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 02:23:09 +0800 Subject: [PATCH 08/11] Resolve ESlint issues --- frontend/components/collab/question-display.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/components/collab/question-display.tsx b/frontend/components/collab/question-display.tsx index 7694c85159..1e0b80ffdf 100644 --- a/frontend/components/collab/question-display.tsx +++ b/frontend/components/collab/question-display.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React from "react"; import clsx from "clsx"; import { Card, @@ -18,7 +18,6 @@ const difficultyColors = { }; export default function QuestionDisplay({ - roomId, className, date, question, From a59143f4289a0f1930c18c62d4c2c218ba9f9b04 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 02:26:00 +0800 Subject: [PATCH 09/11] Provide fallback string in case of empty value --- frontend/components/collab/code-editor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/collab/code-editor.tsx b/frontend/components/collab/code-editor.tsx index b137124054..5f412971e8 100644 --- a/frontend/components/collab/code-editor.tsx +++ b/frontend/components/collab/code-editor.tsx @@ -147,7 +147,7 @@ export default function CodeEditor({ setEditor(editor); }} onChange={(value) => { - setCode(value); + setCode(value || ""); }} theme={theme === "dark" ? "vs-dark" : "light"} /> From b53140f3783a180e349e969fd517a510ec459a28 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 02:29:47 +0800 Subject: [PATCH 10/11] Remove roomId from questionDisplay --- frontend/components/collab/question-display.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/components/collab/question-display.tsx b/frontend/components/collab/question-display.tsx index 1e0b80ffdf..93ab1635c4 100644 --- a/frontend/components/collab/question-display.tsx +++ b/frontend/components/collab/question-display.tsx @@ -22,7 +22,6 @@ export default function QuestionDisplay({ date, question, }: { - roomId: string; className?: string; date?: Date; question: Question | null; From 026b83b88f41b42fcadf895e72d1974f3a676270 Mon Sep 17 00:00:00 2001 From: dylkaw <37286651+dylkaw@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:11:40 +0800 Subject: [PATCH 11/11] Shift question request back to question display Fix history by letting the question display handle question request --- frontend/components/collab/collab-room.tsx | 64 +++---------------- .../components/collab/question-display.tsx | 63 +++++++++++++++++- 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/frontend/components/collab/collab-room.tsx b/frontend/components/collab/collab-room.tsx index 67a4fe1726..5d160b5fac 100644 --- a/frontend/components/collab/collab-room.tsx +++ b/frontend/components/collab/collab-room.tsx @@ -1,64 +1,17 @@ "use client"; -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { Button } from "@/components/ui/button"; import { X } from "lucide-react"; import Chat from "./chat"; import QuestionDisplay from "./question-display"; import CodeEditor from "./code-editor"; -import LoadingScreen from "@/components/common/loading-screen"; -import { getQuestion } from "@/lib/api/question-service/get-question"; -import { useAuth } from "@/app/auth/auth-context"; -import { getQuestionId } from "@/lib/api/collab-service/get-questionId"; -import { Question } from "@/lib/schemas/question-schema"; -import { useToast } from "@/components/hooks/use-toast"; import Link from "next/link"; +import { Question } from "@/lib/schemas/question-schema"; export default function CollabRoom({ roomId }: { roomId: string }) { - const auth = useAuth(); - const token = auth?.token; - const { toast } = useToast(); - - const [question, setQuestion] = useState(null); - const [loading, setLoading] = useState(true); const [code, setCode] = useState(""); - - useEffect(() => { - async function fetchQuestion() { - try { - if (!auth || !auth.token) { - toast({ - title: "Access denied", - description: "No authentication token found", - variant: "destructive", - }); - return; - } - - // Call to the collab microservice to get questionId by roomId - const response = await getQuestionId(auth.token, roomId); - const data = await response.json(); - - if (data.questionId) { - // Fetch the question details using the questionId - if (token) { - const questionResponse = await getQuestion(token, data.questionId); - const questionData = await questionResponse.json(); - setQuestion(questionData); - } else { - console.error("Token is not available"); - } - } - } catch (error) { - console.error("Error fetching question:", error); - } finally { - setLoading(false); - } - } - - fetchQuestion(); - }, [roomId]); - + const [exposedQuestion, setExposedQuestion] = useState(null); return (
@@ -72,12 +25,11 @@ export default function CollabRoom({ roomId }: { roomId: string }) {
- {loading ? ( - - ) : ( - - )} - + +
diff --git a/frontend/components/collab/question-display.tsx b/frontend/components/collab/question-display.tsx index 93ab1635c4..98505f617a 100644 --- a/frontend/components/collab/question-display.tsx +++ b/frontend/components/collab/question-display.tsx @@ -1,5 +1,5 @@ "use client"; -import React from "react"; +import React, { useState, useEffect } from "react"; import clsx from "clsx"; import { Card, @@ -8,8 +8,13 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { getQuestion } from "@/lib/api/question-service/get-question"; +import { useAuth } from "@/app/auth/auth-context"; +import { getQuestionId } from "@/lib/api/collab-service/get-questionId"; +import { useToast } from "@/components/hooks/use-toast"; import { Badge } from "@/components/ui/badge"; import { Question } from "@/lib/schemas/question-schema"; +import LoadingScreen from "@/components/common/loading-screen"; const difficultyColors = { Easy: "bg-green-500", @@ -20,12 +25,64 @@ const difficultyColors = { export default function QuestionDisplay({ className, date, - question, + roomId, + setExposedQuestion, }: { className?: string; date?: Date; - question: Question | null; + roomId: string; + setExposedQuestion?: (question: Question) => void; }) { + const auth = useAuth(); + const token = auth?.token; + const { toast } = useToast(); + + const [question, setQuestion] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function fetchQuestion() { + try { + if (!auth || !auth.token) { + toast({ + title: "Access denied", + description: "No authentication token found", + variant: "destructive", + }); + return; + } + + // Call to the collab microservice to get questionId by roomId + const response = await getQuestionId(auth.token, roomId); + const data = await response.json(); + + if (data.questionId) { + // Fetch the question details using the questionId + if (token) { + const questionResponse = await getQuestion(token, data.questionId); + const questionData = await questionResponse.json(); + setQuestion(questionData); + if (setExposedQuestion) { + setExposedQuestion(questionData); + } + } else { + console.error("Token is not available"); + } + } + } catch (error) { + console.error("Error fetching question:", error); + } finally { + setLoading(false); + } + } + + fetchQuestion(); + }, [roomId]); + + if (loading) { + return ; + } + if (!question) { return
Question not found
; }