The best option when using an example is to make your own elements the same id names as the tutorial, that way you know that the code will be okay and you don’t need to go through changing any incorrect element id name.
Is your code as this albeit with the element id name changes and the service id changes.
Quick Book.
//-------------Imports-------------//
// Import the wix-data module for working with collections.
import wixData from "wix-data";
// Import the wix-bookings module for getting available service slots.
import wixBookings from "wix-bookings";
import {setVisitorId} from 'public/managevisitors.js'
//-------------Global Variables-------------//
let visitorId;
// The ID of the Free Consultation service from the Bookings/Services collection.
const serviceId = "371e7fc0-c04b-4a88-8c1b-d8abf5d4b493";
// Map of available slots.
let slotsMap = {};
//-------------Lightbox Setup-------------//
$w.onReady(function () {
visitorId = setVisitorId();
// Get today's date.
let today = new Date();
// List of the days of the week.
const daysOfTheWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
//-------------Dropdowns Setup-------------//
// Get a list of the next 7 days of the week, starting from today. Use that list to create
// another list with labels and values and use it to populate the dayPicker dropdown.
$w("#dayPicker").options = getWeekDays(today).map(day => {
return {
// Set the label to be the name of the day of the week and its formatted date (e.g Tue 18/12/2018).
label: `${daysOfTheWeek[day.date.getDay()]} ${day.date.toLocaleDateString("en-GB")}`,
// Set the value to be the ISO string representation of the date (e.g. 2018-12-17T22:00:00.000Z).
value: day.date.toISOString()
}
});
// When a day of the week is selected in the day dropdown, populate the time dropdown with the times of
// slots that are available on the selected day.
$w("#dayPicker").onChange((event, $w) => {
const selectedDate = new Date(event.target.value);
findAvailableSlots(selectedDate);
});
// When the submit button is clicked, check that all the fields are valid and then insert the requested slot's
// information into the pendingAppointments collection.
$w("#submitButton").onClick(() => validateAndSubmitForm());
});
async function findAvailableSlots(dateString) {
// Reset the slot map to be empty.
slotsMap = {};
// Get the beginning time of the selected date.
const startDateTime = getMidnight(dateString);
// Get the ending time of the selected date.
const endDateTime = getNextMidnight(dateString);
// Set the options object which contains the date restrictions.
const options = {
startDateTime,
endDateTime
};
// Get all available slots which are not already pending approval for the selected day.
const availableSlots = await getNonPendingAvailableSlots(serviceId, options);
// If no available slots are found:
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();
}
// Otherwise, when available slots are found:
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(slot => {
const uniqueId = new Date().getUTCMilliseconds().toString() // Generate a short unique ID to identify options in the slotPicker
slotsMap[uniqueId] = slot;
let startTime = slot.startDateTime;
let timeString = getTimeOfDay(startTime);
return {
label: timeString,
value: uniqueId
}
});
// Reset the time dropdown's placeholder text.
$w("#slotPicker").placeholder = "Pick a time";
// Reset the time dropdown, so no item is selected.
$w("#slotPicker").selectedIndex = undefined;
$w("#slotPicker").enable();
}
}
//-------------Form Submission-------------//
async function validateAndSubmitForm() {
// Hide the error state.
$w("#errorMessage").hide();
$w("#submitButton").disable();
// List of fields in the booking form.
const formFields = ["nameInput", "emailInput", "ageInput", "dayPicker", "slotPicker", "agreementCheckbox"];
// If all the fields have valid values:
if (formFields.every(input => $w(`#${input}`).valid)) {
// Get the selected slot object from the slot map.
const slot = slotsMap[$w("#slotPicker").value];
// Create a new request item to be inserted in the pendingAppointments collection containing the form field
// values, the slot object, and set its status to pending.
const newRequest = {
name: $w("#nameInput").value,
email: $w("#emailInput").value,
age: $w("#ageInput").value,
requestedSlot: slot,
visitorId: visitorId,
status: "PENDING"
};
// Insert the requested slot information into the pendingAppointments collection.
await wixData.insert("pendingAppointments", newRequest);
// Show the thank you state.
$w("#formGroup").hide();
$w("#thankYouText").show();
}
// If some of the fields have invalid values:
else {
// Show the error state.
$w("#errorMessage").show();
$w("#submitButton").enable();
}
}
//-------------Slot Availability Determination-------------//
// Get all available slots which are not already pending approval.
async function getNonPendingAvailableSlots(requestedServiceId, options = {}) {
// Get the IDs of all the appointments that have been requested but are still pending approval.
const pending = (await getPendingAppointments()).map(appointment => appointment.requestedSlot._id);
// Get all of the service's available slots during the given date range.
let availableSlots = (await wixBookings.getServiceAvailability(requestedServiceId, options)).slots;
// Filter out of the available slots all slots that are pending approval.
availableSlots = availableSlots.filter(slot => !pending.includes(slot._id));
// Return the filtered list.
return availableSlots;
}
// Get the appointments that are pending from the pendingAppointments collection.
async function getPendingAppointments() {
return (await wixData.query("pendingAppointments").find()).items.filter(item => item.status === "PENDING");
}
//-------------Date Helpers-------------//
// Get a list of the next 7 days of the week, starting from a given date.
function getWeekDays(startDate) {
// Create an empty list of days.
let weekDays = [];
// Get the midnight that started today's day.
let current = getMidnight(startDate);
// For 7 days:
for (let i = 0; i < 7; i++) {
// Add to the list of days an object with a running day ID and the day's date.
weekDays.push({
_id: "day" + i,
date: current
});
// Get the midnight of the next day.
current = getNextMidnight(current);
}
// Return the list of days.
return weekDays;
}
// Get the midnight that started the given date's day.
function getMidnight(date) {
// Create a new date which is a copy of the given date.
let midnight = new Date(date);
// Set the new date's time to the previous midnight.
midnight.setHours(0, 0, 0, 0);
// Return the new date.
return midnight;
}
// Get the midnight that starts the day after the given date.
function getNextMidnight(date) {
// Create a new date which is a copy of the given date.
let midnight = new Date(date);
// Set the new date's time to the next midnight.
midnight.setHours(24, 0, 0, 0);
// Return the new date.
return midnight;
}
// Get the time of the given date formatted as HH:MM AM/PM.
function getTimeOfDay(date) {
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }).toLowerCase();
}
Pending Appointments,
//-------------Imports-------------//
// Import the wix-data module for working with collections.
import wixData from "wix-data";
// Import the wix-bookings module for booking appointments.
import wixBookings from "wix-bookings";
// Import the wix-location module for sending emails for dismissed appointments.
import wixLocation from "wix-location";
//-------------Page Setup-------------//
$w.onReady(function () {
// When the pending requests dataset is ready:
$w("#pendingRequestsDataset").onReady(() => {
// If there are no pending requests:
if ($w("#pendingRequestsDataset").getTotalCount() === 0) {
// Show the no pending requests message.
$w("#noPendingRequests").show();
}
});
});
//-------------Repeater Setup-------------//
// Set up each item in the requests repeater as it is loaded.
export function requestsRepeater_itemReady($item, itemData, index) {
// Get the requested slot from the item's data.
const slot = itemData.requestedSlot;
// Get the requested slot's start date and time.
const start = new Date(slot.startDateTime);
// Populate the date field with the slot's start date.
$item("#date").text = getDate(start);
// Populate the time field with the slot's start time.
$item("#time").text = getTimeOfDay(start);
// Set the dismiss button to dismiss the appointment request when clicked.
$item("#dismissButton").onClick(async () => {
// Disable the dismiss and approve buttons.
$item("#dismissButton").disable();
$item("#approveButton").disable();
// Dismiss the appointment request.
await dismissRequest(itemData, index, $w);
});
// Set the approve button to approve the appointment request when clicked.
$item("#approveButton").onClick(async () => {
// Disable the dismiss and approve buttons.
$item("#dismissButton").disable();
$item("#approveButton").disable();
// Approve the appointment request.
await approveRequest(itemData, index);
});
}
// Set up each item in the dismissed requests repeater as it is loaded.
export function dismissedRequests_itemReady($item, itemData, index) {
// Set the contact button to create an email to the user whose request was dismissed.
$item("#emailButton").onClick(() => {
const subject = "Thanks For Getting in Touch";
wixLocation.to(`mailto:${itemData.email}?subject=${subject}`);
});
}
//-------------Request Dismissal-------------//
// Dismiss the requested appointment.
async function dismissRequest(pendingRequest, index, $w) {
// Dismiss the requested appointment.
// Set the requested appointment's status to dismissed.
pendingRequest.status = "DISMISSED";
// Update the requested appointment in the pendingAppointments collection.
await wixData.update("pendingAppointments", pendingRequest);
// Refresh the page's data and update page elements.
refreshData();
}
//-------------Request Approval-------------//
// Approve the requested appointment.
async function approveRequest(pendingRequest, index) {
// Get the requested appointment's slot object.
const slot = pendingRequest.requestedSlot;
// Get the requested appointment's service data.
const service = await getService(slot.serviceId);
// Create a form fields object with the values the user entered in the booking form.
let formFields = [{
// Set _id to the ID of the name field.
_id: getFieldId(service, "Name"),
// Set value to the name the user entered.
value: pendingRequest.name
},
{
// Set _id to the ID of the email field.
_id: getFieldId(service, "Email"),
// Set value to the email address the user entered.
value: pendingRequest.email
}
];
// Create the bookingInfo object needed when performing a booking. It consists of the
// requested appointment's slot and the form field values entered in the booking form.
const bookingInfo = {
slot,
formFields
};
try {
// Perform the booking for the requested appointment.
const bookingResponse = await wixBookings.checkoutBooking(bookingInfo);
// If the booking is confirmed:
if (bookingResponse.status === "Confirmed") {
// Approve the requested appointment.
// Set the requested appointment's status to approved.
pendingRequest.status = "APPROVED";
// Update the requested appointment in the pendingAppointments collection.
await wixData.update("pendingAppointments", pendingRequest);
// Refresh the page's data and update page elements.
refreshData();
}
// If the booking is not confirmed:
else {
// Enable the approve button.
$w("#approveButton").enable();
}
}
// If an error occurred in the booking process:
catch (error) {
// Enable the approve button.
$w("#approveButton").enable();
}
}
//-------------Service Helpers-------------//
// Get a service from the Services collection by ID.
async function getService(id) {
return wixData.get("Bookings/Services", id);
}
// Get a field ID from a service for a given label.
function getFieldId(service, label) {
return service.form.fields.filter(field => field.label === label)[0]._id;
}
//-------------Page Update-------------//
// Refresh the page's datasets and update all the elements that are connected to them.
function refreshData() {
// Refresh the pending requests dataset and update all the elements that are connected to it.
$w("#pendingRequestsDataset").refresh().then(() => {
// If there are no pending requests:
if ($w("#pendingRequestsDataset").getTotalCount() === 0) {
// Show the no pending requests message.
$w("#noPendingRequests").show();
}
});
// Refresh the dismissed requests dataset and update all the elements that are connected to it.
$w("#dismissedRequestsDataset").refresh();
}
//-------------Date Helpers-------------//
// Get the time of the given date formatted as HH:MM am/pm.
function getTimeOfDay(date) {
return date.toLocaleTimeString("en-GB", {hour: "2-digit", minute:"2-digit", hour12: true});
}
// Get the date of the given date formatted as DD/MM/YYYY.
function getDate(date) {
return date.toLocaleDateString("en-GB", {day: "numeric", month: "numeric", year: "numeric" });
}