749 lines
30 KiB
JavaScript
749 lines
30 KiB
JavaScript
// Module de gestion des boutons de la modale
|
|
// Contient les gestionnaires d'événements pour tous les boutons de la modale
|
|
|
|
import { deleteEvent, changeEventStatus, apiFetch } from './agenda-api.js';
|
|
import { notifyError, notifySuccess } from './agenda-notifications.js';
|
|
import { populateSelects } from './agenda-modal-select.js';
|
|
import { fillFormWithEvent, clearFormErrors, handleEventFormSubmit } from './agenda-modal-forms.js';
|
|
import { updateModalDisplay, fillViewBlock } from './agenda-modal-display.js';
|
|
|
|
/**
|
|
* Helper pour gérer l'overlay de chargement
|
|
* @param {Function} asyncAction - Action asynchrone à exécuter
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function withLoadingOverlay(asyncAction) {
|
|
const overlayTarget = document.querySelector('#eventModal .modal-content') || document.getElementById('eventModal');
|
|
try {
|
|
if (window.CRVI_OVERLAY && overlayTarget) {
|
|
window.CRVI_OVERLAY.show(overlayTarget);
|
|
}
|
|
await asyncAction();
|
|
} finally {
|
|
if (window.CRVI_OVERLAY && overlayTarget) {
|
|
window.CRVI_OVERLAY.hide(overlayTarget);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper pour rafraîchir les calendriers
|
|
*/
|
|
function refreshCalendars() {
|
|
if (window.currentCalendar) {
|
|
window.currentCalendar.refetchEvents();
|
|
}
|
|
if (window.currentColleaguesCalendar) {
|
|
window.currentColleaguesCalendar.refetchEvents();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper pour fermer le modal
|
|
* @param {Function} onClosed - Callback après fermeture
|
|
*/
|
|
function closeModal(onClosed = null) {
|
|
const modal = document.getElementById('eventModal');
|
|
if (modal) {
|
|
const bsModal = bootstrap.Modal.getInstance(modal);
|
|
if (bsModal) {
|
|
if (onClosed) {
|
|
modal.addEventListener('hidden.bs.modal', onClosed, { once: true });
|
|
}
|
|
bsModal.hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vérifie les permissions utilisateur
|
|
* @param {string} permission - Type de permission ('can_edit', 'can_delete', 'can_create')
|
|
* @returns {boolean}
|
|
*/
|
|
function checkPermission(permission) {
|
|
const hasPermission = window.crviPermissions && window.crviPermissions[permission];
|
|
if (!hasPermission) {
|
|
console.warn(`Utilisateur non autorisé: ${permission}`);
|
|
}
|
|
return hasPermission;
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton de fermeture
|
|
* @param {string} buttonId - ID du bouton
|
|
*/
|
|
export function initializeCloseButton(buttonId) {
|
|
const button = document.getElementById(buttonId);
|
|
if (button) {
|
|
button.onclick = () => closeModal();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton de suppression
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} onDeleted - Callback après suppression
|
|
*/
|
|
export function initializeDeleteButton(getCurrentEventData, onDeleted = null) {
|
|
const deleteBtn = document.getElementById('deleteEvent');
|
|
if (!deleteBtn) return;
|
|
|
|
deleteBtn.onclick = async function() {
|
|
if (!checkPermission('can_delete')) return;
|
|
|
|
if (!confirm('Êtes-vous sûr de vouloir supprimer cet événement ?')) {
|
|
return;
|
|
}
|
|
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData ? currentEventData.id : null;
|
|
|
|
if (!eventId) {
|
|
notifyError('ID d\'événement manquant');
|
|
return;
|
|
}
|
|
|
|
await withLoadingOverlay(async () => {
|
|
try {
|
|
await deleteEvent(eventId);
|
|
refreshCalendars();
|
|
closeModal(onDeleted);
|
|
} catch (error) {
|
|
console.error('Erreur lors de la suppression:', error);
|
|
notifyError('Erreur lors de la suppression de l\'événement');
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton de validation de présence
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} openCheckPresenceModal - Fonction pour ouvrir la modal de validation de présence de groupe
|
|
* @param {Function} onStatusChanged - Callback après changement de statut
|
|
*/
|
|
export function initializeMarkPresentButton(getCurrentEventData, openCheckPresenceModal, onStatusChanged = null) {
|
|
const markPresentBtn = document.getElementById('markPresentBtn');
|
|
if (!markPresentBtn) return;
|
|
|
|
markPresentBtn.onclick = async function() {
|
|
if (!checkPermission('can_edit')) return;
|
|
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData ? currentEventData.id : null;
|
|
|
|
if (!eventId) {
|
|
notifyError('ID d\'événement manquant');
|
|
return;
|
|
}
|
|
|
|
// Vérifier le type d'événement
|
|
const eventType = currentEventData?.type || currentEventData?.extendedProps?.type || '';
|
|
const isGroupe = eventType === 'groupe';
|
|
|
|
if (isGroupe) {
|
|
// Pour les événements de groupe, ouvrir la modal de validation des présences
|
|
openCheckPresenceModal(currentEventData);
|
|
} else {
|
|
// Pour les événements individuels
|
|
if (!confirm('Confirmer la présence à cet événement ?')) {
|
|
return;
|
|
}
|
|
|
|
await withLoadingOverlay(async () => {
|
|
try {
|
|
await changeEventStatus(eventId, 'present');
|
|
notifySuccess('Présence validée');
|
|
refreshCalendars();
|
|
closeModal(onStatusChanged);
|
|
} catch (error) {
|
|
console.error('Erreur lors du changement de statut:', error);
|
|
notifyError('Erreur lors de la validation de présence');
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton pour marquer comme absent
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} onStatusChanged - Callback après changement de statut
|
|
*/
|
|
export function initializeMarkAbsentButton(getCurrentEventData, onStatusChanged = null) {
|
|
const markAbsentBtn = document.getElementById('markAbsentBtn');
|
|
if (!markAbsentBtn) return;
|
|
|
|
markAbsentBtn.onclick = async function() {
|
|
if (!checkPermission('can_edit')) return;
|
|
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData ? currentEventData.id : null;
|
|
|
|
if (!eventId) {
|
|
notifyError('ID d\'événement manquant');
|
|
return;
|
|
}
|
|
|
|
if (!confirm('Marquer cet événement comme absent ?')) {
|
|
return;
|
|
}
|
|
|
|
await withLoadingOverlay(async () => {
|
|
try {
|
|
await changeEventStatus(eventId, 'absence');
|
|
notifySuccess('Événement marqué comme absent');
|
|
refreshCalendars();
|
|
closeModal(onStatusChanged);
|
|
} catch (error) {
|
|
console.error('Erreur lors du changement de statut:', error);
|
|
notifyError('Erreur lors du changement de statut');
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton d'annulation de rendez-vous
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} onCancelled - Callback après annulation
|
|
*/
|
|
export function initializeCancelAppointmentButton(getCurrentEventData, onCancelled = null) {
|
|
const cancelAppointmentBtn = document.getElementById('cancelAppointmentBtn');
|
|
if (!cancelAppointmentBtn) return;
|
|
|
|
cancelAppointmentBtn.onclick = async function() {
|
|
if (!checkPermission('can_edit')) return;
|
|
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData ? currentEventData.id : null;
|
|
|
|
if (!eventId) {
|
|
notifyError('ID d\'événement manquant');
|
|
return;
|
|
}
|
|
|
|
const motif = prompt('Motif de l\'annulation (optionnel):');
|
|
if (motif === null) {
|
|
return; // L'utilisateur a cliqué sur Annuler
|
|
}
|
|
|
|
await withLoadingOverlay(async () => {
|
|
try {
|
|
await changeEventStatus(eventId, 'annule', motif);
|
|
notifySuccess('Rendez-vous annulé');
|
|
refreshCalendars();
|
|
closeModal(onCancelled);
|
|
} catch (error) {
|
|
console.error('Erreur lors de l\'annulation:', error);
|
|
notifyError('Erreur lors de l\'annulation du rendez-vous');
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton Edit
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} getCurrentMode - Fonction pour obtenir le mode actuel
|
|
* @param {Function} setCurrentMode - Fonction pour changer le mode
|
|
* @param {Function} enableDateSynchronization - Fonction pour activer la synchronisation des dates
|
|
*/
|
|
export function initializeEditButton(getCurrentEventData, getCurrentMode, setCurrentMode, enableDateSynchronization) {
|
|
const editBtn = document.getElementById('editEventBtn');
|
|
if (!editBtn) return;
|
|
|
|
editBtn.onclick = async function() {
|
|
if (!checkPermission('can_edit')) return;
|
|
|
|
const currentEventData = getCurrentEventData();
|
|
|
|
// Changer le mode
|
|
setCurrentMode('edit');
|
|
|
|
// Mettre à jour l'affichage
|
|
const userCanEdit = window.crviPermissions && window.crviPermissions.can_edit;
|
|
const userCanDelete = window.crviPermissions && window.crviPermissions.can_delete;
|
|
updateModalDisplay('edit', userCanEdit, userCanDelete, currentEventData);
|
|
|
|
// Remplir le formulaire avec les données actuelles
|
|
fillFormWithEvent(currentEventData);
|
|
|
|
// Peupler les selects avec overlay de chargement
|
|
await withLoadingOverlay(async () => {
|
|
try {
|
|
await populateSelects(currentEventData);
|
|
} catch (error) {
|
|
console.error('Erreur lors du peuplement des selects:', error);
|
|
}
|
|
});
|
|
|
|
clearFormErrors();
|
|
|
|
// Activer la synchronisation des dates
|
|
if (enableDateSynchronization) {
|
|
enableDateSynchronization();
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton Cancel
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} getCurrentMode - Fonction pour obtenir le mode actuel
|
|
* @param {Function} setCurrentMode - Fonction pour changer le mode
|
|
* @param {Function} disableDateSynchronization - Fonction pour désactiver la synchronisation des dates
|
|
*/
|
|
export function initializeCancelButton(getCurrentEventData, getCurrentMode, setCurrentMode, disableDateSynchronization) {
|
|
const cancelBtn = document.getElementById('cancelEditBtn');
|
|
if (!cancelBtn) return;
|
|
|
|
cancelBtn.onclick = function() {
|
|
const currentMode = getCurrentMode();
|
|
const currentEventData = getCurrentEventData();
|
|
|
|
if (currentMode === 'create') {
|
|
// En mode création, fermer le modal
|
|
closeModal();
|
|
} else if (currentMode === 'edit' && currentEventData) {
|
|
// En mode édition, retourner en mode vue
|
|
setCurrentMode('view');
|
|
|
|
const userCanEdit = window.crviPermissions && window.crviPermissions.can_edit;
|
|
const userCanDelete = window.crviPermissions && window.crviPermissions.can_delete;
|
|
updateModalDisplay('view', userCanEdit, userCanDelete, currentEventData);
|
|
|
|
// Réafficher les données en mode lecture
|
|
fillViewBlock(currentEventData);
|
|
clearFormErrors();
|
|
|
|
// Désactiver la synchronisation des dates
|
|
if (disableDateSynchronization) {
|
|
disableDateSynchronization();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton Save
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} getCurrentMode - Fonction pour obtenir le mode actuel
|
|
* @param {Function} disableDateSynchronization - Fonction pour désactiver la synchronisation des dates
|
|
*/
|
|
export function initializeSaveButton(getCurrentEventData, getCurrentMode, disableDateSynchronization) {
|
|
const saveBtn = document.getElementById('saveEvent');
|
|
if (!saveBtn) return;
|
|
|
|
saveBtn.onclick = async function() {
|
|
const currentMode = getCurrentMode();
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData ? currentEventData.id : null;
|
|
|
|
await withLoadingOverlay(async () => {
|
|
await handleEventFormSubmit(currentMode, eventId, function() {
|
|
// Succès : fermer le modal et rafraîchir les calendriers
|
|
refreshCalendars();
|
|
closeModal();
|
|
|
|
// Désactiver la synchronisation des dates
|
|
if (disableDateSynchronization) {
|
|
disableDateSynchronization();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton "Signaler un incident"
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} openSubModal - Fonction pour ouvrir une sous-modale
|
|
*/
|
|
export function initializeReportIncidentButton(getCurrentEventData, openSubModal) {
|
|
const reportIncidentBtn = document.getElementById('reportIncidentBtn');
|
|
if (!reportIncidentBtn) return;
|
|
|
|
reportIncidentBtn.onclick = async function() {
|
|
const currentEventData = getCurrentEventData();
|
|
|
|
if (!currentEventData || !currentEventData.id) {
|
|
notifyError('Aucun événement sélectionné');
|
|
return;
|
|
}
|
|
|
|
// Récupérer le type d'événement
|
|
const eventType = currentEventData.type || currentEventData.extendedProps?.type || 'individuel';
|
|
const isGroupe = eventType === 'groupe';
|
|
|
|
// Ouvrir la sous-modale avec préparation des données
|
|
openSubModal(
|
|
'declarationIncidentModal',
|
|
(subModal) => {
|
|
// Pré-remplir le formulaire
|
|
const eventIdInput = document.getElementById('incident_event_id');
|
|
const eventTypeInput = document.getElementById('incident_event_type');
|
|
const sectionIndividuel = document.getElementById('incident_individuel_section');
|
|
const sectionGroupe = document.getElementById('incident_groupe_section');
|
|
|
|
if (eventIdInput) eventIdInput.value = currentEventData.id;
|
|
if (eventTypeInput) eventTypeInput.value = eventType;
|
|
|
|
// Afficher/masquer les sections selon le type
|
|
if (isGroupe) {
|
|
if (sectionIndividuel) sectionIndividuel.style.display = 'none';
|
|
if (sectionGroupe) sectionGroupe.style.display = 'block';
|
|
} else {
|
|
if (sectionIndividuel) sectionIndividuel.style.display = 'block';
|
|
if (sectionGroupe) sectionGroupe.style.display = 'none';
|
|
|
|
// Pré-remplir les infos du bénéficiaire
|
|
const beneficiaireId = currentEventData.id_beneficiaire || currentEventData.extendedProps?.id_beneficiaire;
|
|
const beneficiaireNom = currentEventData.beneficiaire?.nom_complet ||
|
|
currentEventData.extendedProps?.beneficiaire?.nom_complet ||
|
|
'Non spécifié';
|
|
|
|
const beneficiaireNomInput = document.getElementById('incident_beneficiaire_nom');
|
|
const beneficiaireIdInput = document.getElementById('incident_beneficiaire_id');
|
|
|
|
if (beneficiaireNomInput) beneficiaireNomInput.value = beneficiaireNom;
|
|
if (beneficiaireIdInput) beneficiaireIdInput.value = beneficiaireId || '';
|
|
}
|
|
}
|
|
);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Charge l'historique des 3 derniers rendez-vous d'un bénéficiaire
|
|
* @param {number} beneficiaireId - ID du bénéficiaire
|
|
* @returns {Promise<Array>} Tableau des rendez-vous avec leurs incidents
|
|
*/
|
|
async function loadBeneficiaireHistorique(beneficiaireId) {
|
|
try {
|
|
const historique = await apiFetch(`beneficiaires/${beneficiaireId}/historique`);
|
|
return historique || [];
|
|
} catch (error) {
|
|
console.error('Erreur lors du chargement de l\'historique:', error);
|
|
notifyError('Erreur lors du chargement de l\'historique du bénéficiaire');
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Affiche l'historique sous forme de ligne du temps verticale
|
|
* @param {Array} historiqueData - Tableau des rendez-vous avec leurs incidents
|
|
*/
|
|
function displayHistoriqueTimeline(historiqueData) {
|
|
const timelineContainer = document.getElementById('historiqueTimeline');
|
|
if (!timelineContainer) {
|
|
console.error('Conteneur de timeline non trouvé');
|
|
return;
|
|
}
|
|
|
|
if (!historiqueData || historiqueData.length === 0) {
|
|
timelineContainer.innerHTML = `
|
|
<div class="alert alert-info text-center">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
Aucun rendez-vous trouvé pour ce bénéficiaire.
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
let html = '<div class="crvi-timeline">';
|
|
|
|
historiqueData.forEach((rdv, index) => {
|
|
const date = new Date(rdv.date_rdv + 'T' + rdv.heure_rdv);
|
|
const dateFormatted = date.toLocaleDateString('fr-FR', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric'
|
|
});
|
|
const heureFormatted = date.toLocaleTimeString('fr-FR', {
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
});
|
|
|
|
const intervenantNom = rdv.intervenant
|
|
? `${rdv.intervenant.nom || ''} ${rdv.intervenant.prenom || ''}`.trim()
|
|
: 'Non renseigné';
|
|
|
|
const typeInterventionNom = rdv.type_intervention?.nom || 'Non renseigné';
|
|
|
|
// Déterminer le type d'événement et la couleur
|
|
const hasIncident = rdv.incident && rdv.incident.id;
|
|
const statutLower = rdv.statut ? rdv.statut.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") : '';
|
|
|
|
let eventType = 'default';
|
|
let icon = 'fa-calendar-alt';
|
|
|
|
if (hasIncident || statutLower.includes('absence') || statutLower.includes('absent')) {
|
|
eventType = 'incident'; // Rouge
|
|
icon = 'fa-exclamation-triangle';
|
|
} else if (statutLower.includes('present')) {
|
|
eventType = 'present'; // Vert
|
|
icon = 'fa-check-circle';
|
|
} else if (statutLower.includes('prevu')) {
|
|
eventType = 'prevu'; // Bleu
|
|
icon = 'fa-clock';
|
|
} else {
|
|
eventType = 'default'; // Gris clair
|
|
icon = 'fa-calendar-alt';
|
|
}
|
|
|
|
const isLastItem = index === historiqueData.length - 1;
|
|
|
|
html += `
|
|
<div class="crvi-timeline__event crvi-timeline__event--${eventType} ${isLastItem ? 'crvi-timeline__event--last' : ''}">
|
|
<div class="crvi-timeline__event__icon">
|
|
<i class="fas ${icon}"></i>
|
|
<div class="crvi-timeline__event__date">
|
|
${dateFormatted}<br>${heureFormatted}
|
|
</div>
|
|
</div>
|
|
<div class="crvi-timeline__event__content">
|
|
<div class="crvi-timeline__event__title">
|
|
${hasIncident ? '<i class="fas fa-exclamation-triangle me-2"></i>' : ''}
|
|
${rdv.type || 'Rendez-vous'}
|
|
</div>
|
|
<div class="crvi-timeline__event__description">
|
|
<div class="mb-2">
|
|
<strong><i class="fas fa-user-md me-2"></i>Intervenant:</strong> ${intervenantNom}
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong><i class="fas fa-tools me-2"></i>Type d'intervention:</strong> ${typeInterventionNom}
|
|
</div>
|
|
${rdv.statut ? `
|
|
<div class="mb-2">
|
|
<strong><i class="fas fa-info-circle me-2"></i>Statut:</strong>
|
|
<span class="badge bg-${eventType === 'present' ? 'success' : eventType === 'prevu' ? 'primary' : eventType === 'incident' ? 'danger' : 'secondary'}">${rdv.statut}</span>
|
|
</div>
|
|
` : ''}
|
|
${rdv.commentaire ? `
|
|
<div class="mb-2">
|
|
<strong><i class="fas fa-comment me-2"></i>Commentaire:</strong> ${rdv.commentaire}
|
|
</div>
|
|
` : ''}
|
|
${hasIncident ? `
|
|
<div class="alert alert-danger mt-3 mb-0">
|
|
<strong><i class="fas fa-exclamation-triangle me-2"></i>Incident signalé</strong>
|
|
<div class="mt-2">
|
|
<strong>Résumé:</strong> ${rdv.incident.resume_incident || 'Non renseigné'}
|
|
</div>
|
|
${rdv.incident.commentaire_incident ? `
|
|
<div class="mt-2">
|
|
<strong>Commentaire:</strong> ${rdv.incident.commentaire_incident}
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
html += '</div>';
|
|
timelineContainer.innerHTML = html;
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton "Historique bénéficiaire"
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} openSubModal - Fonction pour ouvrir une sous-modale
|
|
*/
|
|
export function initializeHistoriqueButton(getCurrentEventData, openSubModal) {
|
|
const historiqueBtn = document.getElementById('showBeneficiaireHistoriqueBtn');
|
|
if (!historiqueBtn) return;
|
|
|
|
historiqueBtn.onclick = async function() {
|
|
const currentEventData = getCurrentEventData();
|
|
const beneficiaireId = historiqueBtn.getAttribute('data-benef') ||
|
|
currentEventData?.id_beneficiaire ||
|
|
currentEventData?.extendedProps?.id_beneficiaire;
|
|
|
|
if (!beneficiaireId) {
|
|
notifyError('ID du bénéficiaire introuvable');
|
|
return;
|
|
}
|
|
|
|
// Ouvrir la sous-modale avec chargement des données
|
|
openSubModal(
|
|
'beneficiaireHistoriqueModal',
|
|
async (subModal) => {
|
|
// Afficher le spinner de chargement
|
|
const timelineContainer = document.getElementById('historiqueTimeline');
|
|
if (timelineContainer) {
|
|
timelineContainer.innerHTML = `
|
|
<div class="text-center py-4">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Chargement...</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Charger l'historique
|
|
try {
|
|
const historiqueData = await loadBeneficiaireHistorique(parseInt(beneficiaireId));
|
|
displayHistoriqueTimeline(historiqueData);
|
|
} catch (error) {
|
|
console.error('Erreur lors du chargement de l\'historique:', error);
|
|
if (timelineContainer) {
|
|
timelineContainer.innerHTML = `
|
|
<div class="alert alert-danger">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
Erreur lors du chargement de l'historique.
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
},
|
|
(subModal) => {
|
|
// Nettoyer après fermeture
|
|
const timelineContainer = document.getElementById('historiqueTimeline');
|
|
if (timelineContainer) {
|
|
timelineContainer.innerHTML = '';
|
|
}
|
|
}
|
|
);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton "Debug SMS"
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
*/
|
|
export function initializeDebugSmsButton(getCurrentEventData) {
|
|
const debugSmsBtn = document.getElementById('debugSmsBtn');
|
|
if (!debugSmsBtn) return;
|
|
|
|
debugSmsBtn.onclick = function() {
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData ? currentEventData.id : null;
|
|
|
|
console.log('[DEBUG_SMS] Données événement actuelles:', currentEventData);
|
|
|
|
// Construire un message simple pour le debug
|
|
const dateStr = (document.getElementById('date_rdv') && document.getElementById('date_rdv').value) || currentEventData?.date || '';
|
|
const timeStr = (document.getElementById('heure_rdv') && document.getElementById('heure_rdv').value) || currentEventData?.time || '';
|
|
const typeStr = (document.getElementById('type') && document.getElementById('type').value) || currentEventData?.type || '';
|
|
|
|
const msg = `Debug SMS - Event ${eventId ?? 'N/A'} - ${dateStr} ${timeStr} - type: ${typeStr}`;
|
|
const phone = '0485500723';
|
|
|
|
if (!window.crviAjax || !window.crviAjax.url || !window.crviAjax.nonce) {
|
|
alert('Debug SMS: configuration AJAX manquante.');
|
|
return;
|
|
}
|
|
|
|
const params = new URLSearchParams();
|
|
params.append('action', 'crvi_send_sms_debug');
|
|
params.append('nonce', window.crviAjax.nonce);
|
|
params.append('phone', phone);
|
|
params.append('message', msg);
|
|
if (eventId) {
|
|
params.append('id_event', String(eventId));
|
|
}
|
|
params.append('sujet', 'debug');
|
|
|
|
fetch(window.crviAjax.url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
},
|
|
body: params.toString()
|
|
}).then(async (res) => {
|
|
let json;
|
|
try { json = await res.json(); } catch (_) {}
|
|
if (!res.ok || !json?.success) {
|
|
const errMsg = json?.data?.message || 'Erreur lors de l\'envoi SMS (debug).';
|
|
throw new Error(errMsg);
|
|
}
|
|
alert('SMS de debug envoyé.');
|
|
}).catch((err) => {
|
|
console.error('[DEBUG_SMS] Échec envoi:', err);
|
|
alert('Échec envoi SMS de debug: ' + (err?.message || 'Erreur inconnue'));
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise le bouton "Voir les incidents"
|
|
* @param {Function} getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} openIncidentsViewModal - Fonction pour ouvrir la modal de visualisation des incidents
|
|
*/
|
|
export function initializeViewIncidentsButton(getCurrentEventData, openIncidentsViewModal) {
|
|
const viewIncidentsBtn = document.getElementById('viewIncidentsBtn');
|
|
if (!viewIncidentsBtn) return;
|
|
|
|
viewIncidentsBtn.onclick = async function() {
|
|
const currentEventData = getCurrentEventData();
|
|
const eventId = currentEventData?.id || currentEventData?.extendedProps?.id;
|
|
|
|
if (!eventId) {
|
|
notifyError('ID de l\'événement introuvable');
|
|
return;
|
|
}
|
|
|
|
await openIncidentsViewModal(eventId);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialise tous les boutons de la modale
|
|
* @param {Object} options - Options de configuration
|
|
* @param {Function} options.getCurrentEventData - Fonction pour obtenir les données de l'événement
|
|
* @param {Function} options.getCurrentMode - Fonction pour obtenir le mode actuel
|
|
* @param {Function} options.setCurrentMode - Fonction pour changer le mode
|
|
* @param {Function} options.openSubModal - Fonction pour ouvrir une sous-modale
|
|
* @param {Function} options.openCheckPresenceModal - Fonction pour ouvrir la modal de validation de présence
|
|
* @param {Function} options.openIncidentsViewModal - Fonction pour ouvrir la modal de visualisation des incidents
|
|
* @param {Function} options.enableDateSynchronization - Fonction pour activer la synchronisation des dates
|
|
* @param {Function} options.disableDateSynchronization - Fonction pour désactiver la synchronisation des dates
|
|
* @param {Function} options.onDeleted - Callback après suppression
|
|
* @param {Function} options.onStatusChanged - Callback après changement de statut
|
|
*/
|
|
export function initializeModalButtons(options = {}) {
|
|
const {
|
|
getCurrentEventData,
|
|
getCurrentMode,
|
|
setCurrentMode,
|
|
openSubModal,
|
|
openCheckPresenceModal,
|
|
openIncidentsViewModal,
|
|
enableDateSynchronization,
|
|
disableDateSynchronization,
|
|
onDeleted,
|
|
onStatusChanged
|
|
} = options;
|
|
|
|
// Boutons de fermeture
|
|
initializeCloseButton('closeModalBtn');
|
|
initializeCloseButton('closeViewBtn');
|
|
|
|
// Boutons d'action
|
|
if (getCurrentEventData) {
|
|
initializeEditButton(getCurrentEventData, getCurrentMode, setCurrentMode, enableDateSynchronization);
|
|
initializeCancelButton(getCurrentEventData, getCurrentMode, setCurrentMode, disableDateSynchronization);
|
|
initializeSaveButton(getCurrentEventData, getCurrentMode, disableDateSynchronization);
|
|
initializeDeleteButton(getCurrentEventData, onDeleted);
|
|
initializeMarkPresentButton(getCurrentEventData, openCheckPresenceModal, onStatusChanged);
|
|
initializeMarkAbsentButton(getCurrentEventData, onStatusChanged);
|
|
initializeCancelAppointmentButton(getCurrentEventData, onStatusChanged);
|
|
initializeDebugSmsButton(getCurrentEventData);
|
|
|
|
// Boutons spécifiques avec sous-modales
|
|
if (openSubModal) {
|
|
initializeReportIncidentButton(getCurrentEventData, openSubModal);
|
|
initializeHistoriqueButton(getCurrentEventData, openSubModal);
|
|
}
|
|
|
|
// Bouton de visualisation des incidents
|
|
if (openIncidentsViewModal) {
|
|
initializeViewIncidentsButton(getCurrentEventData, openIncidentsViewModal);
|
|
}
|
|
}
|
|
}
|