Skip to content

Show the course curriculum to users who haven't purchased - #449

Merged
simonhamp merged 1 commit into
mainfrom
free-modules-dashboard
Jul 30, 2026
Merged

Show the course curriculum to users who haven't purchased#449
simonhamp merged 1 commit into
mainfrom
free-modules-dashboard

Conversation

@simonhamp

Copy link
Copy Markdown
Member

Why

Free course modules were never visible on the course dashboard. customer/course.blade.php gated its whole body on @if ($this->hasPurchased || $this->isAdmin), so non-purchasers got only the marketing page — no module listing existed in that branch, and Course\Index exposed nothing to render one. Free lessons were already reachable (LessonShow::mount() allows is_free without purchase), so the access plumbing worked; there was just no way to discover them.

Visiting a paid lesson without purchase was also a dead end: abort(403, 'You need Pro access...') with no resources/views/errors/403.blade.php in the project, so it fell through to Laravel's bare errors::minimal page — no layout, no branding, no link anywhere. The copy was misleading too: "Pro" means a subscription tier here (policy_name in ['max','pro','mini']), but the masterclass is a one-time product purchase.

What changed

Curriculum outline for non-purchasers. Course\Index::outlineModules() returns published modules with at least one published lesson. Every lesson is listed — free ones link out, the rest render a lock with a "Buy the course to unlock all lessons" tooltip. Collection keys are deliberately preserved so modules are numbered by real course position, not position within the filtered subset.

Paid lessons redirect instead of 403ing. LessonShow::mount() flashes an explanation and redirects to the course page, which already renders the pricing and CTA — turning a dead end into the page most likely to convert. The course page rendered no flash messages at all, so that markup was added.

Locked sidebar lessons are clickable. In lesson-show.blade.php, anything published is now a link and routes through the redirect above; drafts stay unclickable with "Coming Soon". wire:navigate is omitted on locked links so the 302-and-flash is a plain navigation.

Layout. The not-purchased page is ordered hero → feature cards → locked-lesson notice → curriculum. The notice sits inside the outline's max-w-7xl container: app.css strips the main container's padding via [data-flux-main]:has(.course-fullbleed), so anything outside an inner container renders edge-to-edge. Bottom padding moved onto the .course-fullbleed wrapper so spacing holds when the curriculum block is absent.

Copy. Hero pill "New Course" → "Masterclass" (both the early-bird and post-deadline variants).

Notes for review

  • Module-level is_free remains unused for access control — gating is entirely lesson-level is_free. A module flagged free whose lessons aren't will show locked lessons. Left as-is; worth deciding whether that flag should drive access or be removed.
  • The flash callout now lives inside the not-purchased branch, so session('message') no longer renders for purchasers/admins on this page. Harmless today (only the locked-lesson redirect sets it, which can't fire for them), but a constraint to be aware of.
  • No 403.blade.php was added — other abort(403) calls elsewhere still hit the bare vendor page.
  • Not verified in a browser; the tooltip's hover behaviour in particular is untested by the suite.

Tests

tests/Feature/CourseContentTest.php: 50 passing, up from 35. Covers the curriculum listing, both exclusion paths (unpublished lesson, unpublished module), paid-module inclusion, mixed free/paid modules, module numbering, the redirect and its flash end-to-end over HTTP, the redirect under app.debug => false, the 404 path for unpublished lessons, sidebar link behaviour for locked vs draft lessons, and section ordering.

79 passing across CourseContentTest, CoursePageTest, HomeCourseCardTest, DashboardLayoutTest. Pint clean.

🤖 Generated with Claude Code

The course dashboard rendered only a marketing page for non-purchasers,
so free lessons existed but could not be discovered. Add a curriculum
outline listing every published module and lesson, with free lessons
linked and the rest locked behind a tooltip.

Replace the bare 403 on paid lessons with a redirect to the course page
plus an explanation, and make locked lessons in the lesson sidebar
clickable so they route through it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@simonhamp
simonhamp marked this pull request as ready for review July 30, 2026 02:51
@simonhamp
simonhamp merged commit e6b4db8 into main Jul 30, 2026
2 checks passed
@simonhamp
simonhamp deleted the free-modules-dashboard branch July 30, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant