Я использую плагин Javascript easypick для создания средства выбора диапазона дат для бронирования определенного номера в отеле. Это выглядит так:
<script src = "https://cdn.jsdelivr.net/npm/@easepick/[email protected]/dist/index.umd.min.js"></script>
<input id = "datepicker"/>
<script>
const DateTime = easepick.DateTime;
const bookedDates = [
['2023-04-19', '2023-04-21'],
['2023-04-28', '2023-04-29'],
['2023-04-29', '2023-04-30']
].map(d => {
if (d instanceof Array) {
const start = new DateTime(d[0], 'YYYY-MM-DD');
const end = new DateTime(d[1], 'YYYY-MM-DD');
return [start, end];
}
return new DateTime(d, 'YYYY-MM-DD');
});
const picker = new easepick.create({
element: document.getElementById('datepicker'),
css: [
'https://cdn.jsdelivr.net/npm/@easepick/[email protected]/dist/index.css',
'https://easepick.com/css/demo_hotelcal.css',
],
plugins: ['RangePlugin', 'LockPlugin'],
RangePlugin: {
tooltipNumber(num) {
return num - 1;
},
locale: {
one: 'night',
other: 'nights',
},
},
LockPlugin: {
minDate: new Date(),
minDays: 2,
inseparable: true,
filter(date, picked) {
if (picked.length === 0) {
return date.inArray(bookedDates, '[)');
} else {
const incl = date.isBefore(picked[0]) ? '[)' : '(]';
return !picked[0].isSame(date, 'day') && date.inArray(bookedDates, incl);
}
},
},
autoApply: false
});
</script>
Код делает почти то, что должен делать. Если вы выберете 2023-04-18
или любой день раньше в качестве даты начала, станет возможным выбрать 2023-04-19
в качестве даты окончания. Это имеет смысл, потому что, хотя не должно быть возможности выбрать зарезервированную кем-то еще дату заезда, должна быть возможность выбрать ее в качестве даты выезда.
Моя проблема с последующими датами. 2023-04-21
отображается как зарезервированное, и все более поздние интервалы дат также сдвигаются на 1 день вперед. Это только косметическая проблема, потому что все, что позже 2023-04-19
, в любом случае невозможно выбрать. Но выглядит запутанно. Итак, как мне применить фильтр только к первой зарезервированной дате, которая идет после моего первого выбора? В данном случае это будет означать изменение состояния только 2023-04-19
.
В этой конфигурации: после выбора даты начала он отключит и затенит оставшиеся дни после первого дня ближайшего, уже существующего бронирования.
const DateTime = easepick.DateTime;
const bookedDates = [
['2023-04-19', '2023-04-21'],
['2023-04-28', '2023-04-29'],
['2023-04-29', '2023-04-30']
].map(d => {
if (d instanceof Array) {
const start = new DateTime(d[0], 'YYYY-MM-DD');
const end = new DateTime(d[1], 'YYYY-MM-DD');
return [start, end];
}
return new DateTime(d, 'YYYY-MM-DD');
});
const picker = new easepick.create({
element: document.getElementById('datepicker'),
css: [
'https://cdn.jsdelivr.net/npm/@easepick/[email protected]/dist/index.css',
'https://easepick.com/css/demo_hotelcal.css',
],
plugins: ['RangePlugin', 'LockPlugin'],
RangePlugin: {
tooltipNumber(num) {
return num - 1;
},
locale: {
one: 'night',
other: 'nights',
},
},
LockPlugin: {
minDate: new Date(),
minDays: 2,
inseparable: true,
filter(date, picked) {
if (picked.length === 0) {
return date.inArray(bookedDates, '[)');
} else {
const prevBooked = bookedDates.find(([start]) => start.isBefore(picked[0]));
const nextBooked = bookedDates.find(([start]) => start.isAfter(picked[0]));
if (!nextBooked) {
return date.inArray(bookedDates, '[)');
}
const ms = nextBooked[0].getTime() + 86400000;
const nextBookedDayAfter = new Date(ms);
if (nextBooked && date.isSame(nextBooked[0], 'day')) {
return false;
}
if (nextBooked && date.isSame(nextBookedDayAfter, 'day')) {
return true;
}
if (prevBooked && date.isBetween(prevBooked[0], prevBooked[1], '()')) {
return true;
}
if (nextBooked && date.isBetween(nextBooked[0], nextBooked[1], '()')) {
return false;
}
if (bookedDates.filter(([start]) => date.isSame(start, 'day')).length > 0) {
return true;
}
return false;
}
},
},
autoApply: false,
});
<script src = "https://cdn.jsdelivr.net/npm/@easepick/[email protected]/dist/index.umd.min.js"></script>
<input id = "datepicker"/>
Выглядит очень многообещающе, однако я обнаружил две ошибки. Попробуйте выбрать самую последнюю дату в качестве даты начала. Вы увидите, что возникает ошибка. Также попробуйте выбрать начальную дату из следующего месяца, а затем двигаться назад. Вы увидите, что вдруг становится возможным выбирать среди ранее забронированных дат.