Reserve, then confirm
reserve holds the selected slot and refreshes the hold every 15 minutes. Nobody else can book it while you run your own step. confirm turns the hold into a booking; cancel releases it.
vue
<template>
<ZaptimeCalendar :config="config" @time-slot-changed="(s) => (slot = s)" />
<div v-if="slot && step === 'details'">
<input v-model="email" type="email" placeholder="Email" />
<button @click="hold">Continue to payment</button>
</div>
<div v-if="step === 'payment'">
<p>Slot is held for you. Complete the payment.</p>
<button @click="pay">Pay</button>
<button @click="release">Cancel</button>
</div>
<p v-if="step === 'done'">Booked!</p>
</template>
<script setup lang="ts">
import { onUnmounted, ref } from "vue";
import { ZaptimeCalendar, reserve, confirm, cancel } from "@zaptime/vue3";
import type { ZaptimeConfig } from "@zaptime/vue3";
import { stopReservationRefresh } from "@zaptime/core";
import type { TimeSlot } from "@zaptime/core";
const config: ZaptimeConfig = { token: import.meta.env.VITE_ZAPTIME_TOKEN, externalBooking: true };
const slot = ref<TimeSlot>();
const email = ref("");
const step = ref<"details" | "payment" | "done">("details");
let reservationUuid = "";
async function hold() {
const res = await reserve({ email: email.value });
reservationUuid = res.data.uuid;
step.value = "payment";
}
async function pay() {
try {
await chargeCustomer(reservationUuid); // your payment step
await confirm();
step.value = "done";
} catch {
await cancel();
step.value = "details";
}
}
async function release() {
await cancel();
step.value = "details";
}
onUnmounted(() => stopReservationRefresh());
async function chargeCustomer(uuid: string) {}
</script>Details passed to confirm (firstName, lastName, phone, customFields, guests) are merged into the reservation, so you can collect them after the hold.
