Skip to content

Learner Learning Experience

The learner consumption flow: course cards with progress bars, lesson reading with TipTap content, a "Mark Complete" button that awards XP with a confetti modal, and prev/next lesson navigation. This doc covers the gaps that keep it from feeling like a genuine learning hub: dashboard actionability, mobile lesson navigation, and real gamification data.

The Continue-learning proposal here folded into the /learn home in student-guided-ux.md. The mobile-TOC-as-drawer and achievement-wiring work remain valid and ship independently.

How it works

The core journey is structurally sound (courses → lessons → mark complete → XP). Three gaps remain:

  1. Passive dashboard. It shows stats but no actionable CTA. Assignments render as static <div>s, not links, and there's no "Continue where you left off" widget. Resuming a half-finished lesson takes 5 clicks across 2 page loads.
  2. TOC hidden on mobile. The lesson Table of Contents uses hidden lg:block, so phone users can't jump to a section and scroll through the whole lesson instead.
  3. Mocked achievements. Badges read from hardcoded fixtures, not real progress, so the progress bars never move with the learner's activity.

The fixes:

  • Continue Learning widget. A ContinueLearningWidget on the learner dashboard shows the most recently accessed course plus the next incomplete lesson, with one "Continue" button to /lessons/:nextLessonId. Data comes from gamificationApi.getAllCoursesProgress(). Resume drops from 5 clicks to 1 tap.
  • Mobile TOC drawer. Replace hidden lg:block with a TOC trigger in the sticky header. On <lg screens it opens a bottom drawer of lesson headings; tapping a heading scrolls to it.
  • Real achievements. Wire the achievements section to gamificationApi.getAchievements(). If no backend endpoint exists yet, hide the section behind a feature flag rather than show mock data.
  • Assignment links. Render UpcomingAssignmentsWidget items as <Link to={'/assignments/' + id}> instead of static <div>.
  • Data layer. Convert StudentDashboard from useState/useEffect to TanStack Query with shared hooks.

Out of scope: the TipTap renderer (block types render correctly), inline quiz blocks (quizzes stay separate assignments), the XP formula and level thresholds, and a native mobile app (this is web responsive work).

Where it lives

Routes: /dashboard, /courses, /courses/:courseId, /lessons/:lessonId, /lessons.

Key files: apps/web/src/pages/shared/DashboardPage/components/StudentDashboard.tsx (dashboard, achievements, CTA gaps), UpcomingAssignmentsWidget.tsx (<div> not <Link>), apps/web/src/pages/shared/LessonPage.tsx (TOC hidden on mobile, mark-complete flow), apps/web/src/services/gamification.ts (XP, progress, achievements API).