03 — User Journeys (Homework Module)
- 1. Teacher creates homework with attachment (PLAN.md 6.1)
- 2. Student views my-class homework (PLAN.md 6.2)
- 3. Student submits homework (PLAN.md 6.3)
- 4. Teacher grades + feedback (PLAN.md 6.4)
- 5. Edit / delete homework (PLAN.md 6.5)
- 6. Late submission handling
- 7. Parent sees pending / grade (read-only)
- 8. Cross-cutting
End-to-end journeys computed from
homework.controller.ts,homework.service.ts,files.controller.ts,event-queue-map.tsandPLAN.md §6.1–6.5. Each journey: entry, intent, decision points, system responses, loading, failures, recovery, exit, abandonment, offline.(planned)/(forward-looking)marks per global rules.
1. Teacher creates homework with attachment (PLAN.md 6.1)
entry: Homework tab → FAB "New homework"; intent: assign work to a class
sequenceDiagram
actor T as Teacher
participant F as CreateFormScreen
participant R as HomeworkRepository (client)
participant FILE as POST /files/upload
participant API as POST /api/v1/homework
participant Q as BullMQ in-app queue
T->>F: class, subject, title, description, dueDate, attach file
F->>FILE: multipart upload (progress %)
FILE-->>F: file record {_id, originalName, size, mimeType} (files.service.ts:27-46)
F->>R: submit {teacherId, classId, subjectId, title, description?, attachments:[_id], dueDate}
R->>API: POST /api/v1/homework (envelope data = homework doc)
API-->>R: 201 homework doc (status 'active', assignedDate now)
API->>Q: HomeworkCreated {homeworkId, classId} (homework.service.ts:34-41)
R-->>F: success → navigate detail
F-->>T: "Homework assigned" snackbar
- Decision point: due date picker min = today (client-side; server only validates
IsDateString,homework.dto.ts:31-32). - Attachments: upload first via FilesModule, then reference
_idinattachments[]. Upload is a separate request — a failure mid-upload must not create the homework. - Failure: 400
VALIDATION_ERROR(missingtitle/dueDate/MongoIds,homework.dto.ts:4-33) → field errors; 5xx →AppErrorState+ retry (form state kept). - Exit: success → detail screen; abandonment → draft resume (client memo,
(proposed)). - Offline: creation blocked (write queue not defined for homework create), attachment
upload queued with retry per
00-shared/07 §10.
2. Student views my-class homework (PLAN.md 6.2)
entry: Homework tab; intent: see what's due and my submission status
sequenceDiagram
actor S as Student
participant P as Student profile (Students module)
participant L as HomeworkListScreen
participant API as GET /api/v1/homework/class/:classId
S->>L: open Homework tab
L->>P: my classId (cached profile)
L->>API: GET /homework/class/{classId}
API-->>L: data[] sorted dueDate desc (homework.repository.ts:20)
L-->>S: cards: title, subject, due date, status badge, my submission state
- No dedicated student endpoint — classId resolution from the profile is the OQ-6
workaround (PLAN.md:67 lists
GET /api/v1/homeworkas intended; not implemented). - Per-card my-state: client cross-checks against
GET /homework/:id/submissions(only feasible for a single homework; full per-student state is(planned)— OQ-6). - Failure: 404 →
AppEmptyState; 5xx →AppErrorState+ retry; pull-to-refresh. - Loading:
AppSkeleton(list); cache TTL 5 min (volatile — due dates change).
3. Student submits homework (PLAN.md 6.3)
entry: homework detail → "Submit" (only if not already submitted)
sequenceDiagram
actor S as Student
participant D as HomeworkDetailScreen
participant R as HomeworkRepository
participant FILE as POST /files/upload
participant API as POST /api/v1/homework/:id/submit
S->>D: open homework detail, compose remarks + attach file
D->>FILE: upload (progress, retryable)
FILE-->>D: file record id
D->>R: submit {studentId, remarks?, attachments?}
R->>API: POST /api/v1/homework/{id}/submit
API-->>R: 201 submission doc {status:'submitted', submittedAt now} (homework.service.ts:93-98)
API->>Q: HomeworkSubmitted {homeworkId, studentId, submissionId} (homework.service.ts:99-110)
R-->>D: success → detail shows "Submitted" state
D-->>S: "Submitted" confirmation + lightImpact
- Exactly-once: double-tap / retry → second call returns 409
DUPLICATE_RESOURCE"Already submitted." (homework.service.ts:92) — client maps to "Already submitted" info state, not an error. - Submit button disabled permanently after success (server truth; no optimistic
write — the doc id comes from the server,
00-shared/07 §9). - Failure: 404 homework deleted meanwhile →
RESOURCE_NOT_FOUNDempty state; network loss mid-upload → upload pending/retry, no silent corruption (10 §2). - Offline: submit blocked; guidance + draft kept locally (offline queue
(planned)).
4. Teacher grades + feedback (PLAN.md 6.4)
entry: homework detail → "Submissions" tab → tap student row → grade sheet
sequenceDiagram
actor T as Teacher
participant G as GradingSheetScreen
participant R as HomeworkRepository
participant API as PATCH /api/v1/homework/:id/submissions/:submissionId/grade
T->>G: open submission, view attachments + remarks
G->>R: grade {marks, remarks?}
R->>API: PATCH …/grade
API-->>R: 200 updated submission {status:'graded', gradedAt, marks, remarks}
API->>Q: HomeworkGraded {homeworkId, submissionId, marks} (homework.service.ts:136-143)
R-->>G: row flips to "Graded" (marks visible)
G-->>T: snackbar "Graded" + advance to next ungraded row (proposed)
- Regrade: grading an already-graded submission overwrites and emits another
HomeworkGraded(OQ-2) — confirm dialog on regrade ("This will overwrite the existing grade"). - Validation: client enforces
marks ≥ 0and ≤ max marks (configurable; server has no decorator —submission.dto.ts:20-21, OQ-4). - Failure: 404 "Submission not found." (
homework.service.ts:126) → row refresh; network loss → grade sheet keeps typed values, retry offered. - No optimistic grading (side effect + notification event): server-confirmed only.
5. Edit / delete homework (PLAN.md 6.5)
entry: homework detail → menu → Edit / Delete
sequenceDiagram
actor T as Teacher
participant D as HomeworkDetailScreen
participant API as PATCH /api/v1/homework/:id | DELETE
T->>D: Edit → form prefilled (title, description, attachments, dueDate, status)
D->>API: PATCH /homework/{id} (only title, description, attachments, dueDate, status)
API-->>D: 200 updated doc; HomeworkUpdated {homeworkId, changes[]} → in-app (event-queue-map.ts:23)
T->>D: Delete → confirm dialog
D->>API: DELETE /homework/{id}
API-->>D: 200 {message:"OK"}; HomeworkDeleted → audit-write queue (event-queue-map.ts:26)
D-->>T: back to list; removed row (server-confirmed, no optimistic delete)
- Immutable fields:
classId,subjectId,teacherIdare not inUpdateHomeworkDto(homework.dto.ts:35-58) — form disables them after create. - Delete is soft (
base.repository.ts:68-74);GET /homework/class/:classIdwill no longer return it (isDeleted filter). Submissions are not deleted (no cascade, OQ-1/01). - Failure: 404 if already removed (refresh list); offline → blocked.
6. Late submission handling
entry: student submits after dueDate (server allows — OQ-1)
- Server accepts late submissions;
submittedAtis server-set (homework.service.ts:96). - Client derives
isLate = submittedAt > dueDateafter the response and shows atertiarybadge "Late · 2d" on the submission row (no server flag exists — the badge is client-computed,(forward-looking)pending a serverisLatefield). - Grading sheet highlights late rows (
AppBadgewarning) so the teacher can apply policy. - Open question (OQ-1): when the overdue scheduler lands (Homework.md:60), late-rejection or late-marking becomes server-authoritative — client must render whatever the server returns, never block submission client-side.
7. Parent sees pending / grade (read-only)
entry: notification deep link (planned) or child's device — no parent API today (OQ-5)
(planned)GET /homework/class/:classIdread-only +GET /homework/:id/submissionsfor the child's row (parent → student linkage lives in the Students module).- Today: parent sees homework activity only through in-app notifications
(planned — OQ-8); deep linkstudylyon://homework/:id(00-shared/05 §4).
8. Cross-cutting
| Entry | Behavior | Status |
|---|---|---|
Deep link studylyon://homework/:id | opens detail (role-gated actions) | (forward-looking) client |
| Push "homework graded" | opens grade feedback | (planned) push infra (00-shared/12 B3) |
| Notification → homework | HomeworkGraded etc. become in-app notifications | (planned) — enum gap OQ-8 |
Abandonment & exit rules: create form → back = draft prompt; grade sheet → back keeps typed values until dismissed; offline → list from cache + banner; permission denial (role-gated UI) → controls hidden, not errors.