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