Skip to content

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

  1. 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".
  2. Subject picker. Single-select chips. Next is disabled until one is selected. (Subject list below.)
  3. 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.
  4. 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.
  5. Test. The existing MockTest bubble 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 false to user_learning_profiles. Existing rows default false, so legacy users hit the wizard once.
  • Profile endpoint. GET /api/v1/me/learning-profile returns has_seen_test_walkthrough; PATCH /api/v1/me/learning-profile accepts { has_seen_test_walkthrough: true }, idempotent.
  • Upload. Reuse /api/v1/uploads (chat attachments). The wizard posts files there, gets file_id[], and passes them plus subject to generation.
  • Generation. POST /api/v1/mock-tests/from-materials with body { subject, file_ids[], grade_level } returns an SSE stream emitting one phase event per step and a final complete event carrying { mock_test_id, questions[] }. It extends MockTestService.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 same MockTest model 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.