feat(bookings): implement ticket receipts and seat sharing system

Add receipt tokens and booking_seats table to track individual tickets
Create receipt and seat view pages with QR code generation
This commit is contained in:
2026-04-12 22:48:26 +08:00
parent 7f582b530c
commit 6194c96ead
15 changed files with 1663 additions and 61 deletions

View File

@@ -2,6 +2,11 @@ export type BookingMode = 'table' | 'pax'
export type TicketType = 'vip' | 'supporter'
export type BookingStatus = 'pending' | 'confirmed'
export const DINNER_EVENT_TITLE = 'DAP JOHOR 60th Anniversary Celebration'
export const DINNER_EVENT_DATE_LABEL = 'Saturday, 30 May 2026'
export const DINNER_EVENT_TIME_LABEL = '6:30 PM'
export const DINNER_EVENT_VENUE = "Yong Peng's Chee Ann Kor"
export const BOOKING_MODE_OPTIONS = [
{
value: 'table',
@@ -31,6 +36,7 @@ export const BOOKING_TICKET_CATALOG = [
export interface PublicBooking {
id: string
confirmationToken: string
receiptToken: string
customerName: string
customerPhone: string
bookingMode: BookingMode
@@ -47,6 +53,49 @@ export interface PublicBooking {
confirmedAt: string | null
}
export interface ReceiptBooking {
id: string
receiptToken: string
customerName: string
customerPhone: string
bookingMode: BookingMode
quantity: number
seatCount: number
ticketType: TicketType
unitPrice: number
totalPrice: number
status: BookingStatus
createdAt: string
confirmedAt: string | null
}
export interface PublicBookingSeat {
id: string
seatNumber: number
seatToken: string
recipientName: string | null
recipientPhone: string | null
sharedAt: string | null
createdAt: string
updatedAt: string
}
export interface PublicBookingSeatWithUrl extends PublicBookingSeat {
seatUrl: string
}
export interface PublicBookingReceipt {
booking: ReceiptBooking
receiptUrl: string
seats: PublicBookingSeatWithUrl[]
}
export interface PublicSeatReceipt {
booking: ReceiptBooking
seat: PublicBookingSeatWithUrl
receiptUrl: string
}
export interface BookingCapacitySettings {
totalTables: number | null
updatedAt: string | null
@@ -109,6 +158,10 @@ export function formatBookingCurrency(value: number) {
}).format(value)
}
export function getSeatLabel(seatNumber: number) {
return `Seat ${seatNumber}`
}
export function calculateBookingInventorySummary(
bookings: Pick<PublicBooking, 'bookingMode' | 'quantity' | 'seatCount' | 'status'>[],
settings: BookingCapacitySettings