08 — Form Specifications (Homework Module)
- 1. Create Homework Form —
POST /api/v1/homework(homework.dto.ts:4-33) - 2. Edit Homework Form —
PATCH /api/v1/homework/:id(homework.dto.ts:35-58) - 3. Submission Form —
POST /api/v1/homework/:id/submit(submission.dto.ts:4-17) - 4. Grade Form —
PATCH /api/v1/homework/:id/submissions/:submissionId/grade(submission.dto.ts:19-26) - Form-level rules (all)
- Client-side error priority (all forms)
Every form field-by-field. Validation mirrors class-validator decorators exactly from
src/modules/homework/dto/*.ts; messages follow theVALIDATION_ERROR(400) envelope with per-fielddetails(http-exception.filter.ts:27-35,103-108). Client validates inline then submits; server 400 shadows client.
1. Create Homework Form — POST /api/v1/homework (homework.dto.ts:4-33)
| # | Field | Label | Keyboard | Validation (server) | Client UX |
|---|---|---|---|---|---|
| 1 | classId | Class | — | @IsMongoId() required | AppDropdown from Academics; required; immutable after create |
| 2 | subjectId | Subject | — | @IsMongoId() required | AppDropdown (filtered by class where known); immutable after create |
| 3 | teacherId | Teacher | — | @IsMongoId() required | hidden — filled from profile (server trusts body; OQ-9 note in 01) |
| 4 | title | Title | text | @IsString() required | maxLength 200 (client), autofocus, TextInputAction.next |
| 5 | description | Description | multiline | @IsOptional() @IsString() | 4–6 line field; "Markdown supported" helper (rendered via AppMarkdownViewer) |
| 6 | dueDate | Due date | — | @IsDateString() required | AppDatePicker; client min = today; format locale-aware; default time 23:59 local |
| 7 | attachments | Attachments | — | @IsOptional() (string[]) | AppAttachmentUploader (uploads happen before submit; ids sent) |
Server 400 mapping: class-validator errors arrive as
error: { code: 'VALIDATION_ERROR', details: [{ message }] } — map to fields by
trailing field name heuristics where details[].message lacks field ids
(http-exception.filter.ts:103-108); always also show the banner message.
Submit: button "Assign homework" → loading → 201 → detail + snackbar.
Errors: 5xx → AppErrorState keeping the form; offline → blocked, banner.
2. Edit Homework Form — PATCH /api/v1/homework/:id (homework.dto.ts:35-58)
| # | Field | Required | Server validation | Client UX |
|---|---|---|---|---|
| 1 | title | no | @IsOptional() @IsString() | prefilled; empty string sent → validation ok, doc updated |
| 2 | description | no | @IsOptional() @IsString() | prefilled |
| 3 | attachments | no | @IsOptional() | list diff; add/remove before PATCH (full replace — server $sets whole array, homework.service.ts:57) |
| 4 | dueDate | no | @IsOptional() @IsDateString() | date picker; client min = today (moving a due date to the past is possible server-side; flag with helper text) |
| 5 | status | no | @IsOptional() @IsString() | AppDropdown active/closed (schema enum homework.schema.ts:33; invalid string → 400 enum cast error → treat as validation) |
- Immutable:
classId,subjectId,teacherIdare not in the DTO — fields disabled in the edit form with note "Class/subject cannot be changed after assignment". - Submit sends only changed fields (
changes[]echoed inHomeworkUpdatedevent payload,homework.service.ts:65); success → detail refresh. - 404 → empty state; 400 → field errors.
3. Submission Form — POST /api/v1/homework/:id/submit (submission.dto.ts:4-17)
| # | Field | Label | Keyboard | Validation (server) | Client UX |
|---|---|---|---|---|---|
| 1 | studentId | Student | — | @IsMongoId() required | hidden — from profile; the only identity the server trusts (no JWT-sub binding, OQ-9/01) |
| 2 | remarks | Note to teacher | multiline | @IsOptional() @IsString() | optional; placeholder "Add a note (optional)"; maxLength 2000 (client) |
| 3 | attachments | Attachments | — | @IsOptional() (string[]) | AppAttachmentUploader; at least one of remarks/attachments not required by server — allow empty submission (server accepts; client keeps a confirm) |
Flow: submit → button spinner → 201 submission doc → success view → detail. Errors:
- 409
DUPLICATE_RESOURCE"Already submitted." (homework.service.ts:92) → navigate to detail +AppBanner(info)(not an error state). - 404 → homework removed.
- 400 → field errors; 5xx → keep form.
- Late due date: inline
AppBanner(warning)"The due date has passed" — submission still allowed (server accepts; OQ-1).
4. Grade Form — PATCH /api/v1/homework/:id/submissions/:submissionId/grade (submission.dto.ts:19-26)
| # | Field | Label | Keyboard | Validation (server) | Client |
|---|---|---|---|---|---|
| 1 | marks | Marks | number | none — no decorator (submission.dto.ts:20-21) | required, numeric, 0 ≤ marks ≤ maxMarks (client default 100, org-configurable); hint "Out of {max}" |
| 2 | remarks | Feedback | multiline | @IsOptional() @IsString() | optional; maxLength 2000 (client) |
- Server will accept negative/absurd marks (OQ-4) — client is the only guard today; document server-side limit addition as pending.
- Regrade: if
status='graded'already, show existing values +AppBanner(warning)"This overwrites the previous grade" + button "Save new grade" (server overwrites and re-emitsHomeworkGraded,homework.service.ts:127-143). - Success → snackbar "Grade saved" + row updates from server doc
(
marks, remarks, status:'graded', gradedAt). - Errors: 404 "Submission not found." (
homework.service.ts:126) → back+refresh; 400 → field errors; 5xx → keep typed values + retry.
Form-level rules (all)
- Double-submit: disabled while pending (00-shared/08 §6).
- Optimistic: no optimistic writes for create/submit/grade — each is server-confirmed; the submission 409 handler is the only "local success" path (00-shared/07 §9).
- Undo: delete homework → snackbar "Deleted" with no UNDO (soft-delete is irreversible from the client; there is no restore endpoint) — confirm dialog instead (00-shared/05 §5). Attachment removal inside a form = UNDO via snackbar (4 s).
- Abandonment: create/edit forms preserve drafts locally (
(proposed)shared_preferences); back from create → "Discard draft?" dialog. - Keyboard:
.nextsequence, last.done;Ctrl/Cmd+Entersubmits on desktop. - Error copy: from
messageof envelope for business 4xx only; codes for the rest (00-shared/07 §11).
Client-side error priority (all forms)
- 400 VALIDATION → field.
- 404 RESOURCE_NOT_FOUND → empty state / refresh.
- 409 DUPLICATE_RESOURCE → info state (submission) / inline (create race).
- 429 RATE_LIMITED → countdown (uploads count toward
api100/min tier, 00-shared/07 §4). - 5xx → AppErrorState + requestId.