diff --git a/assets/js/modules/agenda-modal.js b/assets/js/modules/agenda-modal.js index 842381a..de8551c 100644 --- a/assets/js/modules/agenda-modal.js +++ b/assets/js/modules/agenda-modal.js @@ -512,9 +512,261 @@ function initializeLangueFilter() { * @param {Object} eventData - Données de l'événement */ export function openCheckPresenceModal(eventData) { - // Logique pour ouvrir le modal de validation de présences - // (à implémenter selon besoin) - console.log('Ouverture du modal de validation des présences pour:', eventData); + const modal = document.getElementById('eventCheckPresenceModal'); + if (!modal) { + console.error('Modal eventCheckPresenceModal non trouvée'); + return; + } + + // Récupérer les données de l'événement + const eventId = eventData?.id || eventData?.extendedProps?.id || null; + const nbParticipants = eventData?.nb_participants || eventData?.extendedProps?.nb_participants || 0; + const eventType = eventData?.type || eventData?.extendedProps?.type || ''; + + // Vérifier que c'est bien un événement de groupe + if (eventType !== 'groupe') { + console.warn('openCheckPresenceModal appelée pour un événement non-groupe'); + return; + } + + // Vérifier que nb_participants est valide + const numParticipants = parseInt(nbParticipants, 10); + if (!numParticipants || numParticipants < 1) { + notifyError('Le nombre de participants n\'est pas valide'); + return; + } + + // Remplir les informations de l'événement + const eventInfoEl = document.getElementById('presence_event_info'); + if (eventInfoEl) { + const date = eventData?.date_rdv || eventData?.extendedProps?.date_rdv || ''; + const heure = eventData?.heure_rdv || eventData?.extendedProps?.heure_rdv || ''; + eventInfoEl.textContent = `Événement du ${date} à ${heure} - ${numParticipants} participant(s)`; + } + + // Définir l'event_id dans le formulaire + const eventIdInput = document.getElementById('presence_event_id'); + if (eventIdInput) { + eventIdInput.value = eventId; + } + + // Générer les lignes de présence + const tbody = document.getElementById('presence_rows'); + if (tbody) { + tbody.innerHTML = ''; + for (let i = 0; i < numParticipants; i++) { + const row = document.createElement('tr'); + row.innerHTML = ` + + + + + + + + + + + + `; + tbody.appendChild(row); + } + + // Initialiser l'autocomplétion pour tous les champs nom + initializePresenceAutocomplete(); + } + + // Fermer le modal principal d'événement s'il est ouvert + const eventModal = document.getElementById('eventModal'); + if (eventModal) { + const eventBsModal = window.bootstrap && window.bootstrap.Modal ? window.bootstrap.Modal.getInstance(eventModal) : null; + if (eventBsModal) { + eventBsModal.hide(); + } + } + + // Attendre un peu que le modal principal se ferme avant d'ouvrir le nouveau + setTimeout(() => { + // Ouvrir le modal de validation des présences + if (window.bootstrap && window.bootstrap.Modal) { + const bsModal = new window.bootstrap.Modal(modal); + bsModal.show(); + + // Ajouter un event listener pour rouvrir le modal principal quand on ferme + modal.addEventListener('hidden.bs.modal', function() { + // Rouvrir le modal principal d'événement + if (eventModal && window.bootstrap && window.bootstrap.Modal) { + const newEventModal = new window.bootstrap.Modal(eventModal); + newEventModal.show(); + } + }, { once: true }); // Une seule fois + } + }, 300); // Délai pour la transition +} + +/** + * Fonction pour gérer la soumission du formulaire de présences + * @param {number} eventId - ID de l'événement + * @param {Array} presenceData - Données de présence + */ +async function handleGroupPresenceSubmission(eventId, presenceData) { + if (!eventId) { + notifyError('ID d\'événement manquant'); + return; + } + + if (!presenceData || !Array.isArray(presenceData) || presenceData.length === 0) { + notifyError('Aucune donnée de présence à enregistrer'); + return; + } + + // Valider les données + for (let i = 0; i < presenceData.length; i++) { + const presence = presenceData[i]; + if (!presence.nom || !presence.prenom) { + notifyError(`Les champs nom et prénom sont requis pour le participant ${i + 1}`); + return; + } + } + + try { + // Envoyer les données à l'API REST + const response = await apiFetch(`events/${eventId}/presences`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + presences: presenceData + }) + }); + + if (response && response.success) { + notifySuccess('Présences enregistrées avec succès'); + + // Fermer la modal + const modal = document.getElementById('eventCheckPresenceModal'); + if (modal && window.bootstrap && window.bootstrap.Modal) { + const bsModal = window.bootstrap.Modal.getInstance(modal); + if (bsModal) { + bsModal.hide(); + } + } + + // Rafraîchir le calendrier si disponible + if (window.currentCalendar) { + window.currentCalendar.refetchEvents(); + } + if (window.currentColleaguesCalendar) { + window.currentColleaguesCalendar.refetchEvents(); + } + } else { + throw new Error(response?.data?.message || 'Erreur lors de l\'enregistrement des présences'); + } + } catch (error) { + console.error('Erreur lors de l\'enregistrement des présences:', error); + notifyError(error.message || 'Erreur lors de l\'enregistrement des présences'); + } +} + +/** + * Initialise l'autocomplétion pour les champs nom dans le formulaire de présences + */ +function initializePresenceAutocomplete() { + const nomInputs = document.querySelectorAll('.presence-nom-input'); + + nomInputs.forEach(nomInput => { + let searchTimeout = null; + let currentSuggestions = []; + + const rowIndex = nomInput.getAttribute('data-row-index'); + const prenomInput = document.getElementById(`presence_prenom_${rowIndex}`); + const beneficiaireIdInput = document.getElementById(`presence_beneficiaire_id_${rowIndex}`); + const suggestionsDiv = document.getElementById(`autocomplete_${rowIndex}`); + + // Fonction pour rechercher des bénéficiaires + async function searchBeneficiaires(searchTerm) { + if (searchTerm.length < 5) { + suggestionsDiv.style.display = 'none'; + return; + } + + try { + const response = await apiFetch(`beneficiaires/search?search=${encodeURIComponent(searchTerm)}`, { + method: 'GET' + }); + + if (response && response.success && response.data) { + currentSuggestions = response.data; + displaySuggestions(); + } else { + currentSuggestions = []; + suggestionsDiv.style.display = 'none'; + } + } catch (error) { + console.error('Erreur lors de la recherche de bénéficiaires:', error); + currentSuggestions = []; + suggestionsDiv.style.display = 'none'; + } + } + + // Fonction pour afficher les suggestions + function displaySuggestions() { + if (currentSuggestions.length === 0) { + suggestionsDiv.style.display = 'none'; + return; + } + + suggestionsDiv.innerHTML = ''; + currentSuggestions.forEach((beneficiaire) => { + const suggestionItem = document.createElement('div'); + suggestionItem.className = 'autocomplete-item'; + suggestionItem.textContent = `${beneficiaire.prenom} ${beneficiaire.nom}`; + suggestionItem.dataset.beneficiaireId = beneficiaire.id; + + suggestionItem.addEventListener('click', () => { + selectBeneficiaire(beneficiaire); + }); + + suggestionsDiv.appendChild(suggestionItem); + }); + + suggestionsDiv.style.display = 'block'; + } + + // Fonction pour sélectionner un bénéficiaire + function selectBeneficiaire(beneficiaire) { + nomInput.value = beneficiaire.nom; + prenomInput.value = beneficiaire.prenom; + if (beneficiaireIdInput) { + beneficiaireIdInput.value = beneficiaire.id; + } + suggestionsDiv.style.display = 'none'; + } + + // Event listener sur le champ nom + nomInput.addEventListener('input', function() { + clearTimeout(searchTimeout); + const searchTerm = this.value.trim(); + + if (searchTerm.length >= 5) { + searchTimeout = setTimeout(() => { + searchBeneficiaires(searchTerm); + }, 300); + } else { + suggestionsDiv.style.display = 'none'; + } + }); + + // Fermer les suggestions au clic en dehors + document.addEventListener('click', function(e) { + if (!nomInput.contains(e.target) && !suggestionsDiv.contains(e.target)) { + suggestionsDiv.style.display = 'none'; + } + }); + }); } // ========== Initialisation des event listeners globaux ========== @@ -532,5 +784,78 @@ export function openCheckPresenceModal(eventData) { } }); +// Initialiser le bouton de sauvegarde des présences +const savePresencesBtn = document.getElementById('savePresencesBtn'); +if (savePresencesBtn) { + savePresencesBtn.onclick = async function() { + const form = document.getElementById('eventCheckPresenceForm'); + if (!form) { + notifyError('Formulaire de présences introuvable'); + return; + } + + const eventIdInput = document.getElementById('presence_event_id'); + const eventId = eventIdInput ? parseInt(eventIdInput.value, 10) : null; + + if (!eventId) { + notifyError('ID d\'événement manquant'); + return; + } + + // Récupérer toutes les lignes de présence + const rows = document.querySelectorAll('#presence_rows tr'); + const presenceData = []; + + rows.forEach((row, index) => { + const checkbox = row.querySelector(`input[type="checkbox"][id^="presence_${index}"]`); + const nomInput = row.querySelector(`input[id="presence_nom_${index}"]`); + const prenomInput = row.querySelector(`input[id="presence_prenom_${index}"]`); + const beneficiaireIdInput = row.querySelector(`input[id="presence_beneficiaire_id_${index}"]`); + + if (nomInput && prenomInput) { + const nom = nomInput.value.trim(); + const prenom = prenomInput.value.trim(); + const isPresent = checkbox ? checkbox.checked : false; + const beneficiaireId = beneficiaireIdInput ? beneficiaireIdInput.value : null; + + // Ne pas inclure les lignes vides (nom et prénom vides) + if (nom || prenom) { + const presenceItem = { + nom: nom, + prenom: prenom, + is_present: isPresent + }; + + // Ajouter beneficiaire_id si un bénéficiaire existant a été sélectionné + if (beneficiaireId) { + presenceItem.beneficiaire_id = parseInt(beneficiaireId, 10); + } + + presenceData.push(presenceItem); + } + } + }); + + if (presenceData.length === 0) { + notifyError('Veuillez remplir au moins une ligne de présence'); + return; + } + + // Afficher un overlay de chargement + const modal = document.getElementById('eventCheckPresenceModal'); + let overlayTarget = modal ? modal.querySelector('.modal-content') : null; + try { + if (window.CRVI_OVERLAY && overlayTarget) { + window.CRVI_OVERLAY.show(overlayTarget); + } + await handleGroupPresenceSubmission(eventId, presenceData); + } finally { + if (window.CRVI_OVERLAY && overlayTarget) { + window.CRVI_OVERLAY.hide(overlayTarget); + } + } + }; +} + // Réexporter les fonctions nécessaires export { fillFormWithDate, fillFormWithEvent, resetForm, showFormErrors, clearFormErrors, handleEventFormSubmit }; diff --git a/templates/modules/modals/event-modal.php b/templates/modules/modals/event-modal.php index 41dcd74..d3c4c19 100644 --- a/templates/modules/modals/event-modal.php +++ b/templates/modules/modals/event-modal.php @@ -485,7 +485,7 @@ $crvi_is_front_context = ($crvi_agenda_context !== 'admin'); Valider présences