Перейти к основному содержимому

Интеграция с DHTMLX Event Calendar

В этом руководстве показано, как интегрировать виджет DHTMLX Booking с DHTMLX Event Calendar. При интеграции события Event Calendar преобразуются в слоты Booking на стороне сервера.

Понимание основных концепций

В основе интеграции лежит преобразование событий Event Calendar в слоты Booking. Перед началом работы учтите следующее.

События Event Calendar и слоты Booking. Event Calendar управляет событиями — как одиночными, так и повторяющимися. Booking генерирует доступные временные слоты на основе этих событий. Пример ниже генерирует слоты бронирования из расписания врача, преобразуя JSON-данные на стороне сервера.

Ограничения повторяющихся событий. Booking поддерживает только еженедельно повторяющиеся события, заданные как FREQ=WEEKLY;INTERVAL=1 в Event Calendar. Event Calendar поддерживает любые шаблоны повторения, поэтому скройте остальные параметры повторения в форме Event Calendar.

Обработка часовых поясов. Booking интерпретирует временные метки в локальном часовом поясе. Если вы используете глобальные временные метки, преобразуйте их в локальный часовой пояс перед отправкой в Booking и обратно в UTC перед сохранением. Инструкции по преобразованию см. в разделе Преобразование данных UTC в локальный часовой пояс.

Стратегии слотов Booking. Выберите один из двух подходов для построения расписания:

  • slots и usedSlots — строить расписание и исключать занятые слоты (стратегия, рассматриваемая здесь)
  • availableSlots — явно перечислять доступные для бронирования слоты; подходит для событий без повторений

Пример

Пример ниже интегрирует Booking с Event Calendar, преобразуя расписания врачей в слоты бронирования. Интеграция использует четыре конечных точки данных:

  • /events — данные Event Calendar (расписания врачей) с повторяющимися и одиночными событиями; источник временных слотов для Booking
  • /units — итоговые слоты Booking, сгенерированные из данных /events на стороне сервера; см. пример бэкенда
  • /calendars — календари врачей; предоставляет информацию о врачах как для виджета Event Calendar, так и для Booking
  • /reservations — вспомогательная коллекция, визуализирующая usedSlots в режиме временной шкалы; содержит уже забронированные слоты из формы Booking

Преобразование событий в слоты — ключевой элемент интеграции. В следующем разделе описаны правила преобразования.

Преобразование событий в слоты Booking

Правила ниже описывают генерацию слотов бронирования из расписания врача на основе JSON-данных, преобразуемых на стороне сервера. Во всех примерах предполагается расписание на следующий период — с 2025-03-13 по 2027-03-13.

Правило 1. Создание слота из одиночного события

Для каждого одиночного события преобразуйте время начала и окончания в слот Booking. Добавьте запись в массив slots и укажите дату события в массиве dates.

Следующий фрагмент кода показывает одиночное событие Event Calendar:

{
"type": 1, // type — это идентификатор календаря
"start_date": "2025-03-18T02:00:00Z", // предполагаем даты в UTC
"end_date": "2025-03-18T06:00:00Z"
}

Следующий фрагмент кода показывает результирующий слот Booking:

{
"id": 1,
"slotSize": 20,
"slotGap": 5,
"slots": [
{
"from": "02:00",
"to": "06:00",
"dates": [
1742256000000 // 2025-03-18 00:00:00 (временная метка)
]
}
]
}

Правило 2. Преобразование повторяющегося события

Сопоставьте повторяющееся событие с еженедельным шаблоном. Дата начала и окончания повторяющегося события в Event Calendar должны совпадать с датами start и end в Booking. В противном случае создайте заглушки для дат до и после повторяющегося события (см. Правило 7).

Следующий фрагмент кода показывает повторяющееся событие Event Calendar, которое повторяется еженедельно по рабочим дням (с понедельника по пятницу):

{
"type": 1,
"start_date": "2025-03-13T09:00:00Z",
"end_date": "2025-03-13T17:00:00Z",
"recurring": true,
"RRULE": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=2027-03-13T23:59:59",
"STDATE": "2025-03-13T09:00:00Z",
"DTEND": "2027-03-13T00:00:00Z"
}

Booking представляет еженедельное расписание в виде единого правила с одинаковым временем начала и окончания для каждого рабочего дня.

Следующий фрагмент кода показывает результирующие слоты Booking:

{
"id": 1,
"slotSize": 20,
"slotGap": 5,
"slots": [
{
"from": "09:00",
"to": "17:00",
"days": [1, 2, 3, 4, 5] // с понедельника по пятницу
}
]
}

Правило 3. Разделение события, охватывающего несколько дней

Booking генерирует слоты в рамках одного дня. Если событие охватывает два дня (например, начинается в 20:00 и заканчивается в 4:00), разделите его на два слота — по одному на каждый день.

Например, смена врача, начинающаяся субботним вечером и заканчивающаяся воскресным утром, делится на два правила: одно для субботы и одно для воскресенья.

Следующий фрагмент кода показывает многодневное событие Event Calendar:

{
"type": 2,
"start_date": "2025-03-13T20:00:00Z",
"end_date": "2025-03-14T04:00:00Z",
"recurring": true,
"RRULE": "FREQ=WEEKLY;INTERVAL=1;BYDAY=SA;UNTIL=2027-03-13T23:59:59",
"STDATE": "2025-03-13T20:00:00Z",
"DTEND": "2027-03-13T00:00:00Z"
}

Следующий фрагмент кода показывает два результирующих слота Booking — по одному на каждый день:

{
"id": 2,
"slotSize": 45,
"slotGap": 5,
"slots": [
{
"from": "20:00",
"to": "24:10",
"days": [6] // суббота
},
{
"from": "00:10",
"to": "04:00",
"days": [0] // воскресенье
}
]
}

Правило 4. Добавление одиночного события к повторяющемуся расписанию

Если одиночное событие расширяет повторяющееся расписание, сгенерируйте слоты для обоих. Добавьте даты одиночного события в массив dates правила повторяющегося события.

В этом примере объединяются два события Event Calendar:

  • повторяющееся событие — доступность врача с 9:00 до 17:00 по рабочим дням
  • одиночное событие — дополнительная доступность с 2:00 до 6:00 18 и 19 марта

Следующий фрагмент кода показывает оба события Event Calendar:

[
// повторяющееся событие
{
"type": 1,
"start_date": "2025-03-13T09:00:00Z",
"end_date": "2025-03-13T17:00:00Z",
"recurring": true,
"RRULE": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=2027-03-13T23:59:59",
"STDATE": "2025-03-13T09:00:00Z",
"DTEND": "2027-03-13T00:00:00Z"
},
// одиночные события
{
"type": 1,
"start_date": "2025-03-18T02:00:00Z",
"end_date": "2025-03-18T06:00:00Z"
},
{
"type": 1,
"start_date": "2025-03-19T02:00:00Z",
"end_date": "2025-03-19T06:00:00Z"
}
]

Booking объединяет повторяющееся и одиночные события в одно правило. Даты одиночных событий (18 и 19 марта) имеют более высокий приоритет и добавляются в массив dates повторяющегося правила. О порядке приоритетов см. раздел Определение правил слотов.

Следующий фрагмент кода показывает объединённые слоты Booking:

{
"id": 1,
"slotSize": 20,
"slotGap": 20,
"slots": [
{
"from": "02:00",
"to": "06:00",
"dates": [
1742256000000, // 2025-03-18 00:00:00
1742342400000 // 2025-03-19 00:00:00
]
},
{
"from": "09:00",
"to": "17:00",
"days": [1, 2, 3, 4, 5],
"dates": [
1742256000000, // 2025-03-18 00:00:00
1742342400000 // 2025-03-19 00:00:00
]
}
]
}

Правило 5. Изменение одного экземпляра повторяющегося события

Если один экземпляр повторяющегося события изменяется (например, смещается время на одну дату), создайте новый слот с обновлённым временем. Добавьте дату в массив dates, который имеет более высокий приоритет над массивом days для этой даты.

Следующий фрагмент кода показывает повторяющееся событие и его изменённый экземпляр:

[
{
"type": 1,
"start_date": "2025-03-13T09:00:00Z",
"end_date": "2025-03-13T17:00:00Z",
"recurring": true,
"RRULE": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=2027-03-13T23:59:59",
"STDATE": "2025-03-13T09:00:00Z",
"DTEND": "2027-03-13T00:00:00Z"
},
{
"type": 1,
"start_date": "2025-03-14T03:00:00Z",
"end_date": "2025-03-14T11:00:00Z",
"recurring": false,
"recurringEventId": 1,
"originalStartTime": "2025-03-14T09:00:00Z"
},
]

Следующий фрагмент кода показывает правило повторения с переопределением для изменённой даты:

{
"id": 1,
"slotSize": 20,
"slotGap": 5,
"slots": [
{
"from": "09:00",
"to": "17:00",
"days": [1, 2, 3, 4, 5]
},
{
"from": "03:00",
"to": "11:00",
"dates": [
1741910400000 // 2025-03-14 03:00:00 (изменено)
]
}
]
}

Правило 6. Удаление одного экземпляра повторяющегося события

При удалении одного вхождения повторяющегося события отразите это удаление в правилах Booking. Создайте правило для удалённой даты с пустым временным интервалом и свойством dates, которое имеет более высокий приоритет над days.

Следующий фрагмент кода показывает повторяющееся событие и его отменённое вхождение:

[
{
"type": 5,
"start_date": "2025-03-14T09:00:00Z",
"end_date": "2025-03-14T17:00:00Z",
"recurring": true,
"RRULE": "FREQ=WEEKLY;INTERVAL=1;BYDAY=TH,FR,SA,SU;UNTIL=2027-03-13T23:59:59",
"STDATE": "2025-03-14T09:00:00Z",
"DTEND": "2027-03-13T00:00:00Z"
},
{
"type": 5,
"recurring": false,
"recurringEventId": 15,
"originalStartTime": "2025-03-23T09:00:00Z",
"status": "cancelled"
}
]

Следующий фрагмент кода показывает правило повторения с пустым интервалом для удалённой даты:

{
"id": 5,
"slotSize":60,
"slotGap":10,
"slots":[
{
"from": "09:00",
"to": "17:00",
"days": [4, 5, 6, 0] // с четверга по воскресенье
},
{
"from": "00:00",
"to": "00:00",
"dates": [
1742688000000 // 2025-03-23 00:00:00 (удалённое вхождение)
]
}
]
}

Правило 7. Обработка событий, начинающихся после даты начала Booking

Если повторяющееся событие начинается позже даты начала Booking (по умолчанию — сегодня, в этих примерах — 2025-03-13), создайте правила с пустыми временными интервалами для дат до начала события. Это исключит эти даты из повторения.

Следующий фрагмент кода показывает повторяющееся событие, начинающееся на четыре дня позже даты начала Booking:

{
"type": 5,
"start_date": "2025-03-17T09:00:00Z",
"end_date": "2025-03-17T17:00:00Z",
"recurring": true,
"RRULE": "FREQ=WEEKLY;INTERVAL=1;BYDAY=SU,MO,TU,WE,TH,FR,SA;UNTIL=2027-03-13T23:59:59",
"STDATE": "2025-03-17T09:00:00Z",
"DTEND": "2027-03-13T00:00:00Z"
}

Следующий фрагмент кода показывает правило повторения с пустыми интервалами для четырёх дат до начала события:

{
"id": 5,
"slotSize":60,
"slotGap":10,
"slots": [
{ "from": "09:00", "to": "17:00", "days": [0, 1, 2, 3, 4, 5, 6] },
{ "from": "00:00", "to": "00:00", "dates": [
1741820400000, // 13 марта 2025
1741906800000, // 14 марта 2025
1741993200000, // 15 марта 2025
1742079600000 // 16 марта 2025
]}
]
}