From 40e48144d3c13f37d3efd7996f076d8c5703b6e7 Mon Sep 17 00:00:00 2001
From: Phineas Truong <56217067+phintruong@users.noreply.github.com>
Date: Fri, 3 Apr 2026 18:21:13 -0400
Subject: [PATCH 1/5] need testing
---
src/app/room/classChat/index.tsx | 18 +++
src/app/room/classChat/post/QuestionPost.tsx | 19 ++-
src/app/room/classChat/post/index.tsx | 3 +
src/socket/handlers/questionHandlers.ts | 118 +++++++++++++++++++
src/socket/index.ts | 2 +
src/socket/types.ts | 11 ++
6 files changed, 169 insertions(+), 2 deletions(-)
diff --git a/src/app/room/classChat/index.tsx b/src/app/room/classChat/index.tsx
index 5ba99a5..d5d35d3 100644
--- a/src/app/room/classChat/index.tsx
+++ b/src/app/room/classChat/index.tsx
@@ -225,6 +225,12 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) {
);
};
+ const onQuestionUnresolved = (payload: { id: string }) => {
+ setQuestions((prev) =>
+ prev.map((q) => (q.id === payload.id ? { ...q, isResolved: false } : q))
+ );
+ };
+
const onAnswerCreated = (payload: {
id: string;
questionId: string;
@@ -386,6 +392,7 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) {
socket.on("question:created", onQuestionCreated);
socket.on("question:updated", onQuestionUpdated);
socket.on("question:resolved", onQuestionResolved);
+ socket.on("question:unresolved", onQuestionUnresolved);
socket.on("question:deleted", onQuestionDeleted);
socket.on("answer:created", onAnswerCreated);
socket.on("answer:updated", onAnswerUpdated);
@@ -400,6 +407,7 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) {
socket.off("question:created", onQuestionCreated);
socket.off("question:updated", onQuestionUpdated);
socket.off("question:resolved", onQuestionResolved);
+ socket.off("question:unresolved", onQuestionUnresolved);
socket.off("question:deleted", onQuestionDeleted);
socket.off("answer:created", onAnswerCreated);
socket.off("answer:updated", onAnswerUpdated);
@@ -454,6 +462,13 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) {
setQuestions((prev) => prev.map((q) => (q.id === questionId ? { ...q, isResolved: true } : q)));
};
+ const handleUnresolve = (questionId: string) => {
+ if (!socket) return;
+ socket.emit("question:unresolve", { questionId });
+ // Optimistic update
+ setQuestions((prev) => prev.map((q) => (q.id === questionId ? { ...q, isResolved: false } : q)));
+ };
+
const handleSubmitAnswer = (questionId: string, content: string) => {
if (!socket) return;
socket.emit("answer:create", { questionId, content, isAnonymous: globalIsAnonymous });
@@ -565,6 +580,9 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) {
? () => handleResolve(q.id)
: undefined
}
+ onUnresolve={
+ isInstructor ? () => handleUnresolve(q.id) : undefined
+ }
canAnswer={canAnswerGlobal || q.user?.id === userId}
onSubmitAnswer={(content) => handleSubmitAnswer(q.id, content)}
onAnswerUpvote={handleAnswerUpvote}
diff --git a/src/app/room/classChat/post/QuestionPost.tsx b/src/app/room/classChat/post/QuestionPost.tsx
index 2b383dd..50aeba5 100644
--- a/src/app/room/classChat/post/QuestionPost.tsx
+++ b/src/app/room/classChat/post/QuestionPost.tsx
@@ -3,7 +3,7 @@
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
-import { MessageCircle, CheckCircle2, Trash2, ChevronDown, ChevronUp } from "lucide-react";
+import { MessageCircle, CheckCircle2, Undo2, Trash2, ChevronDown, ChevronUp } from "lucide-react";
import { Question, Post } from "@/utils/types";
import { UpvoteButton, renderUsername } from "./PostUtils";
@@ -111,6 +111,7 @@ export default function QuestionPost({
canAnswer = true,
onUpvote,
onResolve,
+ onUnresolve,
onDelete,
onSubmitAnswer,
children,
@@ -122,6 +123,7 @@ export default function QuestionPost({
canAnswer?: boolean;
onUpvote?: () => void;
onResolve?: () => void;
+ onUnresolve?: () => void;
onDelete?: () => void;
onSubmitAnswer?: (content: string) => void;
children?: React.ReactNode;
@@ -159,7 +161,7 @@ export default function QuestionPost({
const showThread = threadState !== "collapsed" && (visibleReplies.length > 0 || isReplying);
return (
-
+
{/* Question body */}
{post.content}
@@ -248,6 +250,19 @@ export default function QuestionPost({
)}
+ {onUnresolve && resolved && (
+
+ )}
+
{onDelete && (