From 371ed4e6a6110332e48b0f580d1adb2380ff3be846b5dd3a5fb8fc83c646bb21 Mon Sep 17 00:00:00 2001 From: Claude Dev Date: Mon, 9 Feb 2026 20:24:15 -0500 Subject: [PATCH] Add payment methods management page List Stripe payment methods with set-default and remove actions. Includes delete confirmation dialog, breadcrumb navigation, and sidebar nav entry. Co-Authored-By: Claude Sonnet 4.5 --- .../Controllers/Account/BillingController.php | 29 +++ .../ts/Pages/Billing/PaymentMethods.vue | 229 ++++++++++++++++++ website/resources/ts/navigation/account.ts | 1 + website/routes/account.php | 1 + 4 files changed, 260 insertions(+) create mode 100644 website/resources/ts/Pages/Billing/PaymentMethods.vue diff --git a/website/app/Http/Controllers/Account/BillingController.php b/website/app/Http/Controllers/Account/BillingController.php index 3cc291a..99e085d 100644 --- a/website/app/Http/Controllers/Account/BillingController.php +++ b/website/app/Http/Controllers/Account/BillingController.php @@ -76,6 +76,35 @@ class BillingController extends Controller return back()->with('success', 'Default payment method updated.'); } + public function paymentMethods(Request $request): Response + { + $user = $request->user(); + $paymentMethods = []; + $defaultPaymentMethod = null; + + if ($user->hasStripeId()) { + $methods = $user->paymentMethods(); + $defaultPm = $user->defaultPaymentMethod(); + $defaultPaymentMethod = $defaultPm?->id; + + foreach ($methods as $method) { + $paymentMethods[] = [ + 'id' => $method->id, + 'brand' => $method->card->brand ?? 'unknown', + 'last_four' => $method->card->last_four ?? '****', + 'exp_month' => $method->card->exp_month, + 'exp_year' => $method->card->exp_year, + 'is_default' => $method->id === $defaultPaymentMethod, + ]; + } + } + + return Inertia::render('Billing/PaymentMethods', [ + 'paymentMethods' => $paymentMethods, + 'defaultPaymentMethod' => $defaultPaymentMethod, + ]); + } + public function invoices(Request $request): Response { $invoices = $request->user() diff --git a/website/resources/ts/Pages/Billing/PaymentMethods.vue b/website/resources/ts/Pages/Billing/PaymentMethods.vue new file mode 100644 index 0000000..db438f7 --- /dev/null +++ b/website/resources/ts/Pages/Billing/PaymentMethods.vue @@ -0,0 +1,229 @@ + + + diff --git a/website/resources/ts/navigation/account.ts b/website/resources/ts/navigation/account.ts index 14dcac8..fa4c29f 100644 --- a/website/resources/ts/navigation/account.ts +++ b/website/resources/ts/navigation/account.ts @@ -8,6 +8,7 @@ export const accountNavItems: VerticalNavItems = [ { heading: 'Billing' }, { title: 'Billing', to: '/billing', icon: 'tabler-credit-card' }, + { title: 'Payment Methods', to: '/billing/payment-methods', icon: 'tabler-wallet' }, { title: 'Plans', to: '/plans', icon: 'tabler-package' }, { heading: 'Support' }, diff --git a/website/routes/account.php b/website/routes/account.php index 02baf34..7b1a2ee 100644 --- a/website/routes/account.php +++ b/website/routes/account.php @@ -49,6 +49,7 @@ Route::get('/billing', [BillingController::class, 'index'])->name('account.billi Route::post('/billing/payment-methods', [BillingController::class, 'addPaymentMethod'])->name('account.billing.add-payment-method'); Route::delete('/billing/payment-methods/{paymentMethod}', [BillingController::class, 'removePaymentMethod'])->name('account.billing.remove-payment-method'); Route::post('/billing/payment-methods/default', [BillingController::class, 'setDefaultPaymentMethod'])->name('account.billing.set-default-payment-method'); +Route::get('/billing/payment-methods', [BillingController::class, 'paymentMethods'])->name('account.billing.payment-methods'); Route::get('/billing/invoices', [BillingController::class, 'invoices'])->name('account.billing.invoices'); Route::get('/billing/invoices/{invoice}/download', [BillingController::class, 'downloadInvoice'])->name('account.billing.invoices.download'); Route::get('/billing/transactions', [BillingController::class, 'transactions'])->name('account.billing.transactions');