V1 Web PWA · Surface walkthrough

Tara — course detail

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
9sections4 minread

On this page

Context. surface customer · domain tara · route /domains/tara/courses/[id] · auth signed-in · source apps/oshun/web/src/app/domains/tara/courses/[id]/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; 2026-06-29 targeted Playwright course-detail coverage added for shipped route anatomy, enrollment transition, section accordion, lesson overlays, quiz pass/fail scoring, missing-course fallback, and scoped axe scan. Evidence: apps/oshun/web/e2e/tara-course-detail.spec.ts

Purpose#

Dynamic course-detail surface in the /domains/tara/* namespace. Renders one Tara meditation course identified by the URL segment, with sections, lessons, enrollment flow, learning objectives, quiz interface, completion certificate, and per-lesson resources.

Entry points#

  • Course list / collections / search — surfaces under /domains/tara/* link here with the course id
  • Direct URL / bookmark — yes; params.id flows directly into TaraCourseDetailPage
  • Domain back-stackrouter.back() wired into onBack

Layout regions#

page.tsx is a 'use client' thin wrapper that reads params.id via useParams<{ id: string }>() and renders <TaraCourseDetailPage courseId={courseId} onBack={() => router.back()} />.

Inside TaraCourseDetailPage (TaraCourseDetail.tsx):

  • Header / back affordance — back button, course title
  • Format badgeFORMAT_COLORS[course.format] (daily / weekly / self- paced / scheduled / live) with the appropriate icon
  • Course meta — duration, lesson count, enrollment count, completion rate, average rating, difficulty
  • Hero CTA — Enrollment / Continue / Completed CTA reflects EnrollmentStatus (not-enrolled → enrolled → in-progress → completed)
  • Learning objectives — list of stated objectives
  • Section accordion — one accordion per TaraCourseSection with progress bar; expands to show TaraCourseLesson rows
  • Lesson row — icon by LESSON_TYPE_ICONS[lesson.type] (meditation / video / article / exercise / quiz / reflection / discussion), status by STATUS_COLORS[lesson.status] (locked / available / in-progress / completed)
  • Lesson resources panel — supporting materials for the active lesson
  • Reflection prompts — reflection cards
  • Quiz interface — multiple-choice / true-false with submit and review; scores produce a quiz-results card
  • Completion certificate — full-page certificate when the course is complete (Trophy icon)

States#

  • Course foundSIMULATED_COURSES.find(...) returns a record; hero + sections render
  • Course missing (unknown id) — friendly inline empty state renders with Course not found and the domain back affordance
  • Enrollment status: not-enrolled — enrollment CTA visible
  • Enrollment status: enrolled — local click transition enters enrolled before auto-advancing
  • Enrollment status: in-progress — "Continue where you left off" CTA with progress percent
  • Enrollment status: completed — certificate screen + share/download affordance is not route-reachable with current course fixtures
  • Lesson status branches — locked (no entry) / available (Play) / in-progress (Continue) / completed (CheckCircle2)
  • Quiz answered correctly / incorrectly — result card copy and score attributes verified for 0% fail and 100% pass
  • Course rating display — shows Star rating + average score
  • Reduced motion./fixtures emulates reduced motion and the scoped course-detail accessibility test runs against the settled route root

Interactions#

  • Back (button) — calls router.back() via onBack; direct header click still needs a browser assertion

Course hero#

  • Enroll (button, not-enrolled state) — flips state to enrolled, then local in-progress
  • Continue / Start lesson (button) — opens the next available lesson
  • Download certificate / Share (Download, Share2 icon buttons) — visible only after completion; completion fixture absent today
  • Resume CTA — uses local fixture progress today; persisted progress contract still needs BFF coverage

Section accordion#

  • Section header row (button) — toggles open/closed; chevron rotates
  • Per-section progress bar — non-interactive progress attributes verified

Lesson row#

  • Lesson click
    • When status === 'locked': aria-disabled="true" and does not open an overlay
    • When status === 'available' | 'in-progress': opens the lesson resources panel
    • When status === 'completed': opens the completed quiz for review/retry

Quiz#

  • Multiple-choice options — radio-style selection
  • True/false options — two-option selection
  • Submit (button) — scores and reveals results
  • Retry — no explicit retry button; re-opening a completed quiz starts a fresh attempt and is browser-covered

Resources / reflection prompts#

  • Resource link — current resource/download/share controls are display-only disabled buttons until real downloads/shares are wired
  • Reflection prompt — no available reflection lesson exists in current fixtures; all reflection rows are locked

Data & contracts#

  • Reads:
    • SIMULATED_COURSES from @/lib/tara/tara-simulation-data
    • Content types from @/lib/tara/content-types: TaraCourse, TaraCourseSection, TaraCourseLesson, LessonType, LessonStatus, CourseFormat, EnrollmentStatus
  • Writes: enrollment + progress state are local to this component today
  • Realtime: None.
  • Caching: client-only
  • Auth/role check: shell middleware
  • Route param: params.id: string — no decode in the page wrapper

Current E2E evidence#

  • apps/oshun/web/e2e/tara-course-detail.spec.ts opens /domains/tara/courses/tara-course-001, verifies the in-progress course anatomy, stats, objectives, teacher card, section progress, lesson statuses, disabled resource actions, section toggling, failed quiz scoring, passed quiz scoring, and unknown-course fallback.
  • The same spec opens /domains/tara/courses/tara-course-003, verifies the not-enrolled state, clicks enroll, observes the local enrolledin-progress transition, and opens the first available lesson.
  • The scoped accessibility test runs axe against [data-tara-course-detail="tara-course-001"] under reduced motion.
  • apps/oshun/web/e2e/tara-teacher-pages.spec.ts covers a real teacher-profile course link into tara-course-001 and browser back to the profile.

Cross-references#

Open questions / known gaps#

  • Confirm the BFF endpoint that hydrates real course content; currently SIMULATED_COURSES is local fixture data
  • Document the persistence target for enrollment status and lesson progress (client vs. BFF)
  • Verify how the certificate share / download interacts with the user's Library — should completed courses surface there automatically? Current fixtures do not expose a completed course state.
  • Confirm whether the friendly inline missing-course state is the intended product behavior or whether this route should use a Next not-found page.
  • Add a fixture or harness for an available reflection lesson if the reflection journal hand-off should be route-tested before BFF content exists.