Set checkout date
August 11, 2025 · AI Conversations
<style>
/* Toggle Button */
.toggle-btn {
transition: background 0.2s, color 0.2s;
}
.toggle-btn.active {
background: #00c48c !important;
color: #fff !important;
}
/* Calendar Containers */
.weekly-calendar,
.monthly-calendar {
margin: 30px 0;
font-family: Arial, sans-serif;
}
/* Table Styling */
.weekly-calendar table,
.monthly-calendar table {
width: 100%;
border-collapse: collapse;
text-align: center;
min-width: 220px;
margin-bottom: 0;
}
/* Table Headers and Cells */
.weekly-calendar th,
.weekly-calendar td,
.monthly-calendar th,
.monthly-calendar td {
border: none;
}
.weekly-calendar th {
text-align: center;
vertical-align: middle;
font-size: 12px;
}
.weekly-calendar td {
font-size: 14px !important;
font-weight: 600 !important;
}
.weekly-calendar th small {
font-size: 10px;
color: #666;
display: block;
margin-top: 2px;
}
.weekly-calendar th,
.monthly-calendar th {
}
.yith-wcbk-booking-form button#prev-week-btn ,.yith-wcbk-booking-form button#next-week-btn{
background: none;
border:none;
cursor: pointer;
}
.yith-wcbk-form-section-dates-wrapper .toggle-btn {
padding: 10px !important;
text-align: center;
font-size: 14px;
font-weight: 600;
}
.weekly-calendar .selected,
.monthly-calendar .selected {
color: #fff;
}
/* Monthly Calendar Layout */
.monthly-calendar {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.prev_month ,.next_month {
background: none;
border: none;
cursor: pointer;
}
.monthly-calendar caption {
font-weight: bold;
margin-bottom: 5px;
}
.monthly-calendar .day-checkbox {
display: none;
}
/* 2. Style the label as a box */
label[for^="day-"], label[for^="next-day-"] {
display: inline-block;
text-align: center;
font-weight: bold;
position: relative;
cursor: pointer;
}
/* 3. Show tick icon when checked */
.day-checkbox:checked + label[for^="day-"]::after {
content: "✔";
color: green;
font-size: 19px;
position: absolute;
top: -5px;
right: 0px;
background: #ccffcc;
width: 100%;
}
.monthly-calendar td:has(input.unavailable) {
background-color: #ffcccc !important;
border-radius: 5px;
padding: 5px 8px !important;
}
.monthly-calendar td.selected{
background: #00c48c !important;
border-radius: 5px;
padding: 5px 8px !important;
}
.monthly-calendar td:not(:first-child) {
background: #ccffcc;
border-radius: 5px;
}
/* Scroll Container */
.monthly-calendar-scroll {
width: 100%;
overflow-y: auto;
}
.monthly-calendar-scroll.scrollable {
max-height: 350px;
}
/* Calendar Block */
.strek-calendar-block {
margin-bottom: 24px;
background: #fff;
padding: 8px 0 16px 0;
}
.weekly-calendar .strek-calendar-block:last-child {
border-bottom: none;
}
.weekly-calendar td:has(input.unavailable) {
background-color: #ffcccc !important;
}
.weekly-calendar td.selected{
background: #00c48c !important;
}
/* Custom Checkbox */
.weekly-calendar .strek-checkbox {
appearance: none;
-webkit-appearance: none;
width: 20px;
height: 20px;
border: 2px solid #ccc;
border-radius: 4px;
outline: none;
cursor: pointer;
position: relative;
vertical-align: middle; /* default: available (green) */
transition: background 0.2s;
}
.weekly-calendar .strek-checkbox:checked::after {
content: "✔";
display: inline-block;
color: #ffffff;
font-size: 19px;
position: relative;
left: 2px;
top: 0px;
}
.weekly-calendar .week-checkbox.strek-checkbox.unavailable::after {
content: "✖"; /* Unicode cross */
color: red;
font-size: 19px;
position: absolute;
top: 0;
left: 2px;
}
.weekly-calendar .strek-checkbox.unavailable {
background: #ffcccc !important; /* unavailable (red) */
border-color: #ff8888;
border:none;
}
.weekly-calendar .strek-checkbox:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.weekly-calendar .strek-checkbox:checked {
background: #00c48c !important;
border-color: #00c48c;
border:none;
}
/* Weekly calendar specific styles */
.weekly-calendar td {
text-align: center;
vertical-align: middle;
position: relative;
padding: 0px !important;
}
.weekly-calendar td:not(:first-child){
background: #ccffcc;
border-radius: 5px;
}
.weekly-calendar tr{
border:none !important;
}
td small {
font-size: 10px;
line-height: 1.2;
margin-top: 4px;
display: none;
}
.woocommerce div.product form.cart table{
border-collapse: separate;
border-spacing: 12px;
}
</style>
<script>
let displayWeekly='<?php echo $displayWeekly; ?>';
let displayPerday='<?php echo $displayPerday; ?>';
const strekAvail = <?php echo json_encode($strek_avail); ?>;
const strekMonthIdx = {};
Object.keys(strekAvail).forEach(stekId => {
strekMonthIdx[stekId] = 0; // Start at first month for each strek
});
const allowedDays = <?php echo json_encode($product->get_allowed_start_days()); ?>; // 1=Monday, 5=Friday, etc.
console.log('Streak Availability Data:', strekAvail);
console.log('Allowed Days:', allowedDays);
document.addEventListener('DOMContentLoaded', function() {
const weekList = <?php echo json_encode($week_list); ?>;
const weeksToShow = <?php echo $weeks_to_show; ?>;
const loadedMonths = <?php echo json_encode($loaded_months); ?>;
let weekOffset = 0;
let currentMonthIdx = 0;
const notAvailableDates = <?php echo json_encode($not_available_dates); ?>;
// Helper function to check if any day in a week is unavailable
const weekHasUnavailableDates = (weekDates, notAvailableDates) => {
for (let i = 0; i < weekDates.length; i++) {
if (notAvailableDates.includes(weekDates[i])) {
return true;
}
}
return false;
};
// WEEKLY CALENDAR
const renderCalendar = () => {
let html = `<table><thead><tr><th>Stek</th>`;
// Table headers (weeks)
for (let i = 0; i < weeksToShow; i++) {
const weekIdx = weekOffset + i;
if (weekIdx >= weekList.length) break;
const w = weekList[weekIdx];
// Find allowed weekday (e.g. Friday) in this week
let allowedDate = null;
for (let d = 0; d < w.dates.length; d++) {
const dateObj = new Date(w.dates[d]);
// getDay: 0=Sunday, 1=Monday, ..., 5=Friday, 6=Saturday
// allowedDays uses 1=Monday, 7=Sunday (ISO)
// Convert to ISO format: Saturday=6 becomes 6, Sunday=0 becomes 7
const isoDay = dateObj.getDay() === 0 ? 7 : dateObj.getDay();
if (allowedDays.includes(isoDay)) {
allowedDate = w.dates[d];
break;
}
}
let thLabel = `Week ${w.week}`;
if (allowedDate) {
const dateObj = new Date(allowedDate);
const startObj = new Date(w.dates[0]);
const endObj = new Date(w.dates[w.dates.length - 1]);
const startStr = startObj.toLocaleDateString('nl-NL', { day: '2-digit', month: '2-digit' });
const endStr = endObj.toLocaleDateString('nl-NL', { day: '2-digit', month: '2-digit' });
thLabel += `<br><small>${startStr} to ${endStr}</small>`;
}
html += `<th>${thLabel}</th>`;
}
html += `</tr></thead><tbody>`;
// For each stek, create a row
Object.entries(strekAvail).forEach(([stekId, stekData]) => {
html += `<tr><td>${stekData.label}</td>`;
for (let i = 0; i < weeksToShow; i++) {
const weekIdx = weekOffset + i;
if (weekIdx >= weekList.length) break;
const w = weekList[weekIdx];
// Find allowed weekday in this week
let allowedDate = null;
for (let d = 0; d < w.dates.length; d++) {
const dateObj = new Date(w.dates[d]);
// Convert to ISO format: Saturday=6 becomes 6, Sunday=0 becomes 7
const isoDay = dateObj.getDay() === 0 ? 7 : dateObj.getDay();
if (allowedDays.includes(isoDay)) {
allowedDate = w.dates[d];
break;
}
}
// Check if this specific date is available for this specific stek
const isAvailable = allowedDate && stekData.available_dates.includes(allowedDate);
const unavailableClass = isAvailable ? '' : 'unavailable';
// Debug logging for this specific check
if (allowedDate) {
console.log(`Week ${w.week}: ${stekData.label} - Date: ${allowedDate}, Available: ${isAvailable}`);
// Show specific example for August 2nd
if (allowedDate === '2024-08-02') {
console.log(`🎯 August 2nd found! Week: ${w.week}, Resource: ${stekData.label}, Available: ${isAvailable}`);
}
}
html += `<td style="padding: 20px 10px;">
<input type="checkbox" class="week-checkbox strek-checkbox ${unavailableClass}"
id="week-check-${stekId}-${weekIdx}"
data-stek="${stekId}"
data-week="${w.week}"
data-year="${w.year}"
data-date="${allowedDate ? allowedDate : ''}"
${isAvailable ? '' : 'disabled'}>
${allowedDate
? `<br><small>${new Date(allowedDate).toLocaleDateString('nl-NL', { weekday: 'short', day: '2-digit', month: '2-digit' })}</small>`
: '<br><small>n.v.t.</small>'}
${isAvailable ? '<br><small style="color: green;">✓ Available</small>' : '<br><small style="color: red;">✗ Unavailable</small>'}
</td>`;
}
html += `</tr>`;
});
html += `</tbody></table>`;
document.getElementById('calendar-table-wrapper').innerHTML = html;
// Update navigation label
const navLabel = document.getElementById('week-navigation-label');
if (navLabel && weekList.length > 0) {
const firstWeek = weekList[weekOffset];
const lastWeek = weekList[Math.min(weekOffset + weeksToShow - 1, weekList.length - 1)];
if (firstWeek && lastWeek) {
const firstDate = new Date(firstWeek.start);
const lastDate = new Date(lastWeek.start);
lastDate.setDate(lastDate.getDate() + 6);
navLabel.textContent = `Weeks ${firstWeek.week} - ${lastWeek.week} (${firstDate.toLocaleDateString('nl-NL')} - ${lastDate.toLocaleDateString('nl-NL')})`;
}
}
// Selection highlight for checkboxes and event handlers
document.querySelectorAll('.weekly-calendar .week-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', () => {
const td = checkbox.closest('td');
if (checkbox.checked) {
// Uncheck all other week checkboxes across all streks
document.querySelectorAll('.weekly-calendar .week-checkbox').forEach(cb => {
if (cb !== checkbox) {
cb.checked = false;
cb.closest('td').classList.remove('selected');
}
});
td.classList.add('selected');
// Update the booking form fields
const strekId = checkbox.getAttribute('data-stek');
const productId = "<?php echo $product->get_id(); ?>";
const selectedDate = checkbox.getAttribute('data-date');
// Set the check-in (start date) field
const startDateInput = document.getElementById(`yith-wcbk-booking-start-date-${productId}`);
if (startDateInput) {
startDateInput.value = selectedDate;
startDateInput.dispatchEvent(new Event('input', { bubbles: true }));
startDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(startDateInput).datepicker) {
jQuery(startDateInput).datepicker('setDate', selectedDate);
}
}
// Set the check-out (end date) field to 7 days after check-in
const endDateInput = document.getElementById(`yith-wcbk-booking-end-date-${productId}`);
if (endDateInput) {
const dateObj = new Date(selectedDate);
dateObj.setDate(dateObj.getDate() + 7); // 7 days (week)
const yyyy = dateObj.getFullYear();
const mm = String(dateObj.getMonth() + 1).padStart(2, '0');
const dd = String(dateObj.getDate()).padStart(2, '0');
const endDate = `${yyyy}-${mm}-${dd}`;
endDateInput.value = endDate;
endDateInput.dispatchEvent(new Event('input', { bubbles: true }));
endDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(endDateInput).datepicker) {
jQuery(endDateInput).datepicker('setDate', endDate);
}
}
// Update strek dropdown
const select = document.querySelector(`#yith-wcbk-booking-resources-${productId} select.yith-wcbk-selector__field`);
if (select) {
select.value = strekId;
const event = new Event('change', { bubbles: true });
select.dispatchEvent(event);
const customItem = document.querySelector(`#yith-wcbk-booking-resources-${productId} .yith-wcbk-selector__item[data-key="${strekId}"]`);
if (customItem) {
customItem.click();
}
}
} else {
td.classList.remove('selected');
// Reset check-in, check-out, and strek resource dropdown when unchecked
const productId = "<?php echo $product->get_id(); ?>";
const startDateInput = document.getElementById(`yith-wcbk-booking-start-date-${productId}`);
if (startDateInput) {
startDateInput.value = '';
startDateInput.dispatchEvent(new Event('input', { bubbles: true }));
startDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(startDateInput).datepicker) {
jQuery(startDateInput).datepicker('setDate', null);
}
}
const endDateInput = document.getElementById(`yith-wcbk-booking-end-date-${productId}`);
if (endDateInput) {
endDateInput.value = '';
endDateInput.dispatchEvent(new Event('input', { bubbles: true }));
endDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(endDateInput).datepicker) {
jQuery(endDateInput).datepicker('setDate', null);
}
}
const select = document.querySelector(`#yith-wcbk-booking-resources-${productId} select.yith-wcbk-selector__field`);
if (select) {
select.value = '';
const event = new Event('change', { bubbles: true });
select.dispatchEvent(event);
}
}
});
});
};
document.getElementById('prev-week-btn')?.remove();
document.getElementById('next-week-btn')?.remove();
const navDiv = document.createElement('div');
navDiv.style.display = "flex";
navDiv.style.justifyContent = "center";
navDiv.style.marginBottom = "10px";
navDiv.innerHTML = `
<button type="button" id="prev-week-btn" style="display:<?php echo $displayWeekly; ?>;"> <img src="https://carplakes.newsoftdemo.info/wp-content/uploads/2025/07/left-chevron-svgrepo-com.svg" alt="Previous" width="25" height="25"> </button>
<div style="flex: 1; text-align: center; font-weight: bold;display:<?php echo $displayWeekly; ?>;" id="week-navigation-label">Select a week</div>
<button type="button" id="next-week-btn" style="display:<?php echo $displayWeekly; ?>;"> <img src="https://carplakes.newsoftdemo.info/wp-content/uploads/2025/07/right-chevron-svgrepo-com.svg" alt="Previous" width="25" height="25"> </button>
`;
document.getElementById('calendar-table-wrapper').before(navDiv);
document.getElementById('prev-week-btn').addEventListener('click', () => {
if (weekOffset - weeksToShow >= 0) {
weekOffset -= weeksToShow;
} else {
weekOffset = 0;
}
renderCalendar();
});
document.getElementById('next-week-btn').addEventListener('click', () => {
if (weekOffset + weeksToShow < weekList.length) {
weekOffset += weeksToShow;
renderCalendar();
}
});
// MONTHLY CALENDAR (one month at a time)
const renderMonthlyCalendar = () => {
if (loadedMonths.length === 0) {
document.getElementById('monthly-calendar-scroll').innerHTML = '<p>No months available.</p>';
document.getElementById('monthly-calendar-controls').style.display = 'none';
return;
}
document.getElementById('monthly-calendar-controls').style.display = 'none'; // Hide global controls
let html = '';
Object.entries(strekAvail).forEach(([stekId, stekData]) => {
html += renderStrekMonthBlock(stekId, stekData);
});
document.getElementById('monthly-calendar-scroll').innerHTML = html;
// Add event listeners for each strek's navigation
Object.keys(strekAvail).forEach(stekId => {
document.getElementById(`prev-month-btn-${stekId}`).addEventListener('click', () => {
if (strekMonthIdx[stekId] > 0) {
strekMonthIdx[stekId]--;
renderMonthlyCalendar();
}
});
document.getElementById(`next-month-btn-${stekId}`).addEventListener('click', () => {
if (strekMonthIdx[stekId] < loadedMonths.length - 1) {
strekMonthIdx[stekId]++;
renderMonthlyCalendar();
}
});
});
// Add scrollable class if needed
const strekCount = Object.keys(strekAvail).length;
const scrollDiv = document.getElementById('monthly-calendar-scroll');
if (strekCount > 2) {
scrollDiv.classList.add('scrollable');
} else {
scrollDiv.classList.remove('scrollable');
}
};
const renderStrekMonthBlock = (stekId, stekData) => {
const idx = strekMonthIdx[stekId];
const [year, month] = loadedMonths[idx].split('-').map(Number);
const availableDates = Array.isArray(stekData.available_dates) ? stekData.available_dates : [];
// Get first and last day of month
const firstDay = new Date(year, month - 1, 1);
const lastDay = new Date(year, month, 0);
const daysInMonth = lastDay.getDate();
let html = `<div class="strek-calendar-block">
<div style="font-weight:bold; margin-bottom:20px;">${stekData.label}</div>
<div style="text-align:center; margin-bottom:10px; display:flex; align-items: center; justify-content: space-between;">
<button type="button" id="prev-month-btn-${stekId}" class="prev_month"><img src="https://carplakes.newsoftdemo.info/wp-content/uploads/2025/07/left-chevron-svgrepo-com.svg" alt="Next" width="25" height="25"> </button>
<span style="font-weight:bold; margin:0 10px;">${firstDay.toLocaleString('default', { month: 'long', year: 'numeric' })}</span>
<button type="button" id="next-month-btn-${stekId}" class="next_month"><img src="https://carplakes.newsoftdemo.info/wp-content/uploads/2025/07/right-chevron-svgrepo-com.svg" alt="Next" width="25" height="25"></button>
</div>
<table>
<thead>
<tr>
<th>Sa</th><th>Su</th><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th>
</tr>
</thead>
<tbody>
<tr>`;
// Calculate the day of week for the 1st (Saturday=0)
let dayOfWeek = (firstDay.getDay() + 1) % 7;
// Previous month overflow days
const prevMonthLastDay = new Date(year, month - 1, 0); // Last day of previous month
const prevMonthYear = prevMonthLastDay.getFullYear();
const prevMonth = prevMonthLastDay.getMonth() + 1;
const prevMonthDate = prevMonthLastDay.getDate();
for (let i = dayOfWeek - 1; i >= 0; i--) {
const dateNum = prevMonthDate - i;
const dateStr = `${prevMonthYear}-${String(prevMonth).padStart(2, '0')}-${String(dateNum).padStart(2, '0')}`;
html += `<td style="background-color:#ffcccc;">
<input type="checkbox" class="day-checkbox strek-checkbox unavailable"
id="prev-day-${stekId}-${prevMonthYear}-${prevMonth}-${dateNum}"
data-date="${dateStr}"
data-stek="${stekId}"
disabled>
<label for="prev-day-${stekId}-${prevMonthYear}-${prevMonth}-${dateNum}">${dateNum}</label>
</td>`;
}
for (let day = 1; day <= daysInMonth; day++) {
if ((dayOfWeek % 7 === 0) && day !== 1) html += '</tr><tr>';
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const isAvailable = availableDates.includes(dateStr);
const unavailableClass = isAvailable ? '' : 'unavailable';
const disabledAttr = isAvailable ? '' : 'disabled';
const bgColor = isAvailable ? '#ccffcc' : '#ffcccc';
html += `<td style="background-color:${bgColor};">
<input type="checkbox" class="day-checkbox strek-checkbox ${unavailableClass}"
id="day-${stekId}-${year}-${month}-${day}"
data-date="${dateStr}"
data-stek="${stekId}"
${disabledAttr}>
<label for="day-${stekId}-${year}-${month}-${day}">${day}</label>
</td>`;
dayOfWeek++;
}
// Next month overflow days
const nextMonthYear = (month === 12) ? year + 1 : year;
const nextMonth = (month === 12) ? 1 : month + 1;
let nextMonthDay = 1;
while (dayOfWeek % 7 !== 0) {
const dateStr = `${nextMonthYear}-${String(nextMonth).padStart(2, '0')}-${String(nextMonthDay).padStart(2, '0')}`;
const isAvailable = availableDates.includes(dateStr);
const unavailableClass = isAvailable ? '' : 'unavailable';
const disabledAttr = isAvailable ? '' : 'disabled';
const bgColor = isAvailable ? '#ccffcc' : '#ffcccc';
html += `<td style="background-color:${bgColor};">
<input type="checkbox" class="day-checkbox strek-checkbox ${unavailableClass}"
id="next-day-${stekId}-${nextMonthYear}-${nextMonth}-${nextMonthDay}"
data-date="${dateStr}"
data-stek="${stekId}"
${disabledAttr}>
<label for="next-day-${stekId}-${nextMonthYear}-${nextMonth}-${nextMonthDay}">${nextMonthDay}</label>
</td>`;
nextMonthDay++;
dayOfWeek++;
}
html += '</tr></tbody></table></div>';
return html;
};
const renderSingleMonth = (year, month) => {
// For each strek, render a classic calendar
let html = '';
Object.entries(strekAvail).forEach(([stekId, stekData]) => {
// Get first and last day of month
const firstDay = new Date(year, month - 1, 1);
const lastDay = new Date(year, month, 0);
const daysInMonth = lastDay.getDate();
html += `<div class="strek-calendar-block">
<div style="font-weight:bold; margin-bottom:4px;">${stekData.label}</div>
<table>
<caption>${firstDay.toLocaleString('default', { month: 'long' })} ${year}</caption>
<thead>
<tr>
<th>Sa</th><th>Su</th><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th>
</tr>
</thead>
<tbody>
<tr>`;
// Calculate the day of week for the 1st (Saturday=0)
let dayOfWeek = (firstDay.getDay() + 1) % 7;
for (let i = 0; i < dayOfWeek; i++) html += '<td></td>';
for (let day = 1; day <= daysInMonth; day++) {
if ((dayOfWeek % 7 === 0) && day !== 1) html += '</tr><tr>';
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
html += `<td>
<input type="checkbox" class="day-checkbox strek-checkbox" id="day-${stekId}-${year}-${month}-${day}" data-date="${dateStr}" data-stek="${stekId}">
<label for="day-${stekId}-${year}-${month}-${day}">${day}</label>
</td>`;
dayOfWeek++;
}
while (dayOfWeek % 7 !== 0) { html += '<td></td>'; dayOfWeek++; }
html += '</tr></tbody></table></div>';
});
return html;
};
// Initial render
if(displayWeekly=='block'){
renderCalendar();
}else{
renderMonthlyCalendar();
}
document.getElementById('prev-month-btn').addEventListener('click', () => {
if (currentMonthIdx > 0) {
currentMonthIdx--;
renderMonthlyCalendar();
}
});
document.getElementById('next-month-btn').addEventListener('click', () => {
if (currentMonthIdx < loadedMonths.length - 1) {
currentMonthIdx++;
renderMonthlyCalendar();
}
});
document.addEventListener('change', function(e) {
if (
e.target.classList.contains('day-checkbox') &&
!e.target.disabled
) {
if (e.target.checked) {
// Uncheck all other day-checkboxes
document.querySelectorAll('.day-checkbox').forEach(cb => {
if (cb !== e.target) cb.checked = false;
});
const strekId = e.target.getAttribute('data-stek');
const productId = "<?php echo $product->get_id(); ?>";
const selectedDate = e.target.getAttribute('data-date');
// Set the check-in (start date) field and fire change event
const startDateInput = document.getElementById(`yith-wcbk-booking-start-date-${productId}`);
startDateInput.value = selectedDate;
// Fire both input and change events
startDateInput.dispatchEvent(new Event('input', { bubbles: true }));
startDateInput.dispatchEvent(new Event('change', { bubbles: true }));
// If a jQuery datepicker is attached, update it as well
if (typeof jQuery !== 'undefined' && jQuery(startDateInput).datepicker) {
jQuery(startDateInput).datepicker('setDate', selectedDate);
}
// Set the check-out (end date) field to one day after check-in
const endDateInput = document.getElementById(`yith-wcbk-booking-end-date-${productId}`);
if (endDateInput) {
// Calculate next day
const dateObj = new Date(selectedDate);
dateObj.setDate(dateObj.getDate() + 1);
// Format as yyyy-mm-dd
const yyyy = dateObj.getFullYear();
const mm = String(dateObj.getMonth() + 1).padStart(2, '0');
const dd = String(dateObj.getDate()).padStart(2, '0');
const nextDay = `${yyyy}-${mm}-${dd}`;
endDateInput.value = nextDay;
endDateInput.dispatchEvent(new Event('input', { bubbles: true }));
endDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(endDateInput).datepicker) {
jQuery(endDateInput).datepicker('setDate', nextDay);
}
}
// Strek dropdown logic (as before)
const select = document.querySelector(`#yith-wcbk-booking-resources-${productId} select.yith-wcbk-selector__field`);
if (select) {
select.value = strekId;
const event = new Event('change', { bubbles: true });
select.dispatchEvent(event);
const customItem = document.querySelector(`#yith-wcbk-booking-resources-${productId} .yith-wcbk-selector__item[data-key="${strekId}"]`);
if (customItem) {
customItem.click();
}
}
} else {
// Reset check-in, check-out, and strek resource dropdown when unchecked
const productId = "<?php echo $product->get_id(); ?>";
const startDateInput = document.getElementById(`yith-wcbk-booking-start-date-${productId}`);
if (startDateInput) {
startDateInput.value = '';
startDateInput.dispatchEvent(new Event('input', { bubbles: true }));
startDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(startDateInput).datepicker) {
jQuery(startDateInput).datepicker('setDate', null);
}
}
const endDateInput = document.getElementById(`yith-wcbk-booking-end-date-${productId}`);
if (endDateInput) {
endDateInput.value = '';
endDateInput.dispatchEvent(new Event('input', { bubbles: true }));
endDateInput.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(endDateInput).datepicker) {
jQuery(endDateInput).datepicker('setDate', null);
}
}
const select = document.querySelector(`#yith-wcbk-booking-resources-${productId} select.yith-wcbk-selector__field`);
if (select) {
select.value = '';
const event = new Event('change', { bubbles: true });
select.dispatchEvent(event);
}
}
}
});
});
</script>
allow monthly calender to select to multiple date and automatically set latest date to checkout field
Below is a drop‑in change for your existing script:
1) **Add this helper** anywhere above your current `document.addEventListener('change', …)` block (inside the same “):
function setDatepickerValue(inputEl, ymd) {
if (!inputEl) return;
inputEl.value = ymd || '';
inputEl.dispatchEvent(new Event('input', { bubbles: true }));
inputEl.dispatchEvent(new Event('change', { bubbles: true }));
if (typeof jQuery !== 'undefined' && jQuery(inputEl).datepicker) {
jQuery(inputEl).datepicker('setDate', ymd || null);
}
}
function ymdPlusDays(ymd, days) {
const d = new Date(ymd);
d.setDate(d.getDate() + days);
const yyyy = d.getFullYear();
const mm = String(d.getMonth() + 1).padStart(2, '0');
const dd = String(d.getDate()).padStart(2, '0');
return `${yyyy}-${mm}-${dd}`;
}
function recalcFromMonthlySelections(lastChangedCb, productId) {
// gather all checked, enabled day checkboxes
const checked = Array.from(document.querySelectorAll('.monthly-calendar .day-checkbox:checked:not(:disabled)'));
const dates = checked.map(cb => cb.getAttribute('data-date')).sort(); // lexicographic works for YYYY-MM-DD
const startDateInput = document.getElementById(`yith-wcbk-booking-start-date-${productId}`);
const endDateInput = document.getElementById(`yith-wcbk-booking-end-date-${productId}`);
if (dates.length === 0) {
setDatepickerValue(startDateInput, '');
setDatepickerValue(endDateInput, '');
return;
}
const minDate = dates[0];
const maxDate = dates[dates.length - 1];
// check-in = earliest selected day
setDatepickerValue(startDateInput, minDate);
// checkout = day after latest selected (so nights cover the last selected day)
setDatepickerValue(endDateInput, ymdPlusDays(maxDate, 1));
// If user just checked something, sync the strek/resource to that checkbox's strek
if (lastChangedCb && lastChangedCb.checked) {
const strekId = lastChangedCb.getAttribute('data-stek');
const select = document.querySelector(`#yith-wcbk-booking-resources-${productId} select.yith-wcbk-selector__field`);
if (select && strekId) {
select.value = strekId;
const ev = new Event('change', { bubbles: true });
select.dispatchEvent(ev);
const customItem = document.querySelector(`#yith-wcbk-booking-resources-${productId} .yith-wcbk-selector__item[data-key="${strekId}"]`);
if (customItem) customItem.click();
}
}
}
2) **Replace your current monthly `change` listener** (the one that starts with `document.addEventListener('change', function(e) { if (e.target.classList.contains('day-checkbox') …`) with this version (it enables multi‑select and styling without unchecking others):
document.addEventListener('change', function(e) {
if (!e.target.classList.contains('day-checkbox') || e.target.disabled) return;
// toggle cell highlight
const td = e.target.closest('td');
if (td) td.classList.toggle('selected', e.target.checked);
const productId = "<?php echo $product->get_id(); ?>";
recalcFromMonthlySelections(e.target, productId);
});
That’s it.
– You can now select **multiple available days** in the monthly view.
– The form will automatically set **start = earliest selected** and **end = latest selected + 1 day**.
– Unchecking any day re-calculates both fields.
– The **resource (strek)** switches to the strek of the **last clicked** checkbox (adjust if you want a different rule).
If you want the checkout to be the **same day as latest** (not +1), say the word and I’ll switch that line.
setDatepickerValue(endDateInput, ymdPlusDays(maxDate, 1));
to:
setDatepickerValue(endDateInput, maxDate);
So your updated `recalcFromMonthlySelections()` will be:
function recalcFromMonthlySelections(lastChangedCb, productId) {
const checked = Array.from(document.querySelectorAll('.monthly-calendar .day-checkbox:checked:not(:disabled)'));
const dates = checked.map(cb => cb.getAttribute('data-date')).sort();
const startDateInput = document.getElementById(`yith-wcbk-booking-start-date-${productId}`);
const endDateInput = document.getElementById(`yith-wcbk-booking-end-date-${productId}`);
if (dates.length === 0) {
setDatepickerValue(startDateInput, '');
setDatepickerValue(endDateInput, '');
return;
}
const minDate = dates[0];
const maxDate = dates[dates.length - 1];
// check-in = earliest selected day
setDatepickerValue(startDateInput, minDate);
// checkout = latest selected day (no +1)
setDatepickerValue(endDateInput, maxDate);
if (lastChangedCb && lastChangedCb.checked) {
const strekId = lastChangedCb.getAttribute('data-stek');
const select = document.querySelector(`#yith-wcbk-booking-resources-${productId} select.yith-wcbk-selector__field`);
if (select && strekId) {
select.value = strekId;
const ev = new Event('change', { bubbles: true });
select.dispatchEvent(ev);
const customItem = document.querySelector(`#yith-wcbk-booking-resources-${productId} .yith-wcbk-selector__item[data-key="${strekId}"]`);
if (customItem) customItem.click();
}
}
}
Do you also want me to make it so **when you uncheck the latest date**, the checkout automatically moves to the new latest selected date? That would make the behavior fully dynamic.