for (const p of list) { const o=document.createElement('option'); o.value=p.id; o.textContent=p.name; staffSelect.appendChild(o); } }); }); staffSelect.addEventListener('change', ()=>{ selected.staff_id = parseInt(staffSelect.value || '0'); dateInput.disabled = !selected.staff_id; slotsDiv.innerHTML = ''; bookForm.classList.add('hidden'); }); flatpickr('#dateInput', { locale:'es', minDate:'today', dateFormat:'Y-m-d', onChange:(sel)=>{ selected.date = sel[0] ? sel[0].toISOString().slice(0,10) : null; loadSlots(); }}); function loadSlots(){ slotsDiv.innerHTML = ''; bookForm.classList.add('hidden'); if (!selected.service_id || !selected.staff_id || !selected.date) return; const url = `api/appointments.php?action=slots&service_id=${selected.service_id}&staff_id=${selected.staff_id}&date=${selected.date}`; fetch(url).then(r=>r.json()).then(times=>{ if (!times.length){ slotsDiv.innerHTML = 'No hay horarios disponibles para esa fecha.'; return; } for (const t of times){ const b = document.createElement('button'); b.type='button'; b.textContent=t; b.className='px-3 py-2 rounded-xl border hover:bg-slate-50'; b.addEventListener('click', ()=>{ selected.time = t; renderForm(); }); slotsDiv.appendChild(b); } }) } function renderForm(){ bookForm.classList.remove('hidden'); feedback.textContent = `Turno seleccionado: ${selected.date} a las ${selected.time}`; } bookForm.addEventListener('submit', async (e)=>{ e.preventDefault(); const fd = new FormData(bookForm); const payload = Object.fromEntries(fd.entries()); payload.action = 'book'; payload.service_id = selected.service_id; payload.staff_id = selected.staff_id; payload.date = selected.date; payload.time = selected.time; const res = await fetch('api/appointments.php', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload)}); const json = await res.json(); if (json.ok){ feedback.className = 'text-sm text-emerald-600'; feedback.textContent = '¡Listo! Tu turno fue reservado.'; bookForm.reset(); // recargar calendario calendar.refetchEvents(); slotsDiv.innerHTML=''; bookForm.classList.add('hidden'); } else { feedback.className = 'text-sm text-red-600'; feedback.textContent = json.error || 'No se pudo reservar.'; } }) // Calendario (ocupados) const calendarEl = document.getElementById('calendar'); const calendar = new FullCalendar.Calendar(calendarEl, { initialView: 'timeGridWeek', locale: 'es', height: 720, firstDay: 1, headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' }, events: 'api/appointments.php?action=list' }); calendar.render();