Контроль количества выбираемых слотов времени/дней для всех или различных услуг по отдельным правилам
Порядок оказания некоторых услуг может подразумевать минимальное количество часов бронирования, допустимый диапазон или строго заданное количество времени/дней.
Определенным образом прописав вводные данные (правила) в приведенном здесь коде, Вы можете добавить в Ваш виджет онлайн-записи специальную надстройку, ограничивающую возможность записаться на все или некоторые определенные услуги пока клиент не выберет заданное для них количество времени или дней.Фрагмент, в который необходимо внести изменения, совсем компактный и не требует навыков программирования (при возникновении каких-либо затруднений Вы можете обратиться в нашу службу поддержки):

Наглядный пример настройки
Приведем пример конструкции с единственным правилом, содержащим все возможные переменные (при этом обязательная из них только одна - slotsMin):
var SLOTS_COUNT_RULES = [
{ slotsMin: 2, serviceIDs: ["11111", "22222"], slotsSynName: "часов", slotsMax: 5 }
];
- правило соответствует двум услугам по прокату разных лодок от 2 до 5 часов
Назначение переменных
- slotsMin - число, ограничение минимального количества слотов. Не дает клиенту продолжить бронирование, пока не будет выбрано минимальное количество слотов.
Единственная обязательная переменная, правило может содержать только ее, и содержать ее должно любое правило.
Отсутствие ограничения минимального количества выражается значением { slotsMin: 1 }.
- serviceIDs - ID услуг, к которым применяется правило. Заключены в квадратные скобки, прописываются в кавычках через запятую, после последнего или единственного ID запятая не ставится. Если serviceIDs отсутствует, правило применяется ко всем услугам.
- slotsSynName - Ваше название слотов времени в родительном падеже в кавычках: "часов", "дней", "интервалов" и т. д. Если slotsSynName отсутствует, по умолчанию клиенту универсально предлагается выбрать количество "слотов".
- slotsMax - число, ограничение максимального количества слотов (при необходимости). Может быть равно минимальному ограничению - например, для услуг с фиксированным временным интервалом. В том числе возможно правило { slotsMin: 1, slotsMax: 1 }.
Оформление правил
В зависимости от поставленной задачи, правил можно прописать несколько или только одно.
Общий вид конструкции с правилами:

Код
Полностью скопируйте приведенный ниже код в раздел "Настройки -> Дополнительные CSS/JS -> JS", заменив содержимое конструкции var SLOTS_COUNT_RULES = [ ]; на Ваши правила:
<script>
var SLOTS_COUNT_RULES = [
{ slotsMin: 3, serviceIDs: ["11111", "22222", "33333"]}, // бронирование беседки минимум от 3 часов (3 беседки по разной цене, отдельные услуги)
{ slotsMin: 2, serviceIDs: ["44444"], slotsMax: 8 }, // катание на лодке от 1 до 4 часов при выборе получасовых интервалов (одна или несколько лодок по одной цене, одна услуга)
{ slotsMin: 3, serviceIDs: ["55555", "66666"], slotsSynName: "дней", slotsMax: 3 } // бронирование домика на 3 дня (2 домика по разной цене, отдельные услуги)
];
var INFO_TEXT = "Чтобы продолжить, выберите"; // подсказка необходимого количества слотов
var TEXT_COLOR_TIP = '#08a83d'; // цвет текста подсказки
var TEXT_COLOR_ALERT = '#ff3c00'; // цвет текста подсказки в процессе выбора
var BACKGROUND_COLOR = '#f5f5f5'; // цвет блока подсказки
var BORDER_COLOR = '#ececec'; // цвет границы блока подсказки
let countMsgAlert;
function slotsCountControl() {
let selectedServiceId = $('#service-data a[data-href].selected').attr('data-id');
if (!selectedServiceId) return;
let matchedRule = false;
matchedRule = SLOTS_COUNT_RULES.find(rule => { // поиск правила по selectedServiceId или с установленным slotsMin
return rule.slotsMin && (!rule.serviceIDs || rule.serviceIDs.includes(selectedServiceId));
});
if (!matchedRule) return;
if (matchedRule) {
let tBtn = $('.time-checkbox:checked').length;
let nextButton = $('.next-btn');
let { slotsMin, slotsSynName, slotsMax } = matchedRule;
if (!document.getElementById('countAlert')) {
countMsgAlert = document.createElement('div');
countMsgAlert.id = 'countAlert';
countMsgAlert.setAttribute('style', `display: inline-block; font-size: 120%; padding: 6px 20px; margin-top: 10px; text-align: center; background: ${BACKGROUND_COLOR}; border: 1px solid ${BORDER_COLOR}; border-radius: 6px; position: relative; left: 50%; transform: translateX(-50%);`);
if ($('#time-block').css('display') !== 'none') {
$('#dates-area__block').append(countMsgAlert);
} else if ($('#dates-area__calendar').css('display') !== 'none') {
$('#dates-area__calendar').append(countMsgAlert);
}
} else {
countMsgAlert = document.getElementById('countAlert');
}
nextButton.hide();
if (slotsMin > 1) {
countMsgAlert.innerHTML = INFO_TEXT + ' ' + (slotsSynName ? slotsSynName : 'слотов') + ': ' + (slotsMin - tBtn);
countMsgAlert.style.setProperty("color", `${TEXT_COLOR_TIP}`);
countMsgAlert.style.display = 'inline-block';
} else {
countMsgAlert.style.display = 'none';
}
if (slotsMin > 1 && tBtn < slotsMin && tBtn >= 1) {
nextButton.removeClass('active').hide();
countMsgAlert.innerHTML = INFO_TEXT + ' еще ' + (slotsSynName ? slotsSynName : 'слотов') + ': ' + (slotsMin - tBtn);
countMsgAlert.style.setProperty("color", `${TEXT_COLOR_ALERT}`);
countMsgAlert.style.display = 'inline-block';
} else if (slotsMin > 1 && tBtn < 1) {
nextButton.removeClass('active').hide();
countMsgAlert.innerHTML = INFO_TEXT + ' ' + (slotsSynName ? slotsSynName : 'слотов') + ': ' + (slotsMin - tBtn);
countMsgAlert.style.setProperty("color", `${TEXT_COLOR_TIP}`);
countMsgAlert.style.display = 'inline-block';
} else if (tBtn > slotsMax) {
nextButton.removeClass('active').hide();
countMsgAlert.innerHTML = INFO_TEXT + ' ' + (slotsSynName ? slotsSynName : 'слотов') + ' не более: ' + slotsMax;
countMsgAlert.style.setProperty("color", `${TEXT_COLOR_ALERT}`);
countMsgAlert.style.display = 'inline-block';
} else if (tBtn >= slotsMin && (!slotsMax || tBtn <= slotsMax)) {
nextButton.addClass('active').css({ display: 'inline-block' });
countMsgAlert.style.display = 'none';
}
} else {
return;
}
}
$('body').on('change', '.time-checkbox', function () { setTimeout(slotsCountControl, 20); });
$(document).ajaxComplete(function () { countMsgAlert = null; setTimeout(slotsCountControl, 30); });
</script>- комментарии напротив правил (желтым текстом) даны для ориентировки, их писать не обязательно
Примечание:
Совместно с применением данного скрипта рекомендуется скрыть отображение длительности и цены услуги для клиента, вместо этого обозначив их в названии и/или описании услуги.
Читайте также

