// Module principal de gestion de la modale d'événement // Version refactorisée utilisant des modules séparés import { createEvent, updateEvent, deleteEvent, changeEventStatus, getFilters, apiFetch } from './agenda-api.js'; import { notifyError, notifySuccess } from './agenda-notifications.js'; import { initializeEntityCreators } from './agenda-entity-creator.js'; // Modules refactorisés import { clearDomCache, clearFormFields } from './agenda-modal-dom.js'; import { initializeModalButtons } from './agenda-modal-buttons.js'; import { initializeSelect2, populateSelects, filterTraducteursByLangue, getIsUpdatingSelects, clearDisponibilitesCache, initializeBeneficiaireListeRougeAlert, resetLangueSelectDisplay } from './agenda-modal-select.js'; import { fillFormWithDate, fillFormWithEvent, resetForm, showFormErrors, clearFormErrors, handleEventFormSubmit } from './agenda-modal-forms.js'; import { fillViewBlock, updateModalDisplay, checkIfEventIsPast } from './agenda-modal-display.js'; // Variables globales let currentMode = 'view'; // 'view', 'edit', 'create' let currentEventData = null; let preservedMode = null; let preservedEventData = null; /** * Préserve les données de la modale avant de l'ouvrir une sous-modale */ export function preserveModalData() { preservedMode = currentMode; preservedEventData = currentEventData; } /** * Restaure les données de la modale après fermeture d'une sous-modale * @returns {boolean} - True si des données ont été restaurées */ export function restoreModalData() { if (preservedMode !== null && preservedEventData !== null) { currentMode = preservedMode; currentEventData = preservedEventData; preservedMode = null; preservedEventData = null; return true; } return false; } /** * Ouvre une sous-modale en gérant automatiquement la fermeture/réouverture de la modale principale * @param {string} subModalId - ID de la sous-modale à ouvrir * @param {Function} onBeforeOpen - Callback optionnel appelé avant l'ouverture (pour préparer les données) * @param {Function} onAfterClose - Callback optionnel appelé après la fermeture de la sous-modale * @param {number} delay - Délai avant ouverture de la sous-modale (ms, défaut: 300) */ export function openSubModal(subModalId, onBeforeOpen = null, onAfterClose = null, delay = 300) { const subModal = document.getElementById(subModalId); if (!subModal) { console.error(`Sous-modale non trouvée: ${subModalId}`); return; } // Préserver les données de la modale principale preserveModalData(); // Exécuter le callback de préparation si fourni if (onBeforeOpen && typeof onBeforeOpen === 'function') { try { onBeforeOpen(subModal); } catch (error) { console.error('Erreur dans onBeforeOpen:', error); } } // Fermer la modale principale const eventModal = document.getElementById('eventModal'); if (eventModal) { const eventBsModal = bootstrap.Modal.getInstance(eventModal); if (eventBsModal) { eventBsModal.hide(); } } // Attendre que la modale principale se ferme setTimeout(() => { // Ouvrir la sous-modale if (window.bootstrap && window.bootstrap.Modal) { const bsModal = new window.bootstrap.Modal(subModal); bsModal.show(); // Gérer la réouverture de la modale principale à la fermeture subModal.addEventListener('hidden.bs.modal', function handleSubModalClose() { // Exécuter le callback de fermeture si fourni if (onAfterClose && typeof onAfterClose === 'function') { try { onAfterClose(subModal); } catch (error) { console.error('Erreur dans onAfterClose:', error); } } // Rouvrir la modale principale avec les données préservées if (eventModal && window.bootstrap && window.bootstrap.Modal) { const newEventModal = new window.bootstrap.Modal(eventModal); newEventModal.show(); } }, { once: true }); // Une seule fois } }, delay); } /** * Charge les incidents d'un événement * @param {number} eventId - ID de l'événement * @returns {Promise} - Tableau des incidents */ async function loadEventIncidents(eventId) { try { const incidents = await apiFetch(`events/${eventId}/incidents`); return incidents || []; } catch (error) { console.error('Erreur lors du chargement des incidents:', error); return []; } } /** * Ouvre la modal d'incidents en mode affichage * Utilise la fonction générique openSubModal pour gérer la fermeture/réouverture de la modale principale * @param {number} eventId - ID de l'événement */ async function openIncidentsViewModal(eventId) { // Utiliser openSubModal pour gérer automatiquement la fermeture/réouverture openSubModal( 'declarationIncidentModal', // Callback avant ouverture : charger et afficher les incidents async (subModal) => { const modalTitle = document.getElementById('declarationIncidentModalLabel'); const viewSection = document.getElementById('incidentsViewSection'); const formSection = document.getElementById('incidentsFormSection'); const viewFooter = document.getElementById('incidentsViewFooter'); const formFooter = document.getElementById('incidentsFormFooter'); const listContainer = document.getElementById('incidentsListContainer'); if (!viewSection || !formSection || !listContainer) { notifyError('Sections de la modal d\'incidents introuvables'); return; } try { // Afficher un spinner de chargement listContainer.innerHTML = `
Chargement...
`; // Charger les incidents const incidents = await loadEventIncidents(eventId); if (incidents.length === 0) { listContainer.innerHTML = '

Aucun incident signalé pour cet événement.

'; } else { // Afficher les incidents let html = '
'; incidents.forEach((incident, index) => { const createdAt = incident.created_at ? new Date(incident.created_at).toLocaleDateString('fr-FR') : 'Date inconnue'; html += `
Incident #${index + 1}
${createdAt}
${incident.resume_incident ? `

Résumé : ${incident.resume_incident}

` : ''} ${incident.commentaire_incident ? `

${incident.commentaire_incident}

` : ''}
`; }); html += '
'; listContainer.innerHTML = html; } // Changer le titre de la modal if (modalTitle) { modalTitle.innerHTML = 'Détail des incidents'; } // Afficher la section de vue, masquer le formulaire viewSection.style.display = 'block'; formSection.style.display = 'none'; viewFooter.style.display = 'block'; formFooter.style.display = 'none'; } catch (error) { console.error('Erreur lors du chargement des incidents:', error); listContainer.innerHTML = '

Erreur lors du chargement des incidents

'; notifyError('Erreur lors du chargement des incidents'); } }, // Callback après fermeture : réinitialiser au mode formulaire (subModal) => { const modalTitle = document.getElementById('declarationIncidentModalLabel'); const viewSection = document.getElementById('incidentsViewSection'); const formSection = document.getElementById('incidentsFormSection'); const viewFooter = document.getElementById('incidentsViewFooter'); const formFooter = document.getElementById('incidentsFormFooter'); const listContainer = document.getElementById('incidentsListContainer'); // Réinitialiser au mode formulaire if (viewSection) viewSection.style.display = 'none'; if (formSection) formSection.style.display = 'block'; if (viewFooter) viewFooter.style.display = 'none'; if (formFooter) formFooter.style.display = 'block'; if (modalTitle) { modalTitle.innerHTML = 'Signaler un incident'; } if (listContainer) { listContainer.innerHTML = ''; } } ); } /** * Vérifie si l'événement a des incidents et affiche le bouton en conséquence * @param {number} eventId - ID de l'événement */ export async function checkAndDisplayIncidentsButton(eventId) { const viewIncidentsBtn = document.getElementById('viewIncidentsBtn'); if (!viewIncidentsBtn) { return; } try { const incidents = await loadEventIncidents(eventId); if (incidents.length > 0) { viewIncidentsBtn.style.display = 'inline-block'; // Mettre à jour le texte du bouton avec le nombre const icon = viewIncidentsBtn.querySelector('i'); const iconHtml = icon ? icon.outerHTML : ''; viewIncidentsBtn.innerHTML = `${iconHtml}Détail incident(s) (${incidents.length})`; } else { viewIncidentsBtn.style.display = 'none'; } } catch (error) { console.error('Erreur lors de la vérification des incidents:', error); viewIncidentsBtn.style.display = 'none'; } } /** * Ouvre le modal d'événement * @param {string} mode - Mode ('view', 'edit', 'create') * @param {Object} eventData - Données de l'événement */ export function openModal(mode, eventData = null) { // Vérifier s'il y a des données préservées à restaurer if (restoreModalData()) { mode = currentMode; eventData = currentEventData; } else { if (eventData && !mode) { mode = 'view'; } currentMode = mode; currentEventData = eventData; } const modal = document.getElementById('eventModal'); if (!modal) { console.error('❌ Élément modal non trouvé'); return; } // Obtenir ou créer l'instance Bootstrap du modal let bsModal = window.bootstrap && window.bootstrap.Modal ? window.bootstrap.Modal.getInstance(modal) : null; if (!bsModal && window.bootstrap && window.bootstrap.Modal) { bsModal = new window.bootstrap.Modal(modal); } // Initialiser les composants initializeEntityCreators(); initializeSelect2(); initializeTimeComfort(); initializeLangueFilter(); initializeBeneficiaireListeRougeAlert(); // Initialiser les boutons (une seule fois) initializeModalButtons({ getCurrentEventData: () => currentEventData, getCurrentMode: () => currentMode, setCurrentMode: (mode) => { currentMode = mode; }, openSubModal: openSubModal, openCheckPresenceModal: openCheckPresenceModal, openIncidentsViewModal: openIncidentsViewModal, enableDateSynchronization: enableDateSynchronization, disableDateSynchronization: disableDateSynchronization, onDeleted: () => disableDateSynchronization(), onStatusChanged: () => disableDateSynchronization() }); // Déterminer les permissions const userCanEdit = window.crviPermissions && window.crviPermissions.can_edit; const userCanCreate = window.crviPermissions && window.crviPermissions.can_create; const userCanDelete = window.crviPermissions && window.crviPermissions.can_delete; // Vérifier si l'événement est passé const isEventPast = checkIfEventIsPast(eventData); // Ajuster le mode selon les permissions if (mode === 'edit' && !userCanEdit) { mode = 'view'; currentMode = 'view'; } if (mode === 'edit' && isEventPast) { console.warn('Impossible de modifier un événement passé'); notifyError('Impossible de modifier un événement passé'); mode = 'view'; currentMode = 'view'; } if (mode === 'create' && !userCanCreate) { console.warn('Utilisateur non autorisé à créer des événements'); return; } // Mettre à jour l'affichage updateModalDisplay(currentMode, userCanEdit, userCanDelete, currentEventData); // Remplir les données selon le mode if (mode === 'view') { fillViewBlock(eventData); clearFormErrors(); } else if (mode === 'edit') { fillFormWithEvent(eventData, filterTraducteursByLangue); populateSelects(eventData); clearFormErrors(); } else if (mode === 'create') { if (eventData && eventData.startStr) { fillFormWithDate(eventData); } else { fillFormWithEvent(eventData, filterTraducteursByLangue); } populateSelects(eventData); clearFormErrors(); enableDateSynchronization(); preventPastDates(); } // Nettoyer les champs lors de la fermeture modal.addEventListener('hidden.bs.modal', function() { if (preservedMode === null && preservedEventData === null) { clearModalFields(); clearDomCache(); clearDisponibilitesCache(); resetLangueSelectDisplay(); // Réinitialiser le display des options langue currentMode = 'view'; currentEventData = null; } disableDateSynchronization(); }, { once: true }); // Afficher le modal bsModal.show(); } /** * Ferme le modal de force (pour gérer les bugs de Bootstrap) */ function forceCloseModal() { const modal = document.getElementById('eventModal'); if (modal) { const bsModal = bootstrap.Modal.getInstance(modal); if (bsModal) { bsModal.hide(); } } // Nettoyer manuellement le backdrop et les classes setTimeout(() => { const backdrops = document.querySelectorAll('.modal-backdrop'); backdrops.forEach(backdrop => backdrop.remove()); document.body.classList.remove('modal-open'); document.body.style.overflow = ''; document.body.style.paddingRight = ''; }, 300); } /** * Nettoie les champs du modal */ function clearModalFields() { const textFields = [ 'date_rdv', 'heure_rdv', 'date_fin', 'heure_fin', 'commentaire', 'nb_participants', 'nb_hommes', 'nb_femmes' ]; const selectFields = [ 'type', 'langue', 'id_beneficiaire', 'id_intervenant', 'id_traducteur', 'id_local', 'id_departement', 'id_type_intervention' ]; clearFormFields(textFields, selectFields); clearFormErrors(); // Réinitialiser les champs conditionnels const typeField = document.getElementById('type'); if (typeField) { typeField.dispatchEvent(new Event('change')); } } // ========== Fonctions de synchronisation des dates/heures ========== function calculateHeureFin(heureDebut) { const [h, m] = heureDebut.split(':').map(Number); const heureFin = ((h + 1) % 24).toString().padStart(2, '0') + ':' + m.toString().padStart(2, '0'); return heureFin; } function syncHeureFin() { const heureRdvInput = document.getElementById('heure_rdv'); const heureFinInput = document.getElementById('heure_fin'); const typeInput = document.getElementById('type'); if (!heureRdvInput || !heureFinInput || !typeInput) return; if (typeInput.value !== 'individuel') return; const heureDebut = heureRdvInput.value; if (!heureDebut) return; const heureFinStr = calculateHeureFin(heureDebut); heureFinInput.value = heureFinStr; } function syncDateFin() { const dateRdvInput = document.getElementById('date_rdv'); const dateFinInput = document.getElementById('date_fin'); if (dateRdvInput && dateFinInput && dateRdvInput.value) { dateFinInput.value = dateRdvInput.value; } } function enableDateSynchronization() { const dateRdvInput = document.getElementById('date_rdv'); const heureRdvInput = document.getElementById('heure_rdv'); const typeInput = document.getElementById('type'); if (dateRdvInput) { dateRdvInput.removeEventListener('change', syncDateFin); dateRdvInput.addEventListener('change', syncDateFin); } if (heureRdvInput && typeInput) { heureRdvInput.removeEventListener('change', syncHeureFin); heureRdvInput.addEventListener('change', syncHeureFin); } // Sélectionner 'individuel' par défaut en création if (typeInput && currentMode === 'create' && !typeInput.value) { typeInput.value = 'individuel'; typeInput.dispatchEvent(new Event('change')); } } function disableDateSynchronization() { const dateRdvInput = document.getElementById('date_rdv'); const heureRdvInput = document.getElementById('heure_rdv'); if (dateRdvInput) { dateRdvInput.removeEventListener('change', syncDateFin); } if (heureRdvInput) { heureRdvInput.removeEventListener('change', syncHeureFin); } } function preventPastDates() { const dateRdvInput = document.getElementById('date_rdv'); const dateFinInput = document.getElementById('date_fin'); if (dateRdvInput) { const today = new Date().toISOString().split('T')[0]; dateRdvInput.setAttribute('min', today); dateRdvInput.addEventListener('change', function() { const selectedDate = this.value; if (dateFinInput && selectedDate) { dateFinInput.setAttribute('min', selectedDate); if (dateFinInput.value && dateFinInput.value < selectedDate) { dateFinInput.value = selectedDate; } } }); } } // ========== Fonctions pour les fonctionnalités spécifiques ========== function initializeTimeComfort() { // Logique de confort pour les sélecteurs d'heure // (inchangée de l'original) } function initializeLangueFilter() { // Initialiser le filtre de langue const langueSelect = document.getElementById('langue'); if (langueSelect) { langueSelect.addEventListener('change', filterTraducteursByLangue); } } /** * Ouvre le modal de validation des présences pour un événement de groupe * @param {Object} eventData - Données de l'événement */ export function openCheckPresenceModal(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); }); // Positionner la div de suggestions sous le champ nom const nomInputRect = nomInput.getBoundingClientRect(); const parentCell = nomInput.closest('td'); if (parentCell) { // Position relative au td parent suggestionsDiv.style.position = 'absolute'; suggestionsDiv.style.top = (nomInput.offsetTop + nomInput.offsetHeight) + 'px'; suggestionsDiv.style.left = nomInput.offsetLeft + 'px'; suggestionsDiv.style.width = nomInput.offsetWidth + 'px'; suggestionsDiv.style.zIndex = '1060'; } 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 ========== // Rafraîchir les selects si date/heure/type change ['date_rdv', 'heure_rdv', 'type'].forEach(id => { const element = document.getElementById(id); if (element) { element.addEventListener('change', () => { if (getIsUpdatingSelects()) return; if (currentMode === 'edit' || currentMode === 'create') { populateSelects(currentEventData); } }); } }); // 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 };