Add student questions feature design spec
This commit is contained in:
@@ -0,0 +1,159 @@
|
|||||||
|
# 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
|
||||||
Reference in New Issue
Block a user