Контроль количества выбираемых слотов времени/дней для всех или различных услуг по отдельным правилам

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

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

Наглядный пример настройки


Приведем пример конструкции с единственным правилом, содержащим все возможные переменные (при этом обязательная из них только одна - 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>

- комментарии напротив правил (желтым текстом) даны для ориентировки, их писать не обязательно

Примечание:

Совместно с применением данного скрипта рекомендуется скрыть отображение длительности и цены услуги для клиента, вместо этого обозначив их в названии и/или описании услуги.

Читайте также

Идеальные CRM-платформы для бассейнов: выбор и преимущества. Статья на сайте Rubitime
Идеальные CRM-платформы для бассейнов: выбор и преимущества. Статья на сайте Rubitime
В советское время все бассейны были бесплатными, но тогда они получали государственную финансовую поддержку...
Как приложение для аренды спецтехники упрощает управление бизнесом
Как приложение для аренды спецтехники упрощает управление бизнесом
Аренда спецтехники — это не просто передача техники в пользование...