diff --git a/app/Http/Controllers/CustomerLicenseController.php b/app/Http/Controllers/CustomerLicenseController.php index 62cc960a..4f85638a 100644 --- a/app/Http/Controllers/CustomerLicenseController.php +++ b/app/Http/Controllers/CustomerLicenseController.php @@ -63,8 +63,9 @@ public function index(): View default => 'No accounts connected', }; - // Total purchases (licenses + plugins) - $totalPurchases = $licenseCount + $pluginLicenseCount; + // Total purchases (licenses + plugins + products) + $productLicenseCount = $user->productLicenses()->count(); + $totalPurchases = $licenseCount + $pluginLicenseCount + $productLicenseCount; return view('customer.dashboard', compact( 'licenseCount', diff --git a/app/Http/Controllers/PurchaseHistoryController.php b/app/Http/Controllers/PurchaseHistoryController.php index fb2f0b45..e2fd10eb 100644 --- a/app/Http/Controllers/PurchaseHistoryController.php +++ b/app/Http/Controllers/PurchaseHistoryController.php @@ -61,8 +61,28 @@ public function index(): View ]; }); + // Fetch product licenses (e.g. Plugin Dev Kit, Masterclass) + $productLicenses = $user->productLicenses() + ->with('product') + ->orderBy('purchased_at', 'desc') + ->get() + ->map(function ($productLicense) { + return [ + 'type' => 'product', + 'name' => $productLicense->product->name ?? 'Product', + 'description' => $productLicense->product->description ?? null, + 'price' => $productLicense->price_paid, + 'currency' => $productLicense->currency, + 'purchased_at' => $productLicense->purchased_at, + 'expires_at' => null, + 'is_active' => true, + 'href' => $productLicense->product ? route('products.show', $productLicense->product) : null, + ]; + }); + // Combine and sort by purchased_at descending $purchases = $licenses->concat($pluginLicenses) + ->concat($productLicenses) ->sortByDesc('purchased_at') ->values(); diff --git a/resources/views/customer/purchase-history/index.blade.php b/resources/views/customer/purchase-history/index.blade.php index fe821f34..46e1b80f 100644 --- a/resources/views/customer/purchase-history/index.blade.php +++ b/resources/views/customer/purchase-history/index.blade.php @@ -41,6 +41,10 @@
+ @elseif($purchase['type'] === 'product') +
+ +
@else
@@ -63,6 +67,10 @@ License + @elseif($purchase['type'] === 'product') + + Product + @else Plugin diff --git a/tests/Feature/PurchaseHistoryTest.php b/tests/Feature/PurchaseHistoryTest.php new file mode 100644 index 00000000..b79c7191 --- /dev/null +++ b/tests/Feature/PurchaseHistoryTest.php @@ -0,0 +1,122 @@ +get('/customer/purchase-history'); + + $response->assertRedirect('/login'); + } + + public function test_purchase_history_shows_product_licenses(): void + { + $user = User::factory()->create(); + $product = Product::factory()->create(['name' => 'Plugin Dev Kit']); + + ProductLicense::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'price_paid' => 4900, + 'currency' => 'USD', + 'purchased_at' => now()->subDay(), + ]); + + $response = $this->actingAs($user)->get('/customer/purchase-history'); + + $response->assertStatus(200); + $response->assertSee('Plugin Dev Kit'); + $response->assertSee('Product'); + $response->assertSee('$49.00'); + } + + public function test_purchase_history_shows_multiple_product_types(): void + { + $user = User::factory()->create(); + + $devKit = Product::factory()->create(['name' => 'Plugin Dev Kit']); + $masterclass = Product::factory()->create(['name' => 'The NativePHP Masterclass']); + + ProductLicense::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $devKit->id, + 'price_paid' => 4900, + 'purchased_at' => now()->subDays(2), + ]); + + ProductLicense::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $masterclass->id, + 'price_paid' => 10100, + 'purchased_at' => now()->subDay(), + ]); + + $response = $this->actingAs($user)->get('/customer/purchase-history'); + + $response->assertStatus(200); + $response->assertSee('Plugin Dev Kit'); + $response->assertSee('The NativePHP Masterclass'); + } + + public function test_dashboard_total_purchases_includes_product_licenses(): void + { + $user = User::factory()->create(); + $product = Product::factory()->create(); + + ProductLicense::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + ]); + + $response = $this->actingAs($user)->get('/dashboard'); + + $response->assertStatus(200); + $response->assertViewHas('totalPurchases', 1); + } + + public function test_purchase_history_shows_empty_state_when_no_purchases(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->get('/customer/purchase-history'); + + $response->assertStatus(200); + $response->assertSee('No purchases yet'); + } + + public function test_product_purchases_show_as_active(): void + { + $user = User::factory()->create(); + $product = Product::factory()->create(['name' => 'Plugin Dev Kit']); + + ProductLicense::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'purchased_at' => now(), + ]); + + $response = $this->actingAs($user)->get('/customer/purchase-history'); + + $response->assertStatus(200); + $response->assertSee('Active'); + } +}