Correction presences
This commit is contained in:
parent
b0b5a2eb53
commit
884be3761d
@ -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 = `
|
||||
<td>
|
||||
<input type="checkbox" class="form-check-input" id="presence_${i}" name="presences[${i}][is_present]" checked>
|
||||
</td>
|
||||
<td style="position: relative;">
|
||||
<input type="text" class="form-control presence-nom-input" id="presence_nom_${i}" name="presences[${i}][nom]"
|
||||
data-row-index="${i}" autocomplete="off" required>
|
||||
<input type="hidden" id="presence_beneficiaire_id_${i}" name="presences[${i}][beneficiaire_id]">
|
||||
<div class="autocomplete-suggestions" id="autocomplete_${i}" style="display: none;"></div>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control presence-prenom-input" id="presence_prenom_${i}" name="presences[${i}][prenom]"
|
||||
data-row-index="${i}" autocomplete="off" required>
|
||||
</td>
|
||||
`;
|
||||
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 };
|
||||
|
||||
@ -485,7 +485,7 @@ $crvi_is_front_context = ($crvi_agenda_context !== 'admin');
|
||||
<i class="fas fa-user-check me-1"></i>Valider présences
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary btn-sm groupe-only-button" id="showPresenceModalBtn" title="Afficher le modal de présence" style="display: none;">
|
||||
<i class="fa-regular fa-id-badge me-1"></i>Gérer les présences
|
||||
<i class="fa-solid fa-clipboard-list"></i> Gérer les présences
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning btn-sm" id="markAbsentBtn" title="Marquer comme absent">
|
||||
<i class="fas fa-user-times me-1"></i>Absent
|
||||
|
||||
Loading…
Reference in New Issue
Block a user