const countInput = document.getElementById('child_count');
const template = document.getElementById('child-template');
const childrenContainer = document.getElementById('children-fields');
const hint = document.getElementById('capacity-hint');
const calendar = document.getElementById('booking-calendar');
const monthLabel = document.getElementById('calendar-month-label');
const selectedInputs = document.getElementById('selected-slot-inputs');
const selectedCount = document.getElementById('selected-count');
const selectedDatesList = document.getElementById('selected-dates-list');
let slots = [];
let slotMap = new Map();
let selectedSlots = new Set();
let currentMonth = null;
let calendarStart = null;
let calendarEnd = null;
const monthNames = ['styczeń','luty','marzec','kwiecień','maj','czerwiec','lipiec','sierpień','wrzesień','październik','listopad','grudzień'];
const weekdayShort = ['Nd','Pon','Wt','Śr','Czw','Pt','Sob'];
function parseLocalDate(iso){
const [y,m,d] = iso.split('-').map(Number);
return new Date(y, m-1, d);
}
function isoDate(date){
return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,'0')}-${String(date.getDate()).padStart(2,'0')}`;
}
function selectedPrefillModel(){
return new URLSearchParams(window.location.search).get('model');
}
function maxCapacityAcrossSelected(){
if(selectedSlots.size === 0) return 8;
return Math.min(...[...selectedSlots].map(id => Number(slotMap.get(id)?.free || 0)));
}
function renderChildren(){
if(!childrenContainer || !template || !countInput) return;
const oldValues = [...childrenContainer.querySelectorAll('.child-card')].map(card => ({
name: card.querySelector('.child-name')?.value || '',
age: card.querySelector('.child-age')?.value || '',
model: card.querySelector('.child-model')?.value || 'undecided'
}));
const count = Number(countInput.value);
childrenContainer.innerHTML = '';
for(let i=1;i<=count;i++){
const node = template.content.cloneNode(true);
node.querySelector('.child-number').textContent = i;
const nameInput = node.querySelector('.child-name');
const ageInput = node.querySelector('.child-age');
const modelSelect = node.querySelector('.child-model');
nameInput.name = `child_name_${i}`;
ageInput.name = `child_age_${i}`;
modelSelect.name = `child_model_${i}`;
if(oldValues[i-1]){
nameInput.value = oldValues[i-1].name;
ageInput.value = oldValues[i-1].age;
modelSelect.value = oldValues[i-1].model;
} else if(i === 1 && selectedPrefillModel()) {
modelSelect.value = selectedPrefillModel();
}
childrenContainer.appendChild(node);
}
}
function updateHint(){
if(!hint || !countInput) return;
const count = Number(countInput.value);
if(selectedSlots.size === 0){
hint.textContent = `Zapisujesz ${count} ${count === 1 ? 'dziecko' : 'dzieci'}. Wybierz termin lub kilka terminów w kalendarzu.`;
return;
}
const minFree = maxCapacityAcrossSelected();
if(count <= minFree){
hint.textContent = `Wybrane terminy mają co najmniej ${minFree} wolnych stanowisk. Rezerwujesz ${count} ${count === 1 ? 'stanowisko' : 'stanowiska'} w każdym terminie.`;
} else {
hint.textContent = `Co najmniej jeden termin ma tylko ${minFree} wolnych stanowisk. Zmniejsz liczbę dzieci albo usuń ten termin.`;
}
}
function updateSelectedSummary(){
if(!selectedInputs || !selectedCount || !selectedDatesList) return;
selectedInputs.innerHTML = '';
const selected = [...selectedSlots]
.map(id => slotMap.get(id))
.filter(Boolean)
.sort((a,b) => a.date.localeCompare(b.date));
selected.forEach(slot => {
const input = document.createElement('input');
input.type = 'hidden'; input.name = 'slots'; input.value = slot.id;
selectedInputs.appendChild(input);
});
if(selected.length === 0){
selectedCount.textContent = 'Nie wybrano jeszcze terminu.';
selectedDatesList.innerHTML = '';
} else {
selectedCount.textContent = `Wybrane terminy: ${selected.length}`;
selectedDatesList.innerHTML = selected.map(slot =>
`${slot.label}`
).join('');
}
updateHint();
}
function toggleSlot(id){
const slot = slotMap.get(id);
if(!slot || slot.free <= 0) return;
const childCount = Number(countInput?.value || 1);
if(!selectedSlots.has(id) && childCount > slot.free){
hint.textContent = `Tego dnia są tylko ${slot.free} wolne stanowiska. Zmniejsz liczbę dzieci albo wybierz inny termin.`;
return;
}
if(selectedSlots.has(id)) selectedSlots.delete(id); else selectedSlots.add(id);
renderCalendar(); updateSelectedSummary();
}
function renderCalendar(){
if(!calendar || !currentMonth) return;
const year = currentMonth.getFullYear();
const month = currentMonth.getMonth();
monthLabel.textContent = `${monthNames[month]} ${year}`;
calendar.innerHTML = '';
const first = new Date(year, month, 1);
const last = new Date(year, month + 1, 0);
const mondayOffset = (first.getDay() + 6) % 7;
for(let i=0;i${day}${weekdayShort[dateObj.getDay()]}${slot.free > 0 ? `${slot.free} wolnych` : 'brak miejsc'}${slot.free > 0 ? '16–19' : ''}`;
} else {
cell.classList.add('no-slot');
cell.innerHTML = `${day}`;
}
calendar.appendChild(cell);
}
const prev = document.getElementById('prev-month');
const next = document.getElementById('next-month');
const prevMonth = new Date(year, month-1, 1);
const nextMonth = new Date(year, month+1, 1);
if(prev) prev.disabled = prevMonth < new Date(calendarStart.getFullYear(), calendarStart.getMonth(), 1);
if(next) next.disabled = nextMonth > new Date(calendarEnd.getFullYear(), calendarEnd.getMonth(), 1);
}
if(calendar){
const raw = document.getElementById('slots-data')?.textContent || '[]';
slots = JSON.parse(raw);
slotMap = new Map(slots.map(slot => [slot.id, slot]));
calendarStart = parseLocalDate(calendar.dataset.start);
calendarEnd = parseLocalDate(calendar.dataset.end);
const today = new Date();
const firstAllowed = new Date(calendarStart.getFullYear(), calendarStart.getMonth(), 1);
const lastAllowed = new Date(calendarEnd.getFullYear(), calendarEnd.getMonth(), 1);
let initial = new Date(today.getFullYear(), today.getMonth(), 1);
if(initial < firstAllowed) initial = firstAllowed;
if(initial > lastAllowed) initial = firstAllowed;
currentMonth = initial;
calendar.addEventListener('click', e => {
const button = e.target.closest('[data-slot-id]');
if(button) toggleSlot(button.dataset.slotId);
});
document.getElementById('prev-month')?.addEventListener('click', () => {
currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth()-1, 1); renderCalendar();
});
document.getElementById('next-month')?.addEventListener('click', () => {
currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth()+1, 1); renderCalendar();
});
selectedDatesList?.addEventListener('click', e => {
const button = e.target.closest('[data-remove-slot]');
if(button) toggleSlot(button.dataset.removeSlot);
});
renderCalendar(); updateSelectedSummary();
}
if(countInput){
document.getElementById('plus')?.addEventListener('click',()=>{
const max = selectedSlots.size ? maxCapacityAcrossSelected() : 8;
countInput.value = Math.min(Number(countInput.value)+1, max || 1);
renderChildren(); updateHint();
});
document.getElementById('minus')?.addEventListener('click',()=>{
countInput.value = Math.max(Number(countInput.value)-1, 1);
renderChildren(); updateHint();
});
renderChildren(); updateHint();
}
const signupForm = document.getElementById('signup-form');
signupForm?.addEventListener('submit', e => {
if(selectedSlots.size === 0){
e.preventDefault();
hint.textContent = 'Przed wysłaniem formularza wybierz co najmniej jeden termin w kalendarzu.';
document.querySelector('.calendar-fieldset')?.scrollIntoView({behavior:'smooth', block:'start'});
}
});