Booking Flow Components
Duration selector, calendar, time slots, add-ons, and cart summary components for building custom booking flows.
These components handle the interactive booking steps. The duration selector uses data you provide; the calendar, time slots, and add-on selector fetch data from the API when you call .load().
Duration Selector
A button group for choosing a booking duration.
<resytech-duration-selector show-label="true" label-text="Choose Duration"></resytech-duration-selector>Set the durations from your selected activity:
document.addEventListener('equipment-select', (e) => {
const selector = document.querySelector('resytech-duration-selector');
selector.durations = selectedActivity.durations;
});Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
selected | string | — | Duration UUID to show as selected |
show-label | boolean | true | Show heading label |
label-text | string | Duration | Label text |
Events
| Event | Detail |
|---|---|
duration-select | { duration: Duration } |
Calendar
Month calendar with availability and optional per-day pricing. Fetches data from the API.
<resytech-calendar
activity-id="uuid"
duration-id="uuid"
show-prices="true">
</resytech-calendar>The calendar auto-loads when activity-id is present on connect. For dynamic use, set properties and call .load():
const calendar = document.querySelector('resytech-calendar');
calendar.activityId = selectedActivity.uuid;
calendar.durationId = selectedDuration.uuid;
await calendar.load();Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
activity-id | string | — | Activity UUID (required for loading) |
duration-id | string | — | Duration UUID for pricing |
duration-mins | number | — | Duration in minutes (alternative to duration-id) |
cart-id | string | — | Cart ID for cart-aware availability |
selected | string | — | Pre-selected date (YYYY-MM-DD) |
show-prices | boolean | false | Show per-day pricing |
show-label | boolean | true | Show heading label |
label-text | string | Select a Date | Label text |
use-cart-calendar | boolean | false | Use cart calendar endpoint instead of activity calendar |
Events
| Event | Detail |
|---|---|
date-select | { date: string, day: ActivityCalendarDay } |
Month navigation (‹ ›) automatically re-fetches data. The calendar maintains its layout during loading — no height shift.
Time Slots
Grid of available time slots with price and optional remaining seats. Fetches from the API.
<resytech-timeslots
activity-id="uuid"
date="2025-06-15"
duration-id="uuid">
</resytech-timeslots>Typically loaded in response to a date selection:
document.addEventListener('date-select', async (e) => {
const slots = document.querySelector('resytech-timeslots');
slots.activityId = selectedActivity.uuid;
slots.date = e.detail.date;
slots.durationId = selectedDuration.uuid;
await slots.load();
});Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
activity-id | string | — | Activity UUID |
date | string | — | Date in YYYY-MM-DD format (required) |
duration-id | string | — | Duration UUID |
duration-mins | number | — | Duration in minutes (alternative) |
selected | number | — | Selected slot index |
show-label | boolean | true | Show heading label |
label-text | string | Select a Time | Label text |
show-seats | boolean | true | Show remaining seat count |
low-seats-threshold | number | 5 | Seats below this number show in red |
Events
| Event | Detail |
|---|---|
timeslot-select | { slot: ActivityTimeSlot } |
Add-on Selector
Checkbox list of eligible add-ons with images and pricing. Fetches from the API based on the current activity, date, time, and equipment selection.
document.addEventListener('timeslot-select', async (e) => {
const addons = document.querySelector('resytech-addon-selector');
addons.activityId = selectedActivity.uuid;
addons.date = selectedDate;
addons.time = '10:00';
addons.durationId = selectedDuration.uuid;
addons.equipment = [{ equipmentUuid: selectedEquipment.uuid, quantity: 1, seats: 1 }];
await addons.load();
});Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
activity-id | string | — | Activity UUID |
date | string | — | Booking date |
time | string | — | Booking time (HH:MM) |
duration-id | string | — | Duration UUID |
duration-mins | number | — | Duration minutes (alternative) |
show-label | boolean | true | Show heading label |
label-text | string | Add-ons | Label text |
Events
| Event | Detail |
|---|---|
addon-change | { selected: EligibleAddon[] } |
Reading Selections
const addons = document.querySelector('resytech-addon-selector');
const selected = addons.selectedAddons; // EligibleAddon[]The component renders nothing (no empty state) when no add-ons are eligible — it simply disappears from the page.
Cart Summary
Displays a price breakdown from a server shopping cart response. This is a display-only component — set the cart property from a cart API response.
const response = await api.cart.createOrUpdateCart({ cart: myCart });
if (response.success) {
const summary = document.querySelector('resytech-cart-summary');
summary.cart = response.cart;
}Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
show-title | boolean | true | Show "Order Summary" heading |
title-text | string | Order Summary | Heading text |
show-line-items | boolean | true | Show individual line items |
show-fees | boolean | true | Show taxes & fees row (expandable) |
Display
The summary shows:
- Line items (equipment, add-ons)
- Subtotal
- Discount with coupon code badge (if applied)
- Trip protection (if selected)
- Taxes & fees with expandable detail
- Gift card applied with code badge (if applied)
- Total
- Due now / due later split (for deposit bookings)
