Hourly Rental using Bookings

Hi, all!

I’m using Wix Studio to try to create a custom booking experience for a client. They have some equipment rentals (3 packages) that can last 2-8 hours. I would like for the user to be able to select their requested date and rental times, and then be shown the booking calendar for that service and what times are available.

I have created multiple services for each 2 hour, 3 hour, etc. to try and make this easier. I’m just having some trouble figuring out how to correctly pass data to a calendar widget, or navigate to the calendar booking page directly based on the inputs.

Any help would be greatly appreciated!

@jacobg I know you have created some custom booking sites, I would love a few minutes of your time if possible!

Hey @ColtBoyd , sounds to me that you are starting a custom book flow. Is this correct?
Do you want to create a fully customizable solution or do you want to customize just a part of it?
Are you aware of the Booking Calendar page that you can create and when seamlessly continue to the booking form? Take a look:

@jacobg I have not seen that article yet, I will check it out! It will work in Studio also?
I don’t necessarily need a fully custom solution, if I can just add that end time detail to the time slot selection, to dynamically pick the correct package, it would be perfect!

Studio is not yet supported but Wix is working on this support and I hope it will be ready soon. For now it’s available for the classic editor.

I hope so too! I have a site already published and active and need to add a way to give a clean UI for booking the “hourly” rental and block off the required time. Any chance you have any ideas? If so, I would love to setup a 30-minute call if you have some spare time! I appreciate your help either way!

Hey ColtBoyd,

To start with, Is this service an appointment of a class session?
Either way, you need to start from querying the availability from this API queryAvailability - Velo API Reference - Wix.com.
This API returns an array of available slots.
If you want to book a 2 hour sessions but the slots are all 1 hour long, you need to look for combinations of slots that end and start at the same point. This is how you get the length you need.
Then you need to create an appointment/class session.
For this you can use createBooking - Velo API Reference - Wix.com API.
After booking is in CREATED status, call createCheckout - Velo API Reference - Wix.com API and redirect the customer to online payment with getCheckoutUrl - Velo API Reference - Wix.com API.

These will all be appointments. So, if I have 1 hour long services, and want to create a 4 hour booking, I can push a start and end time through the 1 hour service and have it create a 4 hour booking as 1 event essentially?

@jacobg am I able to push my available slots to a time picker for the user to select and end time? Again, if I could just get like 30 minutes of your time, I really think I could iron out the process. I know what I want to do, I just don’t know how…

Please take your time to practice, asking questions here or inside the Velo community is the prefereed way of communication.
WIth respect to your question, pushing the timeslots to timePicker is possible assuming you have the times for a single day but what if you have 2 dates with available slots at 10AM? How do you distinguish between them?
The right way would be to populate a datePIcker with available dates, and then, after the date was selected, to populate a timePicker with available times.
Please see https://www.wix.com/velo/reference/$w/datepicker/enableddateranges and https://www.wix.com/velo/reference/$w/timepicker/enabledtimes
Here is a short piece of code that implements such scenario:
The following code populates the datePicker and timePickers which are actually a dropdowns.

availableSlots = await getAvailableSlots(service._id, options);
    const datePickerOptions = []
    const dates = []
    availableSlots.forEach(availableSlot => {
        let string = new Date(availableSlot.slot.startDate).toLocaleDateString('en-US',{ weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })
        if (!dates.includes(string)) {
            dates.push(string);
            datePickerOptions.push({label: string, value: string});
        }
    })
    $w("#dayPicker").options = datePickerOptions;

The following code populates the timePicker, which is a dropdown in this case.

$w("#dayPicker").onChange((event, $w) => {
        $w("#slotPicker").disable()
        const selectedDate = new Date(event.target.value);
        findAvailableSlots(selectedDate);
    });

And here is the implementation of findAvailableSlots:

async function findAvailableSlots(dateString) {
    const startDateTime = getMidnight(dateString);
    const endDateTime = getNextMidnight(dateString);

    const options = {
        startDateTime,
        endDateTime
    };

    availableSlots = await getAvailableSlots(service._id, options);

    if (availableSlots.length === 0) {
        // Reset the time dropdown.
        $w("#slotPicker").options = [];
        $w("#slotPicker").placeholder = "No sessions this day";
        $w("#slotPicker").selectedIndex = undefined;
        $w("#slotPicker").disable();
    } else {
        // Populate the time dropdown with the start time of the available slot and store the 
        // available slots in the slot map by ID.
        $w("#slotPicker").options = availableSlots.map((availableSlot) => {
            let startTime = availableSlot.slot.startDate;
            let timeString = getTimeOfDay(new Date(startTime));
            return {
                label: timeString,
                value: startTime
            }
        });

        $w("#slotPicker").placeholder = "Pick a time";
        $w("#slotPicker").selectedIndex = undefined;
        $w("#slotPicker").enable();
    }
}

Then you get the selected slot when time is picked from dropdown

$w("#slotPicker").onChange((event) => {
        selectedSlot = availableSlots.find(availableSlot => availableSlot.slot.startDate === event.target.value);
    });

Good luck.