SOLVED - Quick Booking dropdown display available dates/slots starting one week from now.

Hi!

Quick question for the code experts out there…

I made a quick booking page, like this one here: https://www.wix.com/corvid/example/quick-book-and-pending-appointments

So I have a dropdown to display the days that are available and then another dropdown for the time slots available. Currently the dropdown displays the days for 1 week starting today (the day I am filling out the form. But I want the dropdown to show 1 week starting from a week from today. So if am filling the form and today is Oct 29th, it would show me the options: Nov 5th, Nov 6th, Nov 7th and so forth up to Nov 11th.

So what do I need to configure or change in the code to make that happen?

Here’s the code that sets the date:

function getMidnight (date) {
 let midnight = new Date(date);
    midnight.setHours(0, 0, 0, 0);
 return midnight;
}

function getNextMidnight (date) {
 let midnight = new Date(date);
    midnight.setHours(24, 0, 0, 0);
 return midnight;
}

function getWeekDays (startDate) {
 let weekDays = [];
 let current = getMidnight(startDate);

 for (let i = 0; i < 7; i++) {
        weekDays.push({
            _id: "day" + i,
            date: current
        });
        current = getNextMidnight(current)
    }
 return weekDays;
}

Here’s the code that show the days available:

const serviceId = '7ac4b7cc-a26a-4a83-b4cb-6710de094dbb';
let slotsMap = {};

$w.onReady(function () {
 const today = new Date();
 const daysOfTheWeek = ["Dom","Seg","Ter","Qua","Qui","Sex", "Sáb"]
    $w('#dayPicker').options = getWeekDays(today).map(day => {
 return{
            label: `${daysOfTheWeek[day.date.getDay()]} ${day.date.toLocaleDateString("pt-BR")}`,
            value: day.date.toISOString()
            }
    });
    $w('#dayPicker').onChange((event, $w) => {
 const selectedDate = new Date(event.target.value);
        findAvailableSlots(selectedDate);
    });
     $w('#buttonSubmit').onClick(() => validadeAndSubmitForm());
});


Full booking code, if needed:

import wixBookings from 'wix-bookings';
import wixData from 'wix-data';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location'; 

const serviceId = '7ac4b7cc-a26a-4a83-b4cb-6710de094dbb';
let slotsMap = {};

$w.onReady(function () {
 const today = new Date();
 const daysOfTheWeek = ["Dom","Seg","Ter","Qua","Qui","Sex", "Sáb"]
    $w('#dayPicker').options = getWeekDays(today).map(day => {
 return{
            label: `${daysOfTheWeek[day.date.getDay()]} ${day.date.toLocaleDateString("pt-BR")}`,
            value: day.date.toISOString()
            }
    });
    $w('#dayPicker').onChange((event, $w) => {
 const selectedDate = new Date(event.target.value);
        findAvailableSlots(selectedDate);
    });
     $w('#buttonSubmit').onClick(() => validadeAndSubmitForm());
});

async function findAvailableSlots(dateString) {
    slotsMap = {};
 const startDateTime = getMidnight(dateString);
 const endDateTime = getNextMidnight (dateString);
 const options = {
        startDateTime,
        endDateTime
    };
 const availableSlots = await getNonPendingAvailableSlots(serviceId, options);

 if (availableSlots.length === 0) {
        $w("#slotPicker").options = []
        $w("#slotPicker").placeholder = "Indisponível"
        $w("#slotPicker").selectedIndex = undefined;
        $w("#slotPicker").disable();    
    }
 else  {
        $w("#slotPicker").options = availableSlots.map(slot => {
            slotsMap[slot._id] = slot;
 let startTime = slot.startDateTime;
 let timeString = getTimeOfDay(startTime);
 return {
                label: timeString,
                value: slot._id
            }
        });
        $w("#slotPicker").placeholder = "Horários disponíveis";
        $w("#slotPicker").selectedIndex = undefined;
        $w("#slotPicker").enable();
    }
}

async function validadeAndSubmitForm() {
    $w("#errorMessage").hide();
    $w("#buttonSubmit").disable();

 const formFields = ["inputNome", "inputSobrenome", "inputDN", "inputEmail", "inputWhatsApp", "dayPicker", "slotPicker"];

 if (formFields.every(input => $w(`#${input}`).valid)) {
 const slot = slotsMap[$w("#slotPicker").value];
 const newRequest = {
        nome: $w("#inputNome").value,
        sobrenome: $w('#inputSobrenome').value,
        dataNascimento: $w('#inputDN').value,
        email: $w('#inputEmail').value,
        whatsapp: $w('#inputWhatsApp').value,
        requestedSlot: slot,
        status: "PENDING"
    };
 await wixData.insert("pendingAppointments", newRequest);
    $w('#AnchorTop').scrollTo();
    showPagamento()
    }
 else {
        $w('#errorMessage').show();
        $w('#buttonSubmit').enable();
    }
}

async function getNonPendingAvailableSlots (requestedServiceId, options = {}) {
 const pending = (await getPendingAppointments()).map(appointment => appointment.requestedSlot._id);
 let availableSlots = (await wixBookings.getServiceAvailability(requestedServiceId, options)).slots;
    availableSlots = availableSlots.filter(slot => !pending.includes(slot._id));
 return availableSlots;
}

async function getPendingAppointments (){
 return (await wixData.query("pendingAppointments").find()).items.filter(item => item.status === "PENDING");
}

function getMidnight (date) {
 let midnight = new Date(date);
    midnight.setHours(0, 0, 0, 0);
 return midnight;
}

function getNextMidnight (date) {
 let midnight = new Date(date);
    midnight.setHours(24, 0, 0, 0);
 return midnight;
}

function getWeekDays (startDate) {
 let weekDays = [];
 let current = getMidnight(startDate);

 for (let i = 0; i < 7; i++) {
        weekDays.push({
            _id: "day" + i,
            date: current
        });
        current = getNextMidnight(current)
    }
 return weekDays;
}

function getTimeOfDay(date) {
 return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit"}).toLowerCase();
}

Take a look at the .minDate property.
Setting the minDate property prevents users from selecting dates before the minimum date.
However, it does not limit your ability to change the date picker’s value to one that preceeds minDate programmatically.

https://www.wix.com/corvid/reference/$w.DatePicker.html#minDate

Nice! Thanks. It looks like exactly what I need. I’m trying to figure out how to incorporate it in the code (code newbie). If you have any input on how to put it in there, please let me know. Thanks!

I just tried putting the code, I saw another post here on the forum and discovered sort of where I could put it. But I get an error saying: ‘minDate’ does not exist on ‘#daypicker’.

I think it would be because it’s not a normal date picker input? It’s a regular user input item that i coded to make it show dates…

So then either another solution to make the dates start showing 1 day from now would be needed or to change the user input item to a calendar and then figure out how to code that to show the booking available dates. I think the first option seems easier…

Any ideas?

I got it! Looking around here on the forum I found a code for something else but followed the principle and it worked!

So I just added this line of code:

today.setDate(today.getDate() + 2);

to the onReady function of my code, so it looks like this:

$w.onReady(function () {
    const today = new Date();
    today.setDate(today.getDate() + 2);
    const daysOfTheWeek = ["Dom","Seg","Ter","Qua","Qui","Sex", "Sáb"]
    $w('#dayPicker').options = getWeekDays(today).map(day => {
    return{
            label: `${daysOfTheWeek[day.date.getDay()]} ${day.date.toLocaleDateString("pt-BR")}`,
            value: day.date.toISOString()
            }
    });
    $w('#dayPicker').onChange((event, $w) => {
        const selectedDate = new Date(event.target.value);
        findAvailableSlots(selectedDate);
    });
    $w('#buttonSubmit').onClick(() => validadeAndSubmitForm());
});

PS: I actually set it up to show 2 days from today, instead of the full week from today I was initially thinking. That’s why the code show 2 instead of 7.