123 lines
5.1 KiB
Vue
123 lines
5.1 KiB
Vue
<script setup>
|
|
import AppLayout from '@/Layouts/AppLayout.vue'
|
|
import { useForm, Link } from '@inertiajs/vue3'
|
|
import { ref } from 'vue'
|
|
|
|
const props = defineProps({
|
|
account: Object,
|
|
bookings: Array,
|
|
})
|
|
|
|
const showCreate = ref(false)
|
|
const form = useForm({
|
|
amount: '',
|
|
type: 'credit',
|
|
description: '',
|
|
booked_at: '',
|
|
payment_id: null,
|
|
})
|
|
|
|
function openCreate() {
|
|
form.reset()
|
|
form.clearErrors()
|
|
showCreate.value = true
|
|
}
|
|
function closeCreate() {
|
|
showCreate.value = false
|
|
form.clearErrors()
|
|
}
|
|
function submit() {
|
|
form.post(route('accounts.bookings.store', { account: props.account.id }), {
|
|
preserveScroll: true,
|
|
onSuccess: () => closeCreate(),
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<AppLayout :title="`Bookings - ${account.reference || account.id}`">
|
|
<template #header>
|
|
<div class="flex items-center justify-between">
|
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight">Bookings · {{ account.reference || account.id }}</h2>
|
|
<div class="flex items-center gap-2">
|
|
<Link :href="route('accounts.payments.index', { account: account.id })" class="text-sm underline">Payments</Link>
|
|
<button class="px-3 py-2 bg-emerald-600 text-white rounded" @click="openCreate">New Booking</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="py-6">
|
|
<div class="max-w-5xl mx-auto sm:px-6 lg:px-8">
|
|
<div class="bg-white shadow sm:rounded-lg p-6">
|
|
<table class="min-w-full text-left text-sm">
|
|
<thead class="border-b text-gray-500">
|
|
<tr>
|
|
<th class="py-2 pr-4">Booked at</th>
|
|
<th class="py-2 pr-4">Type</th>
|
|
<th class="py-2 pr-4">Amount</th>
|
|
<th class="py-2 pr-4">Description</th>
|
|
<th class="py-2 pr-0 text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="b in bookings" :key="b.id" class="border-b last:border-0">
|
|
<td class="py-2 pr-4">{{ b.booked_at ? new Date(b.booked_at).toLocaleString() : '-' }}</td>
|
|
<td class="py-2 pr-4">
|
|
<span :class="['px-2 py-0.5 rounded text-xs', b.type === 'credit' ? 'bg-emerald-50 text-emerald-700' : 'bg-amber-50 text-amber-800']">
|
|
{{ b.type }}
|
|
</span>
|
|
</td>
|
|
<td class="py-2 pr-4 font-medium">{{ (b.amount_cents / 100).toFixed(2) }}</td>
|
|
<td class="py-2 pr-4">{{ b.description || '-' }}</td>
|
|
<td class="py-2 pr-0 text-right">
|
|
<form :action="route('accounts.bookings.destroy', { account: account.id, booking: b.id })" method="post" @submit.prevent="$inertia.delete(route('accounts.bookings.destroy', { account: account.id, booking: b.id }), { preserveScroll: true })">
|
|
<button type="submit" class="text-red-600 hover:underline">Delete</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<tr v-if="!bookings?.length">
|
|
<td colspan="5" class="py-6 text-center text-gray-500">No bookings.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="showCreate" class="fixed inset-0 z-50 flex items-center justify-center">
|
|
<div class="absolute inset-0 bg-black/30" @click="closeCreate"></div>
|
|
<div class="relative bg-white rounded shadow-lg w-[32rem] max-w-[90%] p-5">
|
|
<div class="text-lg font-semibold mb-2">New Booking</div>
|
|
<div class="grid grid-cols-1 gap-3">
|
|
<div class="flex gap-3">
|
|
<div class="flex-1">
|
|
<label class="block text-sm text-gray-700 mb-1">Type</label>
|
|
<select v-model="form.type" class="w-full border rounded px-3 py-2">
|
|
<option value="credit">Credit</option>
|
|
<option value="debit">Debit</option>
|
|
</select>
|
|
</div>
|
|
<div class="flex-1">
|
|
<label class="block text-sm text-gray-700 mb-1">Amount</label>
|
|
<input type="number" step="0.01" v-model="form.amount" class="w-full border rounded px-3 py-2" :class="form.errors.amount && 'border-red-500'" />
|
|
<div v-if="form.errors.amount" class="text-xs text-red-600 mt-1">{{ form.errors.amount }}</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm text-gray-700 mb-1">Booked at</label>
|
|
<input type="datetime-local" v-model="form.booked_at" class="w-full border rounded px-3 py-2" />
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm text-gray-700 mb-1">Description</label>
|
|
<input type="text" v-model="form.description" class="w-full border rounded px-3 py-2" />
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center justify-end gap-2 mt-5">
|
|
<button class="px-3 py-1.5 border rounded" @click="closeCreate" :disabled="form.processing">Cancel</button>
|
|
<button class="px-3 py-1.5 rounded text-white bg-emerald-600 disabled:opacity-60" @click="submit" :disabled="form.processing">Create</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</AppLayout>
|
|
</template>
|