Files
website/website/resources/js/Pages/Billing/Index.vue
Claude Dev 67ea1ef22a Switch entire UI to dark mode by default
Update all 26 Vue files (3 layouts, 4 components, 19 pages) and the
Blade root template to use a dark color scheme: gray-950 backgrounds,
gray-900 cards, gray-800 borders, light text, and adjusted status
badges/flash messages for dark backgrounds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 07:24:23 -05:00

165 lines
8.2 KiB
Vue

<script setup>
import { useForm, Link } from '@inertiajs/vue3';
import AppLayout from '@/Layouts/AppLayout.vue';
defineOptions({ layout: AppLayout });
defineProps({
paymentMethods: Array,
invoices: Array,
transactions: Array,
intent: Object,
stripeKey: String,
});
const defaultForm = useForm({
payment_method_id: '',
});
const setDefault = (id) => {
defaultForm.payment_method_id = id;
defaultForm.post('/billing/payment-methods/default');
};
const removeMethod = (id) => {
if (confirm('Are you sure you want to remove this payment method?')) {
useForm({}).delete(`/billing/payment-methods/${id}`);
}
};
</script>
<template>
<div>
<h1 class="text-2xl font-bold text-white mb-6">Billing</h1>
<div class="space-y-8">
<!-- Payment Methods -->
<div class="bg-gray-900 rounded-lg border border-gray-800 shadow-sm p-6">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-semibold text-white">Payment Methods</h2>
</div>
<div v-if="paymentMethods.length === 0" class="text-sm text-gray-500">
No payment methods on file.
</div>
<div v-else class="space-y-3">
<div
v-for="pm in paymentMethods"
:key="pm.id"
class="flex items-center justify-between p-3 border rounded-md"
:class="pm.is_default ? 'border-blue-700 bg-blue-900/20' : 'border-gray-700'"
>
<div class="flex items-center gap-3">
<span class="text-sm font-medium text-gray-200 capitalize">{{ pm.brand }}</span>
<span class="text-sm text-gray-500">&bull;&bull;&bull;&bull; {{ pm.last_four }}</span>
<span class="text-sm text-gray-600">{{ pm.exp_month }}/{{ pm.exp_year }}</span>
<span v-if="pm.is_default" class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-900/50 text-blue-300 border border-blue-800">Default</span>
</div>
<div class="flex items-center gap-2">
<button
v-if="!pm.is_default"
@click="setDefault(pm.id)"
:disabled="defaultForm.processing"
class="text-sm text-blue-400 hover:text-blue-300"
>
Make Default
</button>
<button
@click="removeMethod(pm.id)"
class="text-sm text-red-400 hover:text-red-300"
>
Remove
</button>
</div>
</div>
</div>
</div>
<!-- Recent Invoices -->
<div class="bg-gray-900 rounded-lg border border-gray-800 shadow-sm p-6">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-semibold text-white">Recent Invoices</h2>
<Link href="/billing/invoices" class="text-sm text-blue-400 hover:text-blue-300">View All</Link>
</div>
<div v-if="invoices.length === 0" class="text-sm text-gray-500">No invoices yet.</div>
<table v-else class="w-full text-sm">
<thead>
<tr class="border-b border-gray-800">
<th class="text-left py-2 text-gray-500 font-medium">Number</th>
<th class="text-left py-2 text-gray-500 font-medium">Date</th>
<th class="text-left py-2 text-gray-500 font-medium">Status</th>
<th class="text-right py-2 text-gray-500 font-medium">Amount</th>
<th class="text-right py-2 text-gray-500 font-medium"></th>
</tr>
</thead>
<tbody>
<tr v-for="invoice in invoices" :key="invoice.id" class="border-b border-gray-800/50">
<td class="py-2 text-gray-200">{{ invoice.number }}</td>
<td class="py-2 text-gray-400">{{ new Date(invoice.created_at).toLocaleDateString() }}</td>
<td class="py-2">
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium capitalize"
:class="{
'bg-green-900/50 text-green-300': invoice.status === 'paid',
'bg-yellow-900/50 text-yellow-300': invoice.status === 'pending',
'bg-red-900/50 text-red-300': invoice.status === 'overdue',
}"
>
{{ invoice.status }}
</span>
</td>
<td class="py-2 text-right text-gray-200">${{ parseFloat(invoice.total).toFixed(2) }}</td>
<td class="py-2 text-right">
<a :href="`/billing/invoices/${invoice.id}/download`" class="text-blue-400 hover:text-blue-300">Download</a>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Recent Transactions -->
<div class="bg-gray-900 rounded-lg border border-gray-800 shadow-sm p-6">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-semibold text-white">Recent Transactions</h2>
<Link href="/billing/transactions" class="text-sm text-blue-400 hover:text-blue-300">View All</Link>
</div>
<div v-if="transactions.length === 0" class="text-sm text-gray-500">No transactions yet.</div>
<table v-else class="w-full text-sm">
<thead>
<tr class="border-b border-gray-800">
<th class="text-left py-2 text-gray-500 font-medium">Date</th>
<th class="text-left py-2 text-gray-500 font-medium">Gateway</th>
<th class="text-left py-2 text-gray-500 font-medium">Status</th>
<th class="text-left py-2 text-gray-500 font-medium">Description</th>
<th class="text-right py-2 text-gray-500 font-medium">Amount</th>
</tr>
</thead>
<tbody>
<tr v-for="tx in transactions" :key="tx.id" class="border-b border-gray-800/50">
<td class="py-2 text-gray-400">{{ new Date(tx.created_at).toLocaleDateString() }}</td>
<td class="py-2 text-gray-400 capitalize">{{ tx.gateway }}</td>
<td class="py-2">
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium capitalize"
:class="{
'bg-green-900/50 text-green-300': tx.status === 'succeeded',
'bg-red-900/50 text-red-300': tx.status === 'failed',
'bg-yellow-900/50 text-yellow-300': tx.status === 'pending',
}"
>
{{ tx.status }}
</span>
</td>
<td class="py-2 text-gray-400">{{ tx.description }}</td>
<td class="py-2 text-right text-gray-200">${{ parseFloat(tx.amount).toFixed(2) }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>