|
1 | 1 | --- |
2 | | -sidebar_label: Integration with DHTMLX widgets |
3 | | -title: Integration with DHTMLX widgets |
4 | | -description: You can learn about the integration with DHTMLX widgets in the documentation of the DHTMLX JavaScript Booking library. Browse developer guides and API reference, try out code examples and live demos, and download a free 30-day evaluation version of DHTMLX Booking. |
| 2 | +sidebar_label: Integration with DHTMLX Scheduler |
| 3 | +title: Integration with DHTMLX Scheduler |
| 4 | +description: You can learn about the integration with DHTMLX Scheduler in the documentation of the DHTMLX JavaScript Booking library. Browse developer guides and API reference, try out code examples and live demos, and download a free 30-day evaluation version of DHTMLX Booking. |
5 | 5 | --- |
6 | 6 |
|
7 | | -# Integration with DHTMLX widgets |
| 7 | +# Integration with DHTMLX Scheduler |
8 | 8 |
|
9 | | -You can integrate DHTMLX Booking with such DHTMLX widgets as [Scheduler](https://docs.dhtmlx.com/scheduler/) and [Event Calendar](https://docs.dhtmlx.com/eventcalendar/). Check the examples below. |
| 9 | +This guide will show how to integrate the DHTMLX Booking widget with DHTMLX Scheduler. |
10 | 10 |
|
11 | | -## Integration with DHTMLX Scheduler |
| 11 | +## Main concepts |
12 | 12 |
|
13 | | - Please, also refer to [backend](https://github.com/DHTMLX/scheduler-booking-go). |
| 13 | +The integration primarily focuses on converting the Scheduler data into Booking slots. |
14 | 14 |
|
15 | | -<iframe src="https://snippet.dhtmlx.com/d5zbq3g3?mode=result" frameborder="0" class="snippet_iframe" width="100%" height="800"></iframe> |
| 15 | +- **Scheduler events vs. Booking slots:** |
| 16 | + - Scheduler handles events (e.g., single or recurring). |
| 17 | + - Booking generates available time slots from those events. |
| 18 | + |
| 19 | +So what you actually need is to generate booking slots from the schedule (the [snippet below](#example) shows how to generate booking slots from the doctor's schedule using JSON data). |
| 20 | + |
| 21 | +- **Recurring events limitation:** |
| 22 | + - Booking supports only weekly recurring events (defined as INTERVAL=1;FREQ=WEEKLY in the Scheduler). |
| 23 | + - Scheduler can handle any recurring pattern |
| 24 | + |
| 25 | +- **Timezone handling:** |
| 26 | + - Booking interprets timestamps in the local timezone. |
| 27 | + - You need to convert timestamps between global and local timezones before sending them to Booking (and vice versa). |
| 28 | + |
| 29 | +- **Slot creation strategy:** |
| 30 | + - Use the `slots` and `usedSlots` properties to build the schedule, ensuring that used slots are excluded. |
| 31 | + |
| 32 | + |
| 33 | +## Main steps for integration and rules for generating events |
| 34 | + |
| 35 | +We will show how how to generate booking slots from the doctor's schedule using JSON data. |
| 36 | + |
| 37 | +**Step 1. Retrieve the doctor's schedule data (e.g., /doctors/worktime), which may contain both recurring and single events.** |
| 38 | + |
| 39 | +Scheduler data example: |
| 40 | + |
| 41 | +~~~json |
| 42 | +[ |
| 43 | + { |
| 44 | + "doctor_id": 1, |
| 45 | + "start_date": "2025-03-18 02:00:00", |
| 46 | + "end_date": "2025-03-18 06:00:00" |
| 47 | + }, |
| 48 | + { |
| 49 | + "doctor_id": 1, |
| 50 | + "start_date": "2025-03-13 09:00:00", |
| 51 | + "end_date": "9999-02-01 00:00:00", |
| 52 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", |
| 53 | + "duration": 28800 |
| 54 | + }, |
| 55 | + { |
| 56 | + "doctor_id": 2, |
| 57 | + "start_date": "2025-03-13 20:00:00", |
| 58 | + "end_date": "9999-02-01 00:00:00", |
| 59 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=SA", |
| 60 | + "duration": 28800 |
| 61 | + } |
| 62 | +] |
| 63 | +~~~ |
| 64 | + |
| 65 | +**Step 2. Convert Scheduler events to Booking slots following the next rules.** |
| 66 | + |
| 67 | +**Rule 1:** Single event slot creation. |
| 68 | + |
| 69 | +For each single event in the schedule, convert the start and end times to Booking slots by creating an entry in the slots array, including the corresponding date (dates). |
| 70 | + |
| 71 | +Scheduler event: |
| 72 | + |
| 73 | +~~~json |
| 74 | +{ |
| 75 | + "doctor_id": 1, |
| 76 | + "start_date": "2025-03-18 02:00:00", |
| 77 | + "end_date": "2025-03-18 06:00:00" |
| 78 | +} |
| 79 | +~~~ |
| 80 | + |
| 81 | +Booking slot: |
| 82 | + |
| 83 | +~~~json |
| 84 | +{ |
| 85 | + "id": 1, |
| 86 | + "slotSize": 20, |
| 87 | + "slotGap": 5, |
| 88 | + "slots": [ |
| 89 | + { |
| 90 | + "from": "02:00", |
| 91 | + "to": "06:00", |
| 92 | + "dates": [ |
| 93 | + 1742256000000 // 2025-03-18 00:00:00 (timestamp) |
| 94 | + ] |
| 95 | + } |
| 96 | + ] |
| 97 | +} |
| 98 | +~~~ |
| 99 | + |
| 100 | +**Rule 2:** Recurring events. |
| 101 | + |
| 102 | +For recurring events, we use a weekly pattern. The start and end dates must be the same for each occurrence, as Booking only supports weekly recurring slots. |
| 103 | + |
| 104 | +Scheduler event (weekly on weekdays): the recurrence rule (rrule) specifies that the event repeats weekly on Monday, Tuesday, Wednesday, Thursday, and Friday. |
| 105 | + |
| 106 | +~~~json |
| 107 | +{ |
| 108 | + "doctor_id": 1, |
| 109 | + "start_date": "2025-03-13 09:00:00", |
| 110 | + "end_date": "9999-02-01 00:00:00", |
| 111 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", |
| 112 | + "duration": 28800 |
| 113 | +} |
| 114 | +~~~ |
| 115 | + |
| 116 | +Booking Slots: In Booking, the weekly schedule is represented as a single rule, with the same start and end times for all repeated events: |
| 117 | + |
| 118 | +~~~json |
| 119 | +{ |
| 120 | + "id": 1, |
| 121 | + "slotSize": 20, |
| 122 | + "slotGap": 5, |
| 123 | + "slots": [ |
| 124 | + { |
| 125 | + "from": "09:00", |
| 126 | + "to": "17:00", |
| 127 | + "days": [1, 2, 3, 4, 5] // Monday to Friday |
| 128 | + } |
| 129 | + ] |
| 130 | +} |
| 131 | +~~~ |
| 132 | + |
| 133 | +**Rule 3:** Scheduling an event that spans multiple days. |
| 134 | + |
| 135 | +If an event spans across multiple days (e.g., starts at 8 PM and ends at 4 AM), it should be split into two slots — one for each day. |
| 136 | + |
| 137 | +For example, when a doctor's shift starts on Saturday evening and lasts into Sunday morning, Booking can only generate slots within one day. In this case, we need to split the event into two separate rules: one for Saturday and another for Sunday. |
| 138 | + |
| 139 | +Scheduler event: |
| 140 | + |
| 141 | +~~~json |
| 142 | +{ |
| 143 | + "doctor_id": 2, |
| 144 | + "start_date": "2025-03-13 20:00:00", |
| 145 | + "end_date": "9999-02-01 00:00:00", |
| 146 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=SA", |
| 147 | + "duration": 28800 |
| 148 | +} |
| 149 | +~~~ |
| 150 | + |
| 151 | +Booking slot: |
| 152 | + |
| 153 | +~~~json |
| 154 | +{ |
| 155 | + "id": 2, |
| 156 | + "slotSize": 45, |
| 157 | + "slotGap": 5, |
| 158 | + "slots": [ |
| 159 | + { |
| 160 | + "from": "20:00", |
| 161 | + "to": "24:10", |
| 162 | + "days": [6] // Saturday |
| 163 | + }, |
| 164 | + { |
| 165 | + "from": "00:10", |
| 166 | + "to": "04:00", |
| 167 | + "days": [0] // Sunday |
| 168 | + } |
| 169 | + ] |
| 170 | +} |
| 171 | +~~~ |
16 | 172 |
|
17 | | -## Integration with DHTMLX Event Calendar |
| 173 | +**Rule 4:** Additional single events added to recurring events. |
18 | 174 |
|
19 | | - Please, also refer to [backend](https://github.com/DHTMLX/event-calendar-booking-go). |
| 175 | +In this case, a single event is added to a recurring schedule. The Booking slots are generated for both the recurring and the single events. The single event dates are added to the recurring event's dates array. |
20 | 176 |
|
21 | | -<iframe src="https://snippet.dhtmlx.com/c5eu8pdk?mode=result" frameborder="0" class="snippet_iframe" width="100%" height="800"></iframe> |
| 177 | +Scheduler events: |
| 178 | + |
| 179 | +- Repeating event: Doctor’s availability from 9:00 AM to 5:00 PM on weekdays. |
| 180 | +- Single event: Doctor is also available from 2:00 AM to 6:00 AM on March 18th and 19th. |
| 181 | + |
| 182 | +~~~json |
| 183 | +[ |
| 184 | + // recurring event |
| 185 | + { |
| 186 | + "doctor_id": 1, |
| 187 | + "start_date": "2025-03-13 09:00:00", |
| 188 | + "end_date": "9999-02-01 00:00:00", |
| 189 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", |
| 190 | + "duration": 28800 |
| 191 | + }, |
| 192 | + |
| 193 | + // single events |
| 194 | + { |
| 195 | + "doctor_id": 1, |
| 196 | + "start_date": "2025-03-18 02:00:00", |
| 197 | + "end_date": "2025-03-18 06:00:00" |
| 198 | + }, |
| 199 | + { |
| 200 | + "doctor_id": 1, |
| 201 | + "start_date": "2025-03-19 02:00:00", |
| 202 | + "end_date": "2025-03-19 06:00:00" |
| 203 | + } |
| 204 | +] |
| 205 | +~~~ |
| 206 | + |
| 207 | +Booking slots: |
| 208 | + |
| 209 | +- Merging events: The repeating event and single events are combined into one Booking rule. |
| 210 | +- If the single event has priority, its specific dates (March 18th and 19th) are added to the repeating event's rule. |
| 211 | +- If the single event needs to override the repeating one, it must not be added to the repeating event’s dates. |
| 212 | + |
| 213 | +~~~json |
| 214 | +{ |
| 215 | + "id": 1, |
| 216 | + "slotSize": 20, |
| 217 | + "slotGap": 20, |
| 218 | + "slots": [ |
| 219 | + { |
| 220 | + "from": "02:00", |
| 221 | + "to": "06:00", |
| 222 | + "dates": [ |
| 223 | + 1742256000000, // 2025-03-18 00:00:00 |
| 224 | + 1742342400000 // 2025-03-19 00:00:00 |
| 225 | + ] |
| 226 | + }, |
| 227 | + { |
| 228 | + "from": "09:00", |
| 229 | + "to": "17:00", |
| 230 | + "days": [1, 2, 3, 4, 5], |
| 231 | + "dates": [ |
| 232 | + 1742256000000, // 2025-03-18 00:00:00 |
| 233 | + 1742342400000 // 2025-03-19 00:00:00 |
| 234 | + ] |
| 235 | + } |
| 236 | + ] |
| 237 | +} |
| 238 | +~~~ |
| 239 | + |
| 240 | +**Rule 5:** Modifying a single instance of an recurring event. |
| 241 | + |
| 242 | +If a single instance of a recurring event is edited (e.g., time change for a specific date), generate a new slot with the updated time and date in the dates array, overriding the days array. |
| 243 | + |
| 244 | +Scheduler event: |
| 245 | + |
| 246 | +~~~json |
| 247 | +[ |
| 248 | + { |
| 249 | + "doctor_id": 1, |
| 250 | + "start_date": "2025-03-13 09:00:00", |
| 251 | + "end_date": "9999-02-01 00:00:00", |
| 252 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", |
| 253 | + "duration": 28800 |
| 254 | + }, |
| 255 | + { |
| 256 | + "doctor_id": 1, |
| 257 | + "start_date": "2025-03-14 03:00:00", |
| 258 | + "end_date": "2025-03-14 11:00:00", |
| 259 | + "recurring_event_id": "1", |
| 260 | + "original_start": "2025-03-14 09:00" |
| 261 | + } |
| 262 | +] |
| 263 | +~~~ |
| 264 | + |
| 265 | +Booking slot: |
| 266 | + |
| 267 | +~~~json |
| 268 | +{ |
| 269 | + "id": 1, |
| 270 | + "slotSize": 20, |
| 271 | + "slotGap": 5, |
| 272 | + "slots": [ |
| 273 | + { |
| 274 | + "from": "09:00", |
| 275 | + "to": "17:00", |
| 276 | + "days": [1, 2, 3, 4, 5] |
| 277 | + }, |
| 278 | + { |
| 279 | + "from": "03:00", |
| 280 | + "to": "11:00", |
| 281 | + "dates": [ |
| 282 | + 1741910400000 // 2025-03-14 03:00:00 (modified) |
| 283 | + ] |
| 284 | + } |
| 285 | + ] |
| 286 | +} |
| 287 | +~~~ |
| 288 | + |
| 289 | +**Rule 6:** Deleting a single instance of a recurring event |
| 290 | + |
| 291 | +When a single occurrence is removed from a recurring event in Scheduler, we need to update Booking rules to reflect this removal. This is done by creating a special rule for the removed date, using an empty time interval and the dates property (which has higher priority than days). |
| 292 | + |
| 293 | +Scheduler event: |
| 294 | + |
| 295 | +~~~json |
| 296 | +[ |
| 297 | + { |
| 298 | + "doctor_id": 5, |
| 299 | + "start_date": "2025-03-14 09:00:00", |
| 300 | + "end_date": "9999-02-01 00:00:00", |
| 301 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=TH,FR,SA,SU", |
| 302 | + "duration": 28800 |
| 303 | + }, |
| 304 | + { |
| 305 | + "doctor_id": 5, |
| 306 | + "start_date": "2025-03-23 09:00:00", |
| 307 | + "end_date": "2025-03-23 17:00:00", |
| 308 | + "recurring_event_id": "15", |
| 309 | + "original_start": "2025-03-23 09:00", |
| 310 | + "deleted": true |
| 311 | + } |
| 312 | +] |
| 313 | +~~~ |
| 314 | + |
| 315 | +Booking slot: |
| 316 | + |
| 317 | +~~~json |
| 318 | +{ |
| 319 | + "from": "09:00", |
| 320 | + "to": "17:00", |
| 321 | + "days": [4, 5, 6, 0] // Thursday to Sunday |
| 322 | +}, |
| 323 | +{ |
| 324 | + "from": "00:00", |
| 325 | + "to": "00:00", |
| 326 | + "dates": [ |
| 327 | + 1742688000000 // 2025-03-23 00:00:00 (deleted occurrence) |
| 328 | + ] |
| 329 | +} |
| 330 | +~~~ |
| 331 | + |
| 332 | +**Rule 7:** Events starting later than Booking start date |
| 333 | + |
| 334 | +If a recurring event starts after the Booking start date (default is today), create rules with empty time intervals for the dates prior to the event's start date. This simulates the dates being "removed" from the recurrence. |
| 335 | + |
| 336 | +Scheduler event: |
| 337 | + |
| 338 | +~~~json |
| 339 | +{ |
| 340 | + "id": "ffbe7628-25f4-4cbe-9127-3bc779d6bafa", |
| 341 | + "start_date": "2025-03-17 09:00:00", |
| 342 | + "end_date": "9999-02-01 00:00:00", |
| 343 | + "rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=SU,MO,TU,WE,TH,FR,SA", |
| 344 | + "duration": 28800 |
| 345 | +} |
| 346 | +~~~ |
| 347 | + |
| 348 | +Booking slots: |
| 349 | + |
| 350 | +~~~json |
| 351 | +{ |
| 352 | + "slots": [ |
| 353 | + { "from": "09:00", "to": "17:00", "days": [0, 1, 2, 3, 4, 5, 6] }, |
| 354 | + { "from": "00:00", "to": "00:00", "dates": [ |
| 355 | + 1741906800000, // March 14, 2025 |
| 356 | + 1741993200000, // March 15, 2025 |
| 357 | + 1742079600000 // March 16, 2025 |
| 358 | + ]} |
| 359 | + ] |
| 360 | +} |
| 361 | +~~~ |
| 362 | + |
| 363 | +**Step 3. Timezone Conversion** |
| 364 | + |
| 365 | +Ensure that the timestamps are converted from global time to the local time of the user's timezone before sending them to Booking. This ensures correct slot display in the Booking widget. |
| 366 | + |
| 367 | + |
| 368 | +## Example |
| 369 | + |
| 370 | +The snippet below demonstrates how to convert doctor schedules into booking slots. The doctors' schedules that include recurring and single-time events are fetched from the Scheduler widget via the `/doctors/worktime` URL, while the final booking slots generated from the scheduler data are provided by the `/units` URL. The slots are generated on the server-side. Please, also refer to [backend](https://github.com/DHTMLX/scheduler-booking-go). |
| 371 | + |
| 372 | +<iframe src="https://snippet.dhtmlx.com/d5zbq3g3?mode=result" frameborder="0" class="snippet_iframe" width="100%" height="800"></iframe> |
22 | 373 |
|
23 | 374 |
|
24 | | - |
25 | 375 |
|
26 | 376 |
|
27 | 377 |
|
0 commit comments