Skip to content

Faculty Assignments & Learner Submission

Status: draft LNO: L — assignments are the primary homework/grading loop. If this flow is broken, the core teach-assess-learn cycle doesn't close. Owners: @bhanu Last updated: 2026-04-12 Roles affected: Trainer (create, grade), Learner (submit, view results) Primary routes: /assignments, /assignments/new, /assignments/:id, /submissions Source of the ask: internal audit of trainer + learner panel on 2026-04-12. User explicitly flagged assignments as "not clean UX."

TL;DR

The assignment create flow is a 2,577-line monolith with 12 useState calls, no component split, and raw HTML elements (<input type="checkbox">) instead of DS primitives. The learner submission flow has no draft auto-save — if a learner's browser crashes or WiFi drops during a quiz, their answers are gone. The terminology drifts between "homework" (folder names, legacy routes) and "assignment" (API, i18n, UI labels) without acknowledgment. This doc proposes a phased rebuild: split the monolith, add draft persistence, and unify terminology.

Why this exists

Who asked for it

User (@bhanu) explicitly flagged assignments as having unclean UX during the session on 2026-04-12. Confirmed via code audit: CreateHomeworkPage/index.tsx is the single largest file in the frontend (2,577 LOC).

What user pain does it solve

Trainer (Dr. Anita): Opens "Create Assignment," sees a 3-step wizard (Info, Questions, Settings) crammed into one file. Fills everything out, clicks Create, and is redirected to the list with no confirmation, no "View Assignment" CTA, no preview of what learners will see. She doesn't know if it worked until she scrolls through the list.

Learner (Rahul): Opens a timed quiz on school WiFi. Answers 18 of 20 MCQs over 15 minutes. WiFi drops. Page refreshes. All 18 answers are gone — no auto-save, no localStorage draft, no recovery. He submits a blank quiz and gets 0%.

Cost of not doing it

  • Learners lose work. On school WiFi (common failure mode in Indian schools), this will happen regularly. Each incident destroys trust in the platform.
  • Trainers can't iterate. The monolithic create form can't be extended (AI question generation, rubric attachment, proctoring settings) without making the file even larger.
  • Terminology confusion compounds. Every new feature that references "homework" or "assignment" has to guess which word to use.

Validation

Moderate. The code audit is unambiguous (2,577 LOC, 12 useState, raw HTML). The learner-data-loss risk is a structural observation (no localStorage save in AssignmentDetailPage.tsx). No user interview has confirmed the data-loss scenario, but the code path is provable.

Personas

  • Dr. Anita, CSE Sem-4 lecturer. Creates weekly quizzes with 20 MCQs + 2 coding questions. Needs fast iteration — copy last week's quiz, tweak 5 questions, publish.
  • Rahul, 2nd-year CSE learner. Takes quizzes on his phone during the bus ride home. WiFi is spotty. Needs draft persistence.

ICP exclusions

  • K-12 trainers using simple homework (text-only, no proctoring) — their flow works adequately today; this rebuild is driven by college assessment complexity.
  • Platform admins — no admin-side changes.
  • Parents — parent view of assignments is read-only and not touched.

Outcomes for the user

  • Dr. Anita creates a 20-question quiz in under 5 minutes without wondering which step she's on.
  • Rahul's answers survive a WiFi drop. When he reopens the assignment, his 18 answers are restored.
  • The word "Assignment" appears everywhere — no more "homework" in URLs, folders, or service files.

Non-goals

  • We are not building a question bank with cross-assignment reuse in this phase.
  • We are not touching the AI evaluation / rubric grading flow (that's SubmissionsPage, a separate surface).
  • We are not renaming the backend homework endpoints — frontend terminology unification only.
  • We are not adding offline-first support (Service Worker, IndexedDB). localStorage auto-save is sufficient for Phase 1.

Mental model

Assignment (the thing a trainer creates)
  has: title, type (quiz/homework/test/essay/...), due date, time limit
  has: questions[] (MCQ, short answer, code, file upload, ...)
  has: settings (proctoring, shuffle, late submission, passing marks)
  targets: classes/sections (K-12) or programs/branches/levels (college)

Submission (the thing a learner creates)
  belongs to: one assignment
  has: answers[] (keyed by question ID)
  has: draft state (auto-saved to localStorage every 10s)
  has: submitted_at, score, feedback

Design decisions

Decision 1: Split CreateHomeworkPage into step components

Chose: Extract InfoStep, QuestionsStep, SettingsStep into CreateAssignmentPage/components/. Each step is its own file under 300 lines. Shared wizard state lives in a useAssignmentWizard hook (discriminated union for step + form data).

Why: 2,577 lines is unmaintainable. The wizard structure already exists (3 steps) but all code is inline. The pattern exists in CourseEditPage/ which correctly splits into step components.

Alternatives rejected: - Keep as one file, just add comments. Rejected: doesn't fix the maintainability problem. - Use React Hook Form with a single schema. Rejected for Phase 1: the form has complex conditional fields (K-12 vs college targeting, proctoring toggle) that are easier to reason about as separate step components.

Decision 2: localStorage auto-save for learner submissions

Chose: useEffect that saves answers state to localStorage every 10 seconds during an active attempt. On mount, check for existing draft and restore. Clear on successful submit.

Why: Rahul loses work when WiFi drops. This is a 15-line change that prevents the worst-case learner experience.

Alternatives rejected: - Server-side draft API. Rejected for Phase 1: requires backend changes and doesn't work offline. - IndexedDB via a library. Rejected: overkill for key-value answer storage.

Decision 3: Rename folders and service file to "assignment"

Chose: CreateHomeworkPage/CreateAssignmentPage/, services/homework.tsservices/assignments.ts. Import paths updated. Legacy /homework route already redirects to /assignments.

Why: The terminology drift is the same pattern that caused the courses/modules confusion. Fixing it now prevents compounding.

Alternatives rejected: - Leave folder names, just fix UI labels. Rejected: developers seeing CreateHomeworkPage will call the entity "homework" in new code.

Rollout plan

Phase 1 — Split monolith + draft auto-save

  1. Create pages/trainer/CreateAssignmentPage/ folder with index.tsx + components/InfoStep.tsx, QuestionsStep.tsx, SettingsStep.tsx.
  2. Extract useAssignmentWizard hook (owns step state + form data as discriminated union).
  3. Delete CreateHomeworkPage/ once the new folder is verified.
  4. Rename services/homework.tsservices/assignments.ts (re-export for backward compat if needed).
  5. Add localStorage auto-save to AssignmentDetailPage.tsx learner submission flow.
  6. Add beforeunload warning if learner has unsaved answers.
  7. Add post-create CTA: after trainer clicks Create, show a toast with "View Assignment" link instead of silent redirect.

Phase 2 — Proctoring hardening + per-question feedback

  • Fullscreen enforcement via Fullscreen API (not just CSS position: fixed).
  • Per-question score/feedback display for learners after grading.
  • Question pagination for 50+ question assignments (dots → grouped page buttons).

Success signals

  • Trainers create assignments without asking support "where did my assignment go?" after submit.
  • Zero learner reports of lost answers due to browser crash or WiFi drop.
  • Sean Ellis counterfactual: if we reverted the split + auto-save a week after shipping, trainers wouldn't notice the monolith change (it's internal), but learners WOULD notice if their answers stopped saving — "my quiz answers disappeared" is a specific, loud complaint.

Open questions

  • [ ] Should auto-save frequency be configurable (10s default) or fixed?
  • [ ] When restoring a draft, should the timer also restore (resume from where the learner left off) or restart?
  • [ ] The 22 assignment types in the enum — are all used? Can we prune to the 8 core types?

Changelog

  • 2026-04-12 — Doc created from trainer + learner panel audit findings. Source: code audit, not user interview. CreateHomeworkPage confirmed at 2,577 LOC / 12 useState. Learner auto-save gap confirmed in AssignmentDetailPage.tsx (no localStorage write path).

Appendix: Reference

Key files

  • apps/web/src/pages/trainer/CreateHomeworkPage/index.tsx (2,577 LOC) — the monolith to split
  • apps/web/src/pages/shared/AssignmentDetailPage.tsx (1,593 LOC) — learner submission flow, needs auto-save
  • apps/web/src/pages/trainer/SubmissionsPage/index.tsx (1,411 LOC) — trainer grading flow
  • apps/web/src/pages/shared/HomeworkPage/index.tsx (374 LOC) — list page, role dispatch
  • apps/web/src/services/homework.ts — exports assignmentsApi, rename target
  • apps/web/src/components/proctoring/ — 3 components, partially integrated