diff --git a/src/app/api/courses/[courseId]/students/route.ts b/src/app/api/courses/[courseId]/students/route.ts index c18c9cb..b1932e8 100644 --- a/src/app/api/courses/[courseId]/students/route.ts +++ b/src/app/api/courses/[courseId]/students/route.ts @@ -366,8 +366,11 @@ export async function DELETE(request: NextRequest, { params }: RouteParams) { return NextResponse.json({ error: "Cannot remove the course professor." }, { status: 403 }); } - await prisma.courseEnrollment.delete({ + // Demote TA back to STUDENT rather than removing them from the course entirely. + // This preserves their enrollment so they stay in any active session. + await prisma.courseEnrollment.update({ where: { userId_courseId: { userId: target.id, courseId } }, + data: { role: "STUDENT" }, }); return NextResponse.json({ removed: utorid.trim().toLowerCase() }); diff --git a/src/app/api/sessions/[sessionId]/questions/route.ts b/src/app/api/sessions/[sessionId]/questions/route.ts index b46e398..56277a3 100644 --- a/src/app/api/sessions/[sessionId]/questions/route.ts +++ b/src/app/api/sessions/[sessionId]/questions/route.ts @@ -10,7 +10,6 @@ import { import { validateQuestionContent, validateVisibility, - checkQuestionRateLimit, validateSessionForQuestions, } from "@/lib/questionValidation"; import { getSessionMembership } from "@/lib/sessionService"; @@ -210,16 +209,7 @@ export async function POST(request: NextRequest, { params }: RouteParams) { return NextResponse.json({ error: sessionValidation.error }, { status: statusCode }); } - // 7. Check rate limit using shared validation - const isRateLimited = await checkQuestionRateLimit(authorId); - if (isRateLimited) { - return NextResponse.json( - { error: "Rate limit exceeded. Please wait before asking another question." }, - { status: 429 } - ); - } - - // 8. Create the question and record activity on the session atomically + // 7. Create the question and record activity on the session atomically const [question] = await prisma.$transaction([ prisma.question.create({ data: { diff --git a/src/app/api/sessions/[sessionId]/route.ts b/src/app/api/sessions/[sessionId]/route.ts index 6fc1831..a828def 100644 --- a/src/app/api/sessions/[sessionId]/route.ts +++ b/src/app/api/sessions/[sessionId]/route.ts @@ -52,7 +52,7 @@ export async function GET(_req: Request, { params }: RouteParams) { } } - return NextResponse.json({ status: session.status }); + return NextResponse.json({ status: session.status, courseId: session.courseId }); } catch (error) { console.error("[Sessions API] Failed to fetch session status:", error); return NextResponse.json({ error: "An error occurred." }, { status: 500 }); diff --git a/src/app/room/classChat/ChatHeader.tsx b/src/app/room/classChat/ChatHeader.tsx index 07ec92c..6513aa2 100644 --- a/src/app/room/classChat/ChatHeader.tsx +++ b/src/app/room/classChat/ChatHeader.tsx @@ -3,14 +3,15 @@ import { Input } from "@/components/ui/input"; import { useContext, useState } from "react"; import { - ArrowLeft, PanelRightClose, Users, GraduationCap, Search, X, ArrowBigRight, + UserPlus, } from "lucide-react"; +import ManageTAsModal from "./ManageTAsModal"; import { useMediaQuery } from "@/hooks/use-media-query"; import { SlideUpdateContext } from "../SlideUpdateContext"; import type { Role } from "@/utils/types"; @@ -67,114 +68,129 @@ export default function ChatHeader({ }: ChatHeaderProps) { const { sessionTitle } = useRoom(); const [isSearchExpanded, setIsSearchExpanded] = useState(false); + const [showTAModal, setShowTAModal] = useState(false); return ( -
-
- {isSearchExpanded ? ( -
-
- - onSearchChange(e.target.value)} - onBlur={() => { - if (!searchQuery) setIsSearchExpanded(false); - }} - /> - {searchQuery && ( - - )} -
- -
- ) : ( - <> -
- - {sessionTitle && ( -

- {sessionTitle} -

- )} -
- -
- )} +
+ +
+ ) : ( + <> +
+ + {sessionTitle && ( +

+ {sessionTitle} +

+ )} +
- {/* Answer mode toggle — professors only */} - {role === "PROFESSOR" && ( +
- )} - - Back - - -
- - )} - - + + {/* Answer mode toggle — professors only */} + {role === "PROFESSOR" && ( + + )} + {role === "PROFESSOR" && ( + + )} + + Back + + + + + )} + + + + {showTAModal && setShowTAModal(false)} />} + ); } diff --git a/src/app/room/classChat/ChatInput.tsx b/src/app/room/classChat/ChatInput.tsx index b7088a7..68eb018 100644 --- a/src/app/room/classChat/ChatInput.tsx +++ b/src/app/room/classChat/ChatInput.tsx @@ -59,51 +59,53 @@ export default function ChatInput({
-