Skip to content

Commit b60c320

Browse files
shanerbaner82claude
andcommitted
Redesign dashboard course page with light/dark mode and fix tests
- Full-width hero with violet gradient for non-purchasers - Coming soon message for purchasers while content is being recorded - Light/dark mode support throughout - Update CourseContentTest to match new UI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 18a9783 commit b60c320

2 files changed

Lines changed: 109 additions & 79 deletions

File tree

resources/views/livewire/customer/course.blade.php

Lines changed: 87 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,21 @@ class="h-2 rounded-full bg-emerald-500 transition-all"
2323
</div>
2424
@endif
2525

26-
<flux:callout variant="success" icon="check-circle" class="mb-6">
27-
<flux:callout.text>You have Pro access. All modules and lessons are unlocked.</flux:callout.text>
28-
</flux:callout>
26+
<div class="mb-6 rounded-lg border border-violet-200 bg-violet-50 p-6 dark:border-violet-700/50 dark:bg-violet-900/20">
27+
<div class="flex items-start gap-4">
28+
<div class="shrink-0 text-violet-600 dark:text-violet-400">
29+
<x-heroicon-s-sparkles class="size-6" />
30+
</div>
31+
<div>
32+
<h3 class="font-medium text-violet-900 dark:text-violet-100">
33+
You're in! Course content is coming soon.
34+
</h3>
35+
<p class="mt-1 text-sm text-violet-700 dark:text-violet-300">
36+
We're recording the lessons now. You'll have full access to all modules and lessons as soon as they're published.
37+
</p>
38+
</div>
39+
</div>
40+
</div>
2941

3042
{{-- Modules --}}
3143
<div class="space-y-4">
@@ -84,88 +96,100 @@ class="h-2 rounded-full bg-emerald-500 transition-all"
8496
</flux:callout>
8597
@endif
8698
@else
87-
{{-- Not purchased: Show marketing/purchase page --}}
88-
<div class="mx-auto max-w-2xl">
99+
{{-- Not purchased: Full-width marketing/purchase page --}}
100+
<div class="-mx-6 -mt-6 sm:-mx-8 sm:-mt-8">
89101
{{-- Hero --}}
90-
<div class="rounded-2xl border border-zinc-200 bg-white p-8 text-center dark:border-white/10 dark:bg-white/5 sm:p-12">
91-
<div class="inline-flex items-center gap-2 rounded-full bg-emerald-100 px-4 py-1.5 text-sm font-medium text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300">
92-
<span class="relative flex size-2">
93-
<span class="absolute inline-flex size-full animate-ping rounded-full bg-emerald-400 opacity-75"></span>
94-
<span class="relative inline-flex size-2 rounded-full bg-emerald-500"></span>
102+
<div class="relative overflow-hidden rounded-2xl bg-gradient-to-b from-violet-50 to-white px-6 py-16 sm:px-12 sm:py-20 dark:from-zinc-900 dark:to-zinc-950">
103+
{{-- Background glow --}}
104+
<div class="pointer-events-none absolute -top-24 left-1/2 size-[500px] -translate-x-1/2 rounded-full bg-violet-500/5 blur-[120px] dark:bg-violet-500/10" aria-hidden="true"></div>
105+
<div class="pointer-events-none absolute -bottom-32 -right-32 size-[400px] rounded-full bg-indigo-500/5 blur-[100px] dark:bg-indigo-500/10" aria-hidden="true"></div>
106+
107+
<div class="relative z-10 mx-auto max-w-2xl text-center">
108+
<span class="inline-flex items-center gap-2 rounded-md bg-violet-500/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-violet-600 ring-1 ring-violet-500/20 dark:text-violet-400">
109+
New Course &mdash; Early Bird
95110
</span>
96-
Early Bird Pricing
97-
</div>
98111

99-
<h1 class="mt-6 text-3xl font-bold sm:text-4xl">
100-
<span class="text-zinc-900 dark:text-white">The</span>
101-
<span class="bg-gradient-to-r from-emerald-500 to-teal-500 bg-clip-text text-transparent">NativePHP</span>
102-
<br />
103-
<span class="text-zinc-900 dark:text-white">Masterclass</span>
104-
</h1>
112+
<h1 class="mt-8 text-4xl font-black tracking-tight text-zinc-900 sm:text-5xl lg:text-6xl dark:text-white">
113+
Build native apps
114+
<span class="bg-gradient-to-r from-violet-600 via-purple-500 to-indigo-600 bg-clip-text text-transparent dark:from-violet-400 dark:via-purple-300 dark:to-indigo-400">the Laravel way.</span>
115+
</h1>
105116

106-
<p class="mx-auto mt-4 max-w-md text-zinc-600 dark:text-zinc-400">
107-
Go from zero to published app. Learn to build native mobile and desktop applications using the PHP and Laravel skills you already have.
108-
</p>
117+
<p class="mx-auto mt-6 max-w-xl text-lg leading-relaxed text-zinc-600 dark:text-zinc-400">
118+
This course takes you from zero to a published app on the App Store &mdash; using the PHP and Laravel skills you already have.
119+
</p>
109120

110-
{{-- Price --}}
111-
<div class="mt-8 flex items-baseline justify-center gap-2">
112-
<span class="text-5xl font-bold text-zinc-900 dark:text-white">$101</span>
113-
<span class="text-xl text-zinc-400 line-through">$299</span>
114-
<span class="text-sm text-zinc-500 dark:text-zinc-400">one-time</span>
115-
</div>
121+
<div class="mt-8 flex flex-wrap items-center justify-center gap-4 text-sm text-zinc-500 dark:text-zinc-500">
122+
<span class="flex items-center gap-2">
123+
<svg class="size-4 text-emerald-500 dark:text-emerald-400" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.06l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"/></svg>
124+
Free modules included
125+
</span>
126+
<span class="flex items-center gap-2">
127+
<svg class="size-4 text-emerald-500 dark:text-emerald-400" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.06l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"/></svg>
128+
HD video lessons
129+
</span>
130+
<span class="flex items-center gap-2">
131+
<svg class="size-4 text-emerald-500 dark:text-emerald-400" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.06l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"/></svg>
132+
Lifetime access
133+
</span>
134+
</div>
135+
136+
{{-- Price --}}
137+
<div class="mt-10 flex items-baseline justify-center gap-3">
138+
<span class="text-5xl font-black text-zinc-900 dark:text-white">$101</span>
139+
<span class="text-xl text-zinc-400 line-through dark:text-zinc-600">$299</span>
140+
<span class="text-sm text-zinc-500">one-time</span>
141+
</div>
116142

117-
{{-- CTA --}}
118-
<div class="mt-8">
119-
<form action="{{ route('course.checkout') }}" method="POST">
120-
@csrf
121-
<flux:button type="submit" variant="primary" class="!bg-emerald-600 hover:!bg-emerald-700 !px-8 !py-3 !text-base">
122-
Get Early Bird Access
123-
</flux:button>
124-
</form>
143+
{{-- CTA --}}
144+
<div class="mt-8 flex flex-col items-center gap-4 sm:flex-row sm:justify-center">
145+
<form action="{{ route('course.checkout') }}" method="POST">
146+
@csrf
147+
<button type="submit" class="inline-flex items-center gap-2 rounded-xl bg-gradient-to-b from-violet-500 to-violet-600 px-8 py-3.5 text-sm font-semibold text-white shadow-lg shadow-violet-500/25 ring-1 ring-violet-400/20 transition hover:shadow-xl hover:shadow-violet-500/30">
148+
Get Early Bird Access
149+
<svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"/></svg>
150+
</button>
151+
</form>
152+
<a href="{{ route('course') }}" class="text-sm font-medium text-zinc-500 transition hover:text-zinc-900 dark:hover:text-white">
153+
View full details &rarr;
154+
</a>
155+
</div>
125156
</div>
126157
</div>
127158

128159
{{-- What's Included --}}
129-
<div class="mt-8 grid gap-4 sm:grid-cols-2">
130-
<div class="rounded-xl border border-zinc-200 bg-white p-6 dark:border-white/10 dark:bg-white/5">
131-
<div class="flex size-10 items-center justify-center rounded-lg bg-emerald-100 dark:bg-emerald-900/50">
132-
<x-heroicon-s-device-phone-mobile class="size-5 text-emerald-600 dark:text-emerald-400" />
160+
<div class="mt-8 grid gap-4 px-1 sm:grid-cols-2 lg:grid-cols-4">
161+
<div class="rounded-xl border border-zinc-200 bg-white p-5 dark:border-white/10 dark:bg-white/5">
162+
<div class="flex size-9 items-center justify-center rounded-lg bg-violet-100 dark:bg-violet-500/15">
163+
<x-heroicon-s-device-phone-mobile class="size-4 text-violet-600 dark:text-violet-400" />
133164
</div>
134-
<h3 class="mt-3 font-semibold text-zinc-900 dark:text-white">Mobile & Desktop</h3>
135-
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">Build iOS, Android, macOS, Windows, and Linux apps from one codebase.</p>
165+
<h3 class="mt-3 text-sm font-semibold text-zinc-900 dark:text-white">Mobile & Desktop</h3>
166+
<p class="mt-1 text-xs text-zinc-600 dark:text-zinc-400">iOS, Android, macOS, Windows, and Linux from one codebase.</p>
136167
</div>
137168

138-
<div class="rounded-xl border border-zinc-200 bg-white p-6 dark:border-white/10 dark:bg-white/5">
139-
<div class="flex size-10 items-center justify-center rounded-lg bg-emerald-100 dark:bg-emerald-900/50">
140-
<x-heroicon-s-code-bracket class="size-5 text-emerald-600 dark:text-emerald-400" />
169+
<div class="rounded-xl border border-zinc-200 bg-white p-5 dark:border-white/10 dark:bg-white/5">
170+
<div class="flex size-9 items-center justify-center rounded-lg bg-violet-100 dark:bg-violet-500/15">
171+
<x-heroicon-s-code-bracket class="size-4 text-violet-600 dark:text-violet-400" />
141172
</div>
142-
<h3 class="mt-3 font-semibold text-zinc-900 dark:text-white">Use Your PHP Skills</h3>
143-
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">No need to learn Swift, Kotlin, or Dart. Build native apps with Laravel.</p>
173+
<h3 class="mt-3 text-sm font-semibold text-zinc-900 dark:text-white">Use Your PHP Skills</h3>
174+
<p class="mt-1 text-xs text-zinc-600 dark:text-zinc-400">No Swift, Kotlin, or Dart. Build native apps with Laravel.</p>
144175
</div>
145176

146-
<div class="rounded-xl border border-zinc-200 bg-white p-6 dark:border-white/10 dark:bg-white/5">
147-
<div class="flex size-10 items-center justify-center rounded-lg bg-emerald-100 dark:bg-emerald-900/50">
148-
<x-heroicon-s-rocket-launch class="size-5 text-emerald-600 dark:text-emerald-400" />
177+
<div class="rounded-xl border border-zinc-200 bg-white p-5 dark:border-white/10 dark:bg-white/5">
178+
<div class="flex size-9 items-center justify-center rounded-lg bg-violet-100 dark:bg-violet-500/15">
179+
<x-heroicon-s-rocket-launch class="size-4 text-violet-600 dark:text-violet-400" />
149180
</div>
150-
<h3 class="mt-3 font-semibold text-zinc-900 dark:text-white">Zero to Published</h3>
151-
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">From setup to the App Store and Google Play. The complete journey.</p>
181+
<h3 class="mt-3 text-sm font-semibold text-zinc-900 dark:text-white">Zero to Published</h3>
182+
<p class="mt-1 text-xs text-zinc-600 dark:text-zinc-400">From setup to the App Store and Google Play.</p>
152183
</div>
153184

154-
<div class="rounded-xl border border-zinc-200 bg-white p-6 dark:border-white/10 dark:bg-white/5">
155-
<div class="flex size-10 items-center justify-center rounded-lg bg-emerald-100 dark:bg-emerald-900/50">
156-
<x-heroicon-s-arrow-path class="size-5 text-emerald-600 dark:text-emerald-400" />
185+
<div class="rounded-xl border border-zinc-200 bg-white p-5 dark:border-white/10 dark:bg-white/5">
186+
<div class="flex size-9 items-center justify-center rounded-lg bg-violet-100 dark:bg-violet-500/15">
187+
<x-heroicon-s-arrow-path class="size-4 text-violet-600 dark:text-violet-400" />
157188
</div>
158-
<h3 class="mt-3 font-semibold text-zinc-900 dark:text-white">Lifetime Access</h3>
159-
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">One-time payment. All current and future content included.</p>
189+
<h3 class="mt-3 text-sm font-semibold text-zinc-900 dark:text-white">Lifetime Access</h3>
190+
<p class="mt-1 text-xs text-zinc-600 dark:text-zinc-400">One-time payment. All current and future content.</p>
160191
</div>
161192
</div>
162-
163-
{{-- Link to full course page --}}
164-
<div class="mt-8 text-center">
165-
<a href="{{ route('course') }}" class="text-sm font-medium text-emerald-600 hover:text-emerald-700 dark:text-emerald-400 dark:hover:text-emerald-300">
166-
View full course details &rarr;
167-
</a>
168-
</div>
169193
</div>
170194
@endif
171195
</div>

tests/Feature/CourseContentTest.php

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,23 @@ class CourseContentTest extends TestCase
2121
use RefreshDatabase;
2222

2323
#[Test]
24-
public function course_page_shows_dynamic_modules_from_database(): void
24+
public function course_page_loads_successfully(): void
2525
{
26-
$course = Course::factory()->published()->create();
27-
$module = CourseModule::factory()->published()->free()->create([
28-
'course_id' => $course->id,
29-
'title' => 'Getting Started Module',
30-
]);
31-
CourseLesson::factory()->published()->free()->create([
32-
'course_module_id' => $module->id,
33-
]);
34-
3526
$this
3627
->withoutVite()
3728
->get(route('course'))
3829
->assertStatus(200)
39-
->assertSee('Getting Started Module')
40-
->assertSee('Free');
30+
->assertSee('The NativePHP Masterclass');
4131
}
4232

4333
#[Test]
44-
public function course_page_shows_free_and_pro_pricing_tiers(): void
34+
public function course_page_shows_pricing(): void
4535
{
4636
$this
4737
->withoutVite()
4838
->get(route('course'))
4939
->assertStatus(200)
50-
->assertSee('$0')
51-
->assertSee('$150')
40+
->assertSee('$101')
5241
->assertSee('$299');
5342
}
5443

@@ -73,9 +62,26 @@ public function course_dashboard_loads_for_authenticated_user(): void
7362
}
7463

7564
#[Test]
76-
public function course_dashboard_shows_modules_and_lessons(): void
65+
public function course_dashboard_shows_purchase_page_for_non_owners(): void
66+
{
67+
$user = User::factory()->create();
68+
69+
Livewire::actingAs($user)
70+
->test(Index::class)
71+
->assertSee('Build native apps')
72+
->assertSee('Get Early Bird Access');
73+
}
74+
75+
#[Test]
76+
public function course_dashboard_shows_modules_and_lessons_for_owners(): void
7777
{
7878
$user = User::factory()->create();
79+
$product = Product::where('slug', 'nativephp-masterclass')->first();
80+
ProductLicense::factory()->create([
81+
'user_id' => $user->id,
82+
'product_id' => $product->id,
83+
]);
84+
7985
$course = Course::factory()->published()->create();
8086
$module = CourseModule::factory()->published()->free()->create([
8187
'course_id' => $course->id,

0 commit comments

Comments
 (0)