feat(booking): move event and ticket configuration to database

Replace hardcoded event details and ticket types with dynamic DB records
Add booking-config API endpoint to serve active event settings
This commit is contained in:
2026-05-04 10:09:08 +08:00
parent 06165f80db
commit 3f7025c8e4
13 changed files with 970 additions and 342 deletions

View File

@@ -2,14 +2,9 @@
import type { PublicBookingReceipt, PublicBookingSeatWithUrl } from '~~/shared/booking'
import {
DINNER_EVENT_DATE_LABEL,
DINNER_EVENT_TIME_LABEL,
DINNER_EVENT_TITLE,
DINNER_EVENT_VENUE,
formatBookingCurrency,
getBookingStatusLabel,
getSeatLabel,
getTicketCatalogItem
getSeatLabel
} from '~~/shared/booking'
import { getErrorMessage } from '../../utils/errors'
@@ -51,7 +46,8 @@ try {
const receipt = ref(initialReceipt)
const ticketLabel = computed(() => getTicketCatalogItem(receipt.value.booking.ticketType)?.label || receipt.value.booking.ticketType.toUpperCase())
const eventDetails = computed(() => receipt.value.booking.event)
const ticketLabel = computed(() => receipt.value.booking.ticketLabel || receipt.value.booking.ticketType.toUpperCase())
const statusColor = computed(() => receipt.value.booking.status === 'confirmed' ? 'success' : 'warning')
const sharedSeats = computed(() => receipt.value.seats.filter((seat) => Boolean(seat.sharedAt)))
const availableSeats = computed(() => receipt.value.seats.filter((seat) => !seat.sharedAt))
@@ -66,7 +62,7 @@ const statusRows = computed(() => {
return [
{
label: 'Status',
value: getBookingStatusLabel(receipt.value.booking.status),
value: getBookingStatusLabel(receipt.value.booking.status, receipt.value.booking.statusLabel),
isBadge: true
},
{
@@ -126,15 +122,15 @@ function buildSeatBundleText(
: null
return [
DINNER_EVENT_TITLE,
eventDetails.value.title,
`Guest: ${receipt.value.booking.customerName}`,
recipientLabel,
recipientPhoneLabel,
`Seats: ${seats.map((seat) => getSeatLabel(seat.seatNumber)).join(', ')}`,
`Category: ${ticketLabel.value}`,
`Date: ${DINNER_EVENT_DATE_LABEL}`,
`Time: ${DINNER_EVENT_TIME_LABEL}`,
`Venue: ${DINNER_EVENT_VENUE}`,
`Date: ${eventDetails.value.dateLabel}`,
`Time: ${eventDetails.value.timeLabel}`,
`Venue: ${eventDetails.value.venue}`,
'',
...seats.flatMap((seat) => [
`${getSeatLabel(seat.seatNumber)}:`,
@@ -222,7 +218,7 @@ async function shareSeats() {
recipientPhone: shareForm.recipientPhone
})
const shared = await shareLink({
title: `${DINNER_EVENT_TITLE} seats`,
title: `${eventDetails.value.title} seats`,
text: shareText,
clipboardText: shareText,
successTitle: 'Seats ready',
@@ -289,7 +285,7 @@ async function shareSeat(seat: PublicBookingSeatWithUrl) {
try {
const shared = await shareLink({
title: `${DINNER_EVENT_TITLE} ${getSeatLabel(seat.seatNumber)}`,
title: `${eventDetails.value.title} ${getSeatLabel(seat.seatNumber)}`,
text: buildSeatBundleText([seat]),
clipboardText: buildSeatBundleText([seat]),
successTitle: 'Seat ready',
@@ -365,7 +361,7 @@ async function openBatchShare() {
<div class="space-y-1 text-center">
<UBadge label="Ticket Receipt" color="primary" variant="soft" class="rounded-full" />
<h1 class="text-2xl font-bold tracking-tight text-highlighted sm:text-3xl">
{{ DINNER_EVENT_TITLE }}
{{ eventDetails.title }}
</h1>
</div>