feat: send ticket receipts via WhatsApp and normalize phone numbers

Add WhatsApp API integration for automated receipt delivery
Enforce country codes for all phone number inputs (defaults to +60)
This commit is contained in:
2026-04-27 13:12:25 +08:00
parent faa998c7e1
commit c214d643dd
18 changed files with 208 additions and 28 deletions

View File

@@ -1,7 +1,12 @@
<script lang="ts" setup>
import type { FormError, FormSubmitEvent } from '@nuxt/ui'
import { isValidPhoneNumber, type PublicContact } from '~~/shared/auth'
import {
DEFAULT_PHONE_COUNTRY_CODE,
isValidPhoneNumber,
normalizePhoneNumber,
type PublicContact
} from '~~/shared/auth'
import type { CreateBookingResponse } from '~~/shared/booking'
import {
BOOKING_MODE_OPTIONS,
@@ -51,7 +56,7 @@ const personInCharge = computed(() => {
const form = reactive({
name: '',
phone: '',
phone: DEFAULT_PHONE_COUNTRY_CODE,
bookingMode: 'table' as BookingMode,
quantity: 1,
ticketType: 'vip' as TicketType
@@ -85,7 +90,7 @@ function validateBooking(state: typeof form): FormError[] {
if (!state.phone.trim()) {
errors.push({ name: 'phone', message: 'Please enter a contact number.' })
} else if (!isValidPhoneNumber(state.phone.trim())) {
errors.push({ name: 'phone', message: 'Use a valid phone number with 8 to 15 digits.' })
errors.push({ name: 'phone', message: 'Use a valid phone number with country code, e.g. +60123456789.' })
}
if (state.quantity < 1) {
@@ -117,7 +122,7 @@ async function bookTicket(event: FormSubmitEvent<typeof form>) {
method: 'POST',
body: {
customerName: form.name.trim(),
customerPhone: form.phone.trim(),
customerPhone: normalizePhoneNumber(form.phone),
bookingMode: form.bookingMode,
quantity: form.quantity,
ticketType: form.ticketType,
@@ -181,7 +186,7 @@ async function bookTicket(event: FormSubmitEvent<typeof form>) {
</UFormField>
<UFormField name="phone" label="Phone Number" required>
<UInput v-model="form.phone" size="xl" type="tel" class="w-full" placeholder="e.g. 0123456789" />
<UInput v-model="form.phone" size="xl" type="tel" class="w-full" placeholder="e.g. +60123456789" />
</UFormField>
</div>