(() => { 'use strict'; const PTA = window.PTA; if (!PTA) throw new Error('PTA core doit être chargé avant vacation-calendar.js'); const { escapeHtml, readJsonResponse, apiErrorMessage, formatDate } = PTA.utils; let previewPeriods = []; const elements = () => ({ academy: document.querySelector('#vacation-academy'), calendarYear: document.querySelector('#vacation-calendar-year'), previewButton: document.querySelector('#preview-vacations'), previewMessage: document.querySelector('#vacation-preview-message'), previewPanel: document.querySelector('#vacation-preview-panel'), previewBody: document.querySelector('#vacation-preview-body'), selectAll: document.querySelector('#vacation-select-all'), saveSelected: document.querySelector('#save-selected-vacations'), savedBody: document.querySelector('#vacation-saved-body'), savedMessage: document.querySelector('#vacation-saved-message'), refresh: document.querySelector('#refresh-vacations'), manualForm: document.querySelector('#manual-vacation-form'), manualMessage: document.querySelector('#manual-vacation-message'), }); function setMessage(element, text = '', type = 'info') { if (!element) return; element.className = text ? `message message-${type}` : 'message'; element.textContent = text; } function sourceLabel(source) { return source === 'DATA_GOUV' ? 'API officielle' : 'Saisie manuelle'; } function renderPreview() { const el = elements(); if (!el.previewBody || !el.previewPanel) return; if (!previewPeriods.length) { el.previewBody.innerHTML = '
Aucune période proposée.
'; el.previewPanel.hidden = false; return; } el.previewBody.innerHTML = previewPeriods.map((period, index) => ` ${escapeHtml(period.annee_scolaire || '')} ${period.date_reprise_api ? `Reprise API : ${escapeHtml(formatDate(period.date_reprise_api))}` : ''} ${escapeHtml([period.zone, period.academie].filter(Boolean).join(' · ') || 'Non précisé')} `).join(''); el.previewPanel.hidden = false; if (el.selectAll) el.selectAll.checked = false; } async function preview() { const el = elements(); const academy = el.academy?.value.trim() || ''; const calendarYear = String(el.calendarYear?.value || '').trim(); if (!academy || !/^\d{4}$/.test(calendarYear)) { setMessage(el.previewMessage, 'Renseignez une académie et une année civile au format 2026.', 'warning'); return; } el.previewButton.disabled = true; setMessage(el.previewMessage, 'Consultation de l’API officielle en cours…', 'info'); if (el.previewPanel) el.previewPanel.hidden = true; try { const params = new URLSearchParams({ academy, year: calendarYear }); const response = await fetch(`api/preview_school_holidays.php?${params.toString()}`); const data = await readJsonResponse(response); if (!response.ok) throw new Error(apiErrorMessage(data, 'Impossible de consulter le calendrier scolaire.')); previewPeriods = Array.isArray(data.periods) ? data.periods : []; renderPreview(); const warnings = Array.isArray(data.warnings) ? data.warnings.filter(Boolean) : []; const baseMessage = data.message || `${previewPeriods.length} période(s) proposée(s). Aucune donnée n’a encore été enregistrée.`; const fullMessage = warnings.length ? `${baseMessage} Attention : ${warnings.join(' ')}` : baseMessage; setMessage(el.previewMessage, fullMessage, warnings.length ? 'warning' : (previewPeriods.length ? 'success' : 'warning')); } catch (error) { previewPeriods = []; setMessage(el.previewMessage, error.message, 'error'); } finally { el.previewButton.disabled = false; } } function selectedPreviewPeriods() { const el = elements(); return Array.from(el.previewBody?.querySelectorAll('.vacation-preview-row') || []) .filter((row) => row.querySelector('.vacation-import-check')?.checked) .map((row) => { const source = previewPeriods[Number(row.dataset.index)] || {}; return { libelle: row.querySelector('.vacation-preview-label')?.value.trim() || '', date_debut: row.querySelector('.vacation-preview-start')?.value || '', date_fin: row.querySelector('.vacation-preview-end')?.value || '', annee_scolaire: source.annee_scolaire || '', academie: source.academie || elements().academy?.value.trim() || '', zone: source.zone || '', source: 'DATA_GOUV', }; }); } async function savePeriods(periods, messageElement) { const response = await fetch('api/save_vacation_periods.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ csrf_token: window.PTA_CONFIG.csrfToken, periods, }), }); const data = await readJsonResponse(response); if (!response.ok) throw new Error(apiErrorMessage(data, 'Impossible d’enregistrer les périodes.')); setMessage(messageElement, data.message, 'success'); await loadSaved(); return data; } async function saveSelected() { const el = elements(); const periods = selectedPreviewPeriods(); if (!periods.length) { setMessage(el.previewMessage, 'Cochez au moins une période avant de l’enregistrer.', 'warning'); return; } el.saveSelected.disabled = true; try { await savePeriods(periods, el.previewMessage); el.previewBody?.querySelectorAll('.vacation-import-check').forEach((checkbox) => { checkbox.checked = false; }); if (el.selectAll) el.selectAll.checked = false; } catch (error) { setMessage(el.previewMessage, error.message, 'error'); } finally { el.saveSelected.disabled = false; } } async function saveManual(event) { event.preventDefault(); const el = elements(); const submit = el.manualForm?.querySelector('button[type="submit"]'); const period = { libelle: document.querySelector('#manual-vacation-label')?.value.trim() || '', date_debut: document.querySelector('#manual-vacation-start')?.value || '', date_fin: document.querySelector('#manual-vacation-end')?.value || '', annee_scolaire: document.querySelector('#manual-vacation-school-year')?.value.trim() || '', academie: document.querySelector('#manual-vacation-academy')?.value.trim() || '', zone: document.querySelector('#manual-vacation-zone')?.value.trim() || '', source: 'MANUEL', }; if (period.date_debut && period.date_fin && period.date_fin < period.date_debut) { setMessage(el.manualMessage, 'La date de fin doit être postérieure ou égale à la date de début.', 'warning'); return; } if (submit) submit.disabled = true; try { await savePeriods([period], el.manualMessage); document.querySelector('#manual-vacation-label').value = ''; document.querySelector('#manual-vacation-start').value = ''; document.querySelector('#manual-vacation-end').value = ''; document.querySelector('#manual-vacation-zone').value = ''; } catch (error) { setMessage(el.manualMessage, error.message, 'error'); } finally { if (submit) submit.disabled = false; } } function renderSaved(periods) { const el = elements(); if (!el.savedBody) return; if (!periods.length) { el.savedBody.innerHTML = '
Aucune période de vacances n’est encore enregistrée.
'; return; } el.savedBody.innerHTML = periods.map((period) => ` ${escapeHtml(period.libelle)} ${escapeHtml(formatDate(period.date_debut))} → ${escapeHtml(formatDate(period.date_fin))} ${escapeHtml(period.annee_scolaire || '')} ${escapeHtml([period.academie, period.zone].filter(Boolean).join(' · ') || 'Non précisé')} ${escapeHtml(sourceLabel(period.source))} `).join(''); } async function loadSaved() { const el = elements(); try { const response = await fetch('api/vacation_periods.php'); const data = await readJsonResponse(response); if (!response.ok) throw new Error(apiErrorMessage(data, 'Impossible de charger les périodes enregistrées.')); renderSaved(Array.isArray(data.periods) ? data.periods : []); setMessage(el.savedMessage, '', 'info'); } catch (error) { setMessage(el.savedMessage, error.message, 'error'); } } async function deletePeriod(button) { const row = button.closest('tr[data-period-id]'); const id = Number(row?.dataset.periodId || 0); if (!id || !confirm('Supprimer cette période de vacances ? Les journées concernées seront à nouveau considérées comme périscolaires.')) return; button.disabled = true; try { const response = await fetch('api/delete_vacation_period.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ csrf_token: window.PTA_CONFIG.csrfToken, period_id: id, }), }); const data = await readJsonResponse(response); if (!response.ok) throw new Error(apiErrorMessage(data, 'Suppression impossible.')); setMessage(elements().savedMessage, data.message, 'success'); await loadSaved(); } catch (error) { setMessage(elements().savedMessage, error.message, 'error'); button.disabled = false; } } function init() { const el = elements(); el.previewButton?.addEventListener('click', preview); el.saveSelected?.addEventListener('click', saveSelected); el.refresh?.addEventListener('click', loadSaved); el.manualForm?.addEventListener('submit', saveManual); el.selectAll?.addEventListener('change', () => { el.previewBody?.querySelectorAll('.vacation-import-check').forEach((checkbox) => { checkbox.checked = el.selectAll.checked; }); }); el.savedBody?.addEventListener('click', (event) => { const button = event.target.closest('.delete-vacation-period'); if (button) deletePeriod(button); }); loadSaved(); } PTA.modules.vacationCalendar = { init, loadSaved, preview }; })();