Skip to content

ZaptimeCalendar component

ts
import { ZaptimeCalendar, useCalendarViewState, book, reserve, confirm, cancel } from "@zaptime/vue3";
import type { ZaptimeConfig } from "@zaptime/vue3";

Props

PropTypeDescription
configZaptimeConfigRequired. See the config reference. The prop is watched: replacing it or mutating a ref merges the new values into the calendar without a remount.
calendar-idstringOptional. Isolates the state of this instance. Required when several calendars share a page. Pass the same id to book, reserve, confirm, cancel and to every composable.
classstringForwarded to the calendar, form and success containers.

Events

EventPayloadWhen
booking-confirmedReservationResponseThe built-in form booked or rescheduled successfully. Not emitted with externalBooking: true.
time-slot-changedTimeSlot | undefinedThe selected time slot changed. undefined on deselect.
calendar-loadednoneInitialization finished: remote configuration fetched and the first month loaded. Also fires for a disabled event type.
vue
<ZaptimeCalendar
  :config="config"
  @booking-confirmed="(r) => track('booked', r.data.uuid)"
  @time-slot-changed="(slot) => (selected = slot)"
  @calendar-loaded="loading = false"
/>

ReservationResponse is { success: boolean; data: { uuid: string; userId: number; userName: string; userEmail: string } }. TimeSlot carries start and end as ISO strings. See Types.

TIP

The component shows its own success screen after a booking. Use booking-confirmed for analytics, closing a modal, or navigation. When redirectAfterBookingUrl is set the browser navigates away right after the booking, before your handler can do much.

Rendering states

  1. A spinner (min height 360px) until the remote configuration is loaded.
  2. The calendar.
  3. A "calendar disabled" panel when the event type is disabled in the dashboard.

Updating the config at runtime

Keep the config in a ref or computed and change it; the component merges the new value into its state.

vue
<script setup lang="ts">
import { computed, ref } from "vue";
import { ZaptimeCalendar } from "@zaptime/vue3";
import type { ZaptimeConfig } from "@zaptime/vue3";

const locale = ref("en");
const dark = ref(false);

const config = computed<ZaptimeConfig>(() => ({
  token: "<API_TOKEN>",
  locale: { preset: locale.value },
  theme: { mode: dark.value ? "dark" : "light" },
}));
</script>

<template>
  <select v-model="locale">
    <option value="en">English</option>
    <option value="de">Deutsch</option>
  </select>
  <label><input v-model="dark" type="checkbox" /> Dark</label>

  <ZaptimeCalendar :config="config" />
</template>

Multiple calendars on one page

Give every instance a unique calendar-id and pass it to any API call.

vue
<template>
  <ZaptimeCalendar calendar-id="sales" :config="{ token: SALES_TOKEN }" />
  <ZaptimeCalendar calendar-id="support" :config="{ token: SUPPORT_TOKEN }" />
</template>

<script setup lang="ts">
import { ZaptimeCalendar, book } from "@zaptime/vue3";

await book({ email: "john@doe.test", calendarId: "sales" });
</script>

Calendar state lives at module level. Two calendars without distinct ids (or two pages that mount a calendar with the same id) share selection and config.

Using in a modal

Mount the calendar only when the modal is open (v-if, not v-show). Initialization runs in onMounted and needs real viewport widths for the compact layout switch.

vue
<Dialog v-model:open="open">
  <ZaptimeCalendar v-if="open" :config="config" @booking-confirmed="open = false" />
</Dialog>

useCalendarViewState

Read or set which screen the component shows.

ts
import { useCalendarViewState } from "@zaptime/vue3";

const { view, calendarView, setView, setCalendarView } = useCalendarViewState(calendarId);

view.value; // "calendar" | "form" | "success"
calendarView.value; // "pickingDate" | "pickingTime" (compact mode only)

setView("calendar"); // reset the widget to the month grid after a host-side action

Responsive behaviour

The default layout is about 840px wide. Under a viewport width of 860px the component switches to the single-column compact layout (date first, then time) automatically. Set compact: true in the config to force it.

Re-exported API functions

book, reserve, confirm and cancel are re-exported from @zaptime/core for convenience. Everything else (composables, reschedule, error classes, types) is imported from @zaptime/core. See Working with Time Slots.