Test Prep Wizard¶
A guided first-run flow for free B2C learners who land on the AI Tutor with intent practice. Instead of a generic "what do you want to practice?" chat input, a wizard walks the learner through a 5-step flow (overview → subject → material upload → generation → test), then drops them into the mock-test surface. It shows once per learner; re-entries skip straight to test generation.
How it works¶
The wizard intercepts the chat empty-state only when all of these hold:
user.role === 'b2c_user'
AND profile.has_seen_test_walkthrough === false
AND seededIntent === 'practice'
AND no existing messages in this chat
If any is false, the existing empty-state renders instead.
ChatEngine.tsx already gates the empty-state by seededIntent. When the guard passes it renders <TestPrepWizard onComplete={enterChatWithMockTest} />; enterChatWithMockTest injects the SSE-completed mock test as the first assistant message. The wizard sets has_seen_test_walkthrough = true once the learner reaches the test screen. State lives only for the wizard lifetime; nothing is persisted client-side.
The five screens¶
- Overview. Full-bleed inside the chat surface. Explains the loop: Practice ("see where you stand"), Review ("understand the why"), Study Guide ("a recap of what to work on next"). CTA: "Let's start".
- Subject picker. Single-select chips. Next is disabled until one is selected. (Subject list below.)
- Add study materials. Upload files (PDF, JPG, PNG, DOCX; max 4 files, 10MB each) so the generator can anchor questions on the learner's real material. Optional with a strong CTA; "Skip intro" ghost button on the left, "Next" on the right.
- Generating. A phased checklist (one row highlights at a time, completed rows check off) driven by SSE events: Understanding your material → Scanning your files to find key topics → Refining the details → Personalizing your practice → Final touches.
- Test. The existing
MockTestbubble surface inside chat, no wizard chrome.
Back navigation works only between overview, subject, and materials; generating and test are non-reversible.
Subjects¶
English · Mathematics · Social Studies · Business · History · Health · Geography · Biology · Physics · Chemistry · Computers and Technology · Arts · World Languages · Spanish · French · German · Advanced Placement (AP) · SAT · Medicine · Law · Engineering
Backend¶
- Profile column. Migration adds
has_seen_test_walkthrough boolean NOT NULL DEFAULT falsetouser_learning_profiles. Existing rows default false, so legacy users hit the wizard once. - Profile endpoint.
GET /api/v1/me/learning-profilereturnshas_seen_test_walkthrough;PATCH /api/v1/me/learning-profileaccepts{ has_seen_test_walkthrough: true }, idempotent. - Upload. Reuse
/api/v1/uploads(chat attachments). The wizard posts files there, getsfile_id[], and passes them plussubjectto generation. - Generation.
POST /api/v1/mock-tests/from-materialswith body{ subject, file_ids[], grade_level }returns an SSE stream emitting onephaseevent per step and a finalcompleteevent carrying{ mock_test_id, questions[] }. It extendsMockTestService.generate_from_materials(): resolve files to text via the existing OCR/extract pipeline, call the LLM with material context plus subject, emit phase markers, and return the sameMockTestmodel so the downstream review/grading flow is unchanged. - Telemetry.
test_walkthrough_started,test_walkthrough_file_attached,test_walkthrough_generation_completed.
Where it lives¶
Route: /ai-tutor (entered via intent=practice seed; the wizard overlays the chat empty-state).
Frontend: apps/web/src/pages/shared/AITutorPage/components/TestPrepWizard/ (orchestrator + steps/ + constants.ts + useWizard.ts) and the apps/web/src/services/test-prep/ hook (useGenerateFromMaterials over SSE). i18n keys under b2c.testPrep.* in apps/web/src/i18n/locales/en/b2c.json.