# Student Questions — Design Spec _Created: 20260519_ ## Overview A support-chat feature inside the LMS. Students ask questions, school staff (admin/curator) answers. Each question is a threaded conversation with open/closed status. Includes file attachments and email notifications for all parties. Also in scope: email notifications for homework submissions (new + student updates). --- ## Data Model ### StudentQuestion ``` id String @id @default(cuid()) userId String -- student who created it courseId String? -- optional course context title String status QuestionStatus @default(OPEN) -- OPEN | CLOSED closedAt DateTime? closedById String? -- admin/curator who closed createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User course Course? messages StudentQuestionMessage[] ``` ### StudentQuestionMessage ``` id String @id @default(cuid()) questionId String authorId String text String files String[] -- S3 paths: questions/{questionId}/{messageId}/{filename} isRead Boolean @default(false) createdAt DateTime @default(now()) question StudentQuestion author User ``` ### QuestionStatus (enum) ``` OPEN CLOSED ``` --- ## Routes ### Student | Route | Description | |---|---| | `(student)/questions` | List of own questions with unread indicators | | `(student)/questions/new` | Form to create a new question | | `(student)/questions/[id]` | Thread view — read messages + reply | ### Admin / Curator | Route | Description | |---|---| | `admin/questions` | Split-view: question list left, thread right | | `curator/questions` | Same split-view (curators have same access as admins here) | --- ## UI Behaviour ### Student — Questions List (`/questions`) - Header: "Мои вопросы" + "+ Задать вопрос" button (→ `/questions/new`) - Each row: title, message count, last activity, status badge (ОТКРЫТ / ЗАКРЫТ) - Unread indicator: black dot + "Новый ответ от школы" when school replied since last student visit - Closed questions: dimmed (opacity 0.7), grey badge - Active (unread) questions: bold border, bold title ### Student — Thread (`/questions/[id]`) - Header: question title, created date, status, "← Все вопросы" link - Message bubbles: student messages left (#E8E8E0), school messages right (#F5F5F0 + green border #E8F0D8) - New school message: bold label "🔵 новое" in timestamp - File attachments shown inline under message text (📎 filename · size) - Reply form at bottom: textarea + attach button + send button - Attachment types: jpg, png, pdf, md · max 10 MB - Student CAN reply to closed questions (creates new message, does NOT reopen question) ### Admin/Curator — Split View (`/admin/questions`, `/curator/questions`) - Left panel (45%): tab filter "Открытые / Закрытые", question list sorted by last activity - Unread: red dot, green-tinted background, bold student name - Right panel (55%): selected thread with full message history + reply form + "✓ Закрыть вопрос" button - Only admin/curator can close a question - Closing a question does NOT prevent further messages --- ## Notifications ### → School (admin + all curators) | Trigger | Channel | |---|---| | New question created | Email + admin sidebar badge (count of unread questions) | | Student adds message to existing question | Email | ### → Student | Trigger | Channel | |---|---| | Admin/curator replies to question | Email | ### Admin Badge - Sidebar badge shows count of questions with unread messages (school hasn't seen yet) - Separate from homework badge ### Email for Homework (added to scope) | Trigger | Recipient | |---|---| | New HomeworkSubmission created | Admin + all curators | | Student updates existing submission (adds text/file) | Admin + all curators | --- ## File Storage - Path pattern: `questions/{questionId}/{messageId}/{filename}` - Reuse existing S3 upload infrastructure (`src/lib/s3.ts`) - Allowed: jpg, png, pdf, md - Max size: 10 MB per file - No limit on number of files per message (reasonable: 5) --- ## Read Tracking - `isRead` flag per message, set to `true` when the OTHER party opens the thread - Student opens `/questions/[id]` → all school messages in that thread marked `isRead = true` - Admin/curator opens a question in split-view → all student messages marked `isRead = true` - Admin badge recalculates on each page load (count questions where latest student message is unread) --- ## API Routes ``` POST /api/questions -- create question GET /api/questions -- list own questions (student) or all (admin/curator) GET /api/questions/[id] -- get question + messages POST /api/questions/[id]/messages -- add message + files PATCH /api/questions/[id]/close -- close question (admin/curator only) POST /api/upload/question-file -- upload attachment, returns S3 path ``` --- ## Out of Scope (this iteration) - Question categories / tags - Assigning question to a specific curator - Email threading (reply-to email to answer) - Push/browser notifications - Question templates