Velo: Blocking Off Time in the Wix Bookings Calendar

The Wix Bookings backend module lets you manage bookings resources using Velo APIs.

When managing staff resource schedules, a common use case is setting up the times that staff are available, and the times that they're not.

What if you want to block off some time in the middle of the work day when your staff resource is not available ? You can do this by using the createSession() function to create "blocked time". 

To set up blocked time, you need to create a session of type "EVENT" with a tag value of "Blocked". The session can be a single session or a recurring session.

In the first example, we'll create a function that takes a resource ID and creates a single blocked time session on the resource's schedule. We'll also see how to create a dropdown element containing all of your resources. Once we have that working, in the second example, we'll add some functionality to make recurring blocked time sessions.

Let's assume you already have some staff members defined. If you don't, take a look at Creating Bookings Resources using Velo, or create some using the dashboard Staff page.

Before we go on, you need to install the Bookings app. If you haven't installed it yet, here's how to do it.
  1. Select the Add Apps icon in the editor.
  1. Type "Bookings" in the search field and select the Wix Bookings App.

  2. Click "Add to Site."

Setting up our site page

Create a page with the elements shown above. Put the Recurrence Rule text and inRecurrenceRule input element inside the container box box1. In the Properties and Events panel for box1, select Collapsed under Default Values. Set the default text as shown above for the From, To, and Recurrence Rule input elements.

Timestamps and Recurrence Rules. Make sure that the format of the timestamps and recurrence rule are correct. To reduce complexity, we are not going to validate them in this tutorial.

Timestamp example: 2021-06-15T13:00:00.000-05:00 

Recurrence Rule example: FREQ=WEEKLY;INTERVAL=1;BYDAY=MO;UNTIL=20220101T000000Z.

Query Resources to Load the Dropdown Element.

We'll load the dropdown element with a list of resources, display the resource name and use the resource ID as the value.

Create a backend file called blockedSessions.web.js. This file will hold all of our backend code for this tutorial.  

First import the Permissions enum and webMethod function from wix-web-module, and then import the resources and sessions APIs from the wix-bookings-backend module.

Copy
1
import { Permissions, webMethod } from 'wix-web-module';
2
import { resources, sessions } from "wix-bookings-backend";

Create a function called getResourceList() that returns an array of all resources.

The code will look like this:

Copy
1
import { Permissions, webMethod } from 'wix-web-module';
2
import { resources, sessions } from 'wix-bookings-backend';
3
4
export const getResourceList = webMethod(Permissions.Anyone, async () => {
5
6
try {
7
const results = await resources.queryResourceCatalog().find();
8
return results.items;
9
} catch (error) {
10
return error;
11
}
12
});

Now in your page code, create the loadResourceDropdown() function to load the dropdown element. Call the loadResourceDropdown() function from the onReady code block so the dropdown is loaded when the page is displayed. 

Don't forget to import getResourceList from the APIs from the blockedSessions backend file. 

Add the following code to your page to load the  ddResource dropdown with resource names and their schedule IDs:

  • Call getResourceList() to get a list of all of your resources. 
  • Use the  map function to build the resourceSchedules array from the resource name and scheduleId for each resource in the resourceCatalog array.
  • Set the options property of the dropdown element to the array of resource names and schedule IDs.
Copy
1
import { getResourceList, createSingleBlockedSession } from 'backend/blockedSessions.web'
2
3
$w.onReady(function () {
4
loadResourceDropdown();
5
});
6
7
8
export async function loadResourceDropdown() {
9
let resourceCatalog = await getResourceList();
10
11
const resourceSchedules = resourceCatalog.map(resource1 => {
12
let resourceEntry = {
13
label: resource1.resource.name,
14
value: resource1.resource.scheduleIds[0]
15
};
16
return resourceEntry;
17
});
18
$w('#ddResource').options = resourceSchedules;
19
}

Now create an onClick function for the button that will gather the information we need, and call the function to create the blocking sessions.

Copy
1
export async function btnCreateSession_click(event) {
2
let fromDateTime = $w('#inFrom').value;
3
let toDateTime = $w('#inTo').value;
4
let scheduleID = $w('#ddResource').value;
5
try {
6
const session = await createSingleBlockedSession(scheduleID, fromDateTime, toDateTime);
7
console.log("Session", session);
8
} catch (err) {
9
console.error("Session creation failed.", err);
10
}
11
}

Create A Single Blocked Time

Now we can create our blocking session. Create a function in the blockedSessions.web.js backend code file called createSingleBlockedSession().

Copy
1
export const createSingleBlockedSession = webMethod(Permissions.Anyone, async (resourceScheduleId, startDate, endDate) => {
2
3
try {
4
const sessionInfo = {
5
scheduleId: resourceScheduleId,
6
start: {
7
timestamp: new Date(startDate),
8
},
9
end: {
10
timestamp: new Date(endDate),
11
},
12
type: "EVENT",
13
tags: ["Blocked"],
14
};
15
16
const options = { suppressAuth: true };
17
return sessions.createSession(sessionInfo, options);
18
} catch (error) {
19
console.error(error);
20
// Handle the error
21
}
22
});

Understanding the code.

Line 4: Create the sessionInfo object using the date from the function's parameters.
Lines 12,13: Set the session type to "EVENT" and the tag to "Blocked".
Line 16: If you want any user to be able to create a blocked time session, set the suppressAuth option to true.
Line 17: Call createSession() to create the blocked time session and return the session details to the calling function. This returns to the page code that called the createSingleBlockedSession() function, and the created session is displayed in the console.
The returned session looks like this:

Copy
1
{
2
"_id": "2mmoW0vwKcSFyxtOfCdMeoE8hsC05dc6rdVucf52tUuT6FFcAWCPTKHipQaFL7nOW9qlB9c6Fjm00bZxYfABQpF6kQSpWw6TqFx7",
3
"scheduleId": "278012f1-674e-4a2b-93d2-29f8894ee732",
4
"scheduleOwnerId": "3cdb6d0f-be29-450b-a2e0-184975d95cb3",
5
"start": {
6
"timestamp": "Tue Jun 15 2021 23:00:00 GMT+0300 (Israel Daylight Time)"
7
},
8
"end": {
9
"timestamp": "Wed Jun 16 2021 00:00:00 GMT+0300 (Israel Daylight Time)"
10
},
11
"status": "CONFIRMED",
12
"tags": [
13
"Blocked"
14
],
15
"type": "EVENT",
16
"notes": ""
17
}

Recurring Blocked Times

Now that we've seen single blocked times working, let's take it up a level and create a series of blocked times using recurrence rules.

Recurrence rules specify when and how often an event repeats. A session that repeats every second week on a Monday until January 7, 2022 at 8 AM, is specified using the following recurrence rule:"FREQ=WEEKLY;INTERVAL=2;BYDAY=MO;UNTIL=20220107T080000Z"

Page Code

When we defined our page, we set the container box to collapsed. Expand the box based on the checkbox cbRecurrence using the following code:

Copy
1
export function cbRecurring_click(event) {
2
3
if ($w('#cbRecurring').checked === true) {
4
$w('#box1').expand();
5
} else {
6
$w('#box1').collapse();
7
}
8
}

Now that we see the recurrence rule, we can use it to create recurring sessions.

Update the button's onClick  function with the code below, to add processing for recurring sessions. If the cbRecurring checkbox is checked, call  createRecurringBlockedSession(), passing the recurrence rule. Otherwise, call createSingleBlockedSession().

Copy
1
export async function btnCreateSession_click(event) {
2
let fromDateTime = $w('#inFrom').value;
3
let toDateTime = $w('#inTo').value;
4
let scheduleID = $w('#ddResource').value;
5
let recurrenceRule = $w('#inRecurrenceRule').value;
6
console.log(scheduleID, fromDateTime, toDateTime);
7
let session = "";
8
9
try {
10
if ($w('#cbRecurring').checked) {
11
session = await createRecurringBlockedSession(scheduleID, fromDateTime, toDateTime, recurrenceRule);
12
} else {
13
session = await createSingleBlockedSession(scheduleID, fromDateTime, toDateTime);
14
}
15
console.log("Session", session);
16
} catch (err) {
17
console.error("Session creation failed.", err);
18
}
19
}

Create A Recurring Blocked Time Session

Now we can create our recurring blocking session. Create a function in the blockedSessions.web.js backend code file called createRecurringBlockedSession().

In your page code, add createRecurringBlockedSession to your import statement.

Note: You must use the localDateTime objects for start and end when defining a recurring session. For single sessions you can use the timestamp properties.
Remember that localDateTime uses the business's timezone .

Copy
1
export const createRecurringBlockedSession = webMethod(Permissions.Anyone, async (resourceScheduleId, startDate, endDate, recurrenceRule) => {
2
3
try {
4
//Create the recurring session object, breaking the start and end dates into their components.
5
const sessionInfo = {
6
scheduleId: resourceScheduleId,
7
start: {
8
localDateTime: {
9
year: startDate.substr(0, 4),
10
monthOfYear: startDate.substr(5, 2),
11
dayOfMonth: startDate.substr(8, 2),
12
hourOfDay: startDate.substr(11, 2),
13
minutesOfHour: startDate.substr(14, 2),
14
},
15
},
16
end: {
17
localDateTime: {
18
year: endDate.substr(0, 4),
19
monthOfYear: endDate.substr(5, 2),
20
dayOfMonth: endDate.substr(8, 2),
21
hourOfDay: endDate.substr(11, 2),
22
minutesOfHour: endDate.substr(14, 2),
23
},
24
},
25
// Set the session type to "EVENT" and add "Blocked" to the tags array.
26
type: "EVENT",
27
tags: ["Blocked"],
28
recurrence: recurrenceRule,
29
};
30
31
//Set the option to suppress permissions checking.
32
const options = { suppressAuth: true };
33
return sessions.createSession(sessionInfo, options);
34
} catch (error) {
35
console.error(error);
36
// Handle the error
37
}
38
});

Understanding The Code

Line 5: Create the sessionInfo object. You have to break the dates into their components for the localDateTime objects. You cannot use the timestamp properties for recurring sessions.
Line 26: Set the session type to "EVENT".
LIne 27: Add "Blocked" to the tags array.
Line 32: If you want any user to be able to create a blocked time session, set the suppressAuth option to true.
Line 33: Call createSession() using the sessionInfo and options objects, and return the promise to the calling function on the site page.

You'll get a session object displayed on the console, similar to the one below.

Copy
1
{
2
"_id": "ce6e440d1ef941c08f0e317d75fe5cbc-885c479078d145f992b2bad2a2b5f151",
3
"notes": "",
4
"recurrence": "FREQ=WEEKLY;INTERVAL=1;BYDAY=TU;UNTIL=20220101T000000Z",
5
"scheduleId": "ce6e440d-1ef9-41c0-8f0e-317d75fe5cbc",
6
"scheduleOwnerId": "3df00036-ac5a-4f8b-bf0d-4f77b1795b1d",
7
"start": {
8
"localDateTime": {
9
"year": 2021,
10
"monthOfYear": 7,
11
"dayOfMonth": 1,
12
"hourOfDay": 9,
13
"minutesOfHour": 0
14
}
15
},
16
"end": {
17
"localDateTime": {
18
"year": 2021,
19
"monthOfYear": 7,
20
"dayOfMonth": 1,
21
"hourOfDay": 10,
22
"minutesOfHour": 0
23
}
24
},
25
"status": "UNDEFINED",
26
"tags": [
27
"Blocked"
28
],
29
"type": "EVENT"
30
}

Check that it Worked.

In addition to the returned session object, you can also check your calendar to confirm that the blocked time appears for your resource at the time that you specified.

All the Code

Below is all of the code used in the tutorial in one place.

Page Code

Copy
1
import { getResourceList, createSingleBlockedSession ,createRecurringBlockedSession} from 'backend/blockedSessions.web'
2
3
$w.onReady(function () {
4
loadResourceDropdown();
5
});
6
7
8
export async function loadResourceDropdown() {
9
let resourceCatalog = await getResourceList()
10
11
const resourceSchedules = resourceCatalog.map(resource1 => {
12
let resourceEntry = {
13
label: resource1.resource.name,
14
value: resource1.resource.scheduleIds[0]
15
}
16
return resourceEntry
17
})
18
$w('#ddResource').options = resourceSchedules;
19
}
20
21
export async function btnCreateSession_click(event) {
22
let fromDateTime = $w('#inFrom').value;
23
let toDateTime = $w('#inTo').value;
24
let scheduleID = $w('#ddResource').value;
25
let recurrenceRule = $w('#inRecurrenceRule').value;
26
console.log(scheduleID, fromDateTime, toDateTime);
27
let session = "";
28
29
try {
30
if ($w('#cbRecurring').checked) {
31
session = await createRecurringBlockedSession(scheduleID, fromDateTime, toDateTime, recurrenceRule);
32
} else {
33
session = await createSingleBlockedSession(scheduleID, fromDateTime, toDateTime);
34
}
35
console.log("Session", session);
36
} catch (err) {
37
console.error("Session creation failed.", err);
38
}
39
}
40
41
export function cbRecurring_click(event) {
42
43
if ($w('#cbRecurring').checked === true) {
44
$w('#box1').expand()
45
} else {
46
$w('#box1').collapse()
47
}
48
}

blockedSessions.web.js

Copy
1
import { Permissions, webMethod } from "wix-web-module";
2
import { resources, sessions } from "wix-bookings-backend";
3
4
export const getResourceList = webMethod(Permissions.Anyone, async () => {
5
6
try {
7
const results = await resources.queryResourceCatalog().find();
8
return results.items;
9
} catch (error) {
10
throw error;
11
}
12
});
13
14
export const createSingleBlockedSession = webMethod(Permissions.Anyone, async (resourceScheduleId, startDate, endDate) => {
15
16
const sessionInfo = {
17
scheduleId: resourceScheduleId,
18
start: {
19
timestamp: new Date(startDate),
20
},
21
end: {
22
timestamp: new Date(endDate),
23
},
24
type: "EVENT",
25
tags: ["Blocked"],
26
};
27
28
const options = { suppressAuth: true };
29
30
try {
31
return await sessions.createSession(sessionInfo, options);
32
} catch (error) {
33
throw error;
34
}
35
});
36
37
export const createRecurringBlockedSession = webMethod(Permissions.Anyone, async (resourceScheduleId, startDate, endDate, recurrenceRule) => {
38
39
//Create the recurring session object, breaking the start and end dates into their components.
40
const sessionInfo = {
41
scheduleId: resourceScheduleId,
42
start: {
43
localDateTime: {
44
year: startDate.substr(0, 4),
45
monthOfYear: startDate.substr(5, 2),
46
dayOfMonth: startDate.substr(8, 2),
47
hourOfDay: startDate.substr(11, 2),
48
minutesOfHour: startDate.substr(14, 2),
49
},
50
},
51
end: {
52
localDateTime: {
53
year: endDate.substr(0, 4),
54
monthOfYear: endDate.substr(5, 2),
55
dayOfMonth: endDate.substr(8, 2),
56
hourOfDay: endDate.substr(11, 2),
57
minutesOfHour: endDate.substr(14, 2),
58
},
59
},
60
// Set the session type to "EVENT" and add "Blocked" to the tags array.
61
type: "EVENT",
62
tags: ["Blocked"],
63
recurrence: recurrenceRule,
64
};
65
66
//Set the option to suppress permissions checking.
67
const options = { suppressAuth: true };
68
69
try {
70
return await sessions.createSession(sessionInfo, options);
71
} catch (error) {
72
throw error;
73
}
74
});
Was this helpful?
Yes
No