diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php
index 4c4a52e5..4ee4d34e 100644
--- a/app/Http/Controllers/ProductController.php
+++ b/app/Http/Controllers/ProductController.php
@@ -3,15 +3,20 @@
namespace App\Http\Controllers;
use App\Models\Product;
+use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class ProductController extends Controller
{
- public function show(Product $product): View
+ public function show(Product $product): View|RedirectResponse
{
abort_unless($product->isActive(), 404);
+ if ($product->slug === 'nativephp-masterclass') {
+ return redirect()->route('course');
+ }
+
$user = Auth::user();
if (! $product->hasAccessiblePriceFor($user)) {
diff --git a/resources/views/course.blade.php b/resources/views/course.blade.php
index 6d8c1d8e..6c69d5c0 100644
--- a/resources/views/course.blade.php
+++ b/resources/views/course.blade.php
@@ -112,30 +112,39 @@ class="mx-auto mt-6 max-w-2xl text-lg text-gray-600 dark:text-gray-400"
"
class="mt-8 flex flex-col items-center gap-4 sm:flex-row"
>
-
- Get Early Bird Access — $101
-
-
-
- or join the waitlist
-
+ Get Early Bird Access — $101
+
You Own This Course
++ You'll be notified when the course launches. +
+- Early bird pricing won't last forever. Lock in the lowest price today. -
++ Early bird pricing won't last forever. Lock in the lowest price today. +
+ @endunless @@ -755,7 +780,7 @@ class="rounded-xl bg-gray-900 px-6 py-3 text-sm font-semibold text-white transit @auth - @if (request('checkout')) + @if (request('checkout') && ! $alreadyOwned) diff --git a/routes/web.php b/routes/web.php index 952e3726..93566425 100644 --- a/routes/web.php +++ b/routes/web.php @@ -64,7 +64,15 @@ Route::view('/', 'welcome')->name('welcome'); Route::redirect('pricing', 'blog/nativephp-for-mobile-is-now-free')->name('pricing'); Route::view('alt-pricing', 'alt-pricing')->name('alt-pricing')->middleware('signed'); -Route::view('course', 'course')->name('course'); +Route::get('course', function () { + $user = auth()->user(); + $product = \App\Models\Product::where('slug', 'nativephp-masterclass')->first(); + $alreadyOwned = $user && $product && $product->isOwnedBy($user); + + return view('course', [ + 'alreadyOwned' => $alreadyOwned, + ]); +})->name('course'); Route::post('course/checkout', function (\Illuminate\Http\Request $request) { $user = $request->user(); diff --git a/tests/Feature/ProductPageTest.php b/tests/Feature/ProductPageTest.php new file mode 100644 index 00000000..090dfbcd --- /dev/null +++ b/tests/Feature/ProductPageTest.php @@ -0,0 +1,87 @@ +first(); + + $this + ->get(route('products.show', $product)) + ->assertRedirect(route('course')); + } + + #[Test] + public function non_masterclass_product_page_loads_normally(): void + { + $product = Product::factory()->active()->create([ + 'slug' => 'plugin-dev-kit', + ]); + + ProductPrice::factory()->for($product)->create(); + + $this + ->withoutVite() + ->get(route('products.show', $product)) + ->assertStatus(200) + ->assertSee($product->name); + } + + #[Test] + public function course_page_shows_purchase_form_for_guests(): void + { + $this + ->withoutVite() + ->get(route('course')) + ->assertStatus(200) + ->assertSee('Get Early Bird Access') + ->assertDontSee('You Own This Course'); + } + + #[Test] + public function course_page_shows_purchase_form_for_users_without_purchase(): void + { + $user = User::factory()->create(); + + $this + ->withoutVite() + ->actingAs($user) + ->get(route('course')) + ->assertStatus(200) + ->assertSee('Get Early Bird Access') + ->assertDontSee('You Own This Course'); + } + + #[Test] + public function course_page_shows_owned_state_for_purchasers(): void + { + $user = User::factory()->create(); + $product = Product::where('slug', 'nativephp-masterclass')->first(); + + ProductLicense::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + ]); + + $this + ->withoutVite() + ->actingAs($user) + ->get(route('course')) + ->assertStatus(200) + ->assertSee('You Own This Course') + ->assertDontSee('Get Early Bird Access'); + } +}