352 lines
15 KiB
JavaScript
352 lines
15 KiB
JavaScript
// Module d'affichage des données de la modale
|
|
// Contient les fonctions d'affichage en mode lecture seule
|
|
|
|
import { setText, toggleElement } from './agenda-modal-dom.js';
|
|
import { checkAndDisplayIncidentsButton } from './agenda-modal.js';
|
|
|
|
/**
|
|
* Extrait la date et l'heure d'un événement selon différentes sources
|
|
* @param {Object} event - Données de l'événement
|
|
* @returns {Object} - {dateFormatted, heureFormatted}
|
|
*/
|
|
function extractDateTime(event) {
|
|
let dateFormatted = '';
|
|
let heureFormatted = '';
|
|
|
|
// Priorité 1: Données directes de l'API
|
|
if (event?.date && event?.heure) {
|
|
const dateObj = new Date(event.date + 'T' + event.heure);
|
|
dateFormatted = dateObj.toLocaleDateString('fr-FR');
|
|
heureFormatted = dateObj.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
|
|
}
|
|
// Priorité 2: Données dans extendedProps
|
|
else if (event?.extendedProps?.date && event?.extendedProps?.heure) {
|
|
const dateObj = new Date(event.extendedProps.date + 'T' + event.extendedProps.heure);
|
|
dateFormatted = dateObj.toLocaleDateString('fr-FR');
|
|
heureFormatted = dateObj.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
|
|
}
|
|
// Priorité 3: Données FullCalendar
|
|
else if (event?.start) {
|
|
const startDate = new Date(event.start);
|
|
dateFormatted = startDate.toLocaleDateString('fr-FR');
|
|
heureFormatted = startDate.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
|
|
}
|
|
|
|
return { dateFormatted, heureFormatted };
|
|
}
|
|
|
|
/**
|
|
* Récupère le nom d'une entité depuis le select ou les données
|
|
* @param {string} entityName - Nom de l'entité ('beneficiaire', 'intervenant', etc.)
|
|
* @param {Object} event - Données de l'événement
|
|
* @param {string} selectId - ID du select
|
|
* @param {string} idField - Nom du champ ID
|
|
* @returns {string} - Nom formaté
|
|
*/
|
|
function getEntityName(entityName, event, selectId, idField) {
|
|
let name = '';
|
|
|
|
// Vérifier dans les relations directes
|
|
if (event?.[entityName]?.nom) {
|
|
name = event[entityName].nom + (event[entityName].prenom ? ' ' + event[entityName].prenom : '');
|
|
} else if (event?.extendedProps?.[entityName]?.nom) {
|
|
name = event.extendedProps[entityName].nom + (event.extendedProps[entityName].prenom ? ' ' + event.extendedProps[entityName].prenom : '');
|
|
} else {
|
|
// Chercher par ID dans le select
|
|
const entityId = event?.[idField] || event?.extendedProps?.[idField];
|
|
if (entityId) {
|
|
const select = document.getElementById(selectId);
|
|
// Vérifier si c'est un SELECT (pour intervenant côté front c'est un input hidden)
|
|
if (select && select.tagName === 'SELECT') {
|
|
const option = select.querySelector(`option[value="${entityId}"]`);
|
|
if (option) {
|
|
name = option.textContent;
|
|
}
|
|
} else if (select && selectId === 'id_intervenant') {
|
|
// Cas spécial pour intervenant côté front (input hidden)
|
|
const displayEl = document.getElementById('id_intervenant_display');
|
|
if (displayEl && displayEl.textContent) {
|
|
name = displayEl.textContent;
|
|
}
|
|
}
|
|
|
|
if (!name) {
|
|
name = `ID: ${entityId}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Récupère le nom d'un terme taxonomy depuis les données ou le select
|
|
* @param {Object} event - Données de l'événement
|
|
* @param {string} labelField - Champ de label (_label)
|
|
* @param {string} relationField - Champ de relation
|
|
* @param {string} idField - Champ ID
|
|
* @param {string} selectId - ID du select
|
|
* @returns {string} - Nom du terme
|
|
*/
|
|
function getTermName(event, labelField, relationField, idField, selectId) {
|
|
let name = '';
|
|
|
|
// Priorité 1: Label direct
|
|
name = event?.[labelField] || event?.extendedProps?.[labelField] || '';
|
|
|
|
// Priorité 2: Relation
|
|
if (!name && event?.[relationField]?.nom) {
|
|
name = event[relationField].nom;
|
|
} else if (!name && event?.extendedProps?.[relationField]?.nom) {
|
|
name = event.extendedProps[relationField].nom;
|
|
}
|
|
|
|
// Priorité 3: Chercher dans le select
|
|
if (!name) {
|
|
const termId = event?.[idField] || event?.extendedProps?.[idField];
|
|
if (termId && termId !== '0' && termId !== 0) {
|
|
const select = document.getElementById(selectId);
|
|
if (select) {
|
|
const option = select.querySelector(`option[value="${termId}"]`);
|
|
if (option) {
|
|
name = option.textContent;
|
|
}
|
|
}
|
|
if (!name) {
|
|
name = `ID: ${termId}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Remplit le bloc de vue avec les données d'un événement
|
|
* @param {Object} event - Données de l'événement
|
|
*/
|
|
export function fillViewBlock(event) {
|
|
// Date et heure
|
|
const { dateFormatted, heureFormatted } = extractDateTime(event);
|
|
setText('view_date_rdv', dateFormatted);
|
|
setText('view_heure_rdv', heureFormatted);
|
|
|
|
// Type et langue
|
|
const type = event?.type || event?.extendedProps?.type || '';
|
|
setText('view_type', type);
|
|
|
|
let langue = event?.langue_label || event?.extendedProps?.langue_label || '';
|
|
if (!langue || /^\d+$/.test(langue)) {
|
|
const langueId = langue || event?.langue || event?.extendedProps?.langue || '';
|
|
if (langueId) {
|
|
const langueSelect = document.getElementById('langue');
|
|
if (langueSelect) {
|
|
const option = langueSelect.querySelector(`option[value="${langueId}"]`);
|
|
if (option) {
|
|
langue = option.textContent;
|
|
} else {
|
|
langue = langueId;
|
|
}
|
|
} else {
|
|
langue = langueId;
|
|
}
|
|
}
|
|
}
|
|
if (!langue) {
|
|
langue = event?.langue || event?.extendedProps?.langue || '';
|
|
}
|
|
setText('view_langue', langue);
|
|
|
|
// Entités
|
|
setText('view_beneficiaire', getEntityName('beneficiaire', event, 'id_beneficiaire', 'id_beneficiaire'));
|
|
setText('view_intervenant', getEntityName('intervenant', event, 'id_intervenant', 'id_intervenant'));
|
|
setText('view_local', getEntityName('local', event, 'id_local', 'id_local'));
|
|
|
|
// Termes taxonomy
|
|
setText('view_departement', getTermName(event, 'departement_label', 'departement', 'id_departement', 'id_departement'));
|
|
setText('view_type_intervention', getTermName(event, 'type_intervention_label', 'type_intervention', 'id_type_intervention', 'id_type_intervention'));
|
|
|
|
// Traducteur (logique spéciale)
|
|
let traducteurNom = '';
|
|
const traducteurId = event?.id_traducteur || event?.extendedProps?.id_traducteur;
|
|
const hasValidTraducteurId = traducteurId && parseInt(traducteurId, 10) > 0;
|
|
|
|
if (hasValidTraducteurId) {
|
|
traducteurNom = getEntityName('traducteur', event, 'id_traducteur', 'id_traducteur');
|
|
} else {
|
|
traducteurNom = event?.nom_traducteur || event?.extendedProps?.nom_traducteur || '';
|
|
}
|
|
setText('view_traducteur', traducteurNom);
|
|
|
|
// Données de groupe
|
|
const eventType = event?.type || event?.extendedProps?.type || '';
|
|
const groupeFields = document.querySelectorAll('.groupe-only-field');
|
|
|
|
if (eventType === 'groupe') {
|
|
groupeFields.forEach(field => field.style.display = '');
|
|
setText('view_nb_participants', event?.nb_participants || event?.extendedProps?.nb_participants || '');
|
|
setText('view_nb_hommes', event?.nb_hommes || event?.extendedProps?.nb_hommes || '');
|
|
setText('view_nb_femmes', event?.nb_femmes || event?.extendedProps?.nb_femmes || '');
|
|
} else {
|
|
groupeFields.forEach(field => field.style.display = 'none');
|
|
setText('view_nb_participants', '');
|
|
setText('view_nb_hommes', '');
|
|
setText('view_nb_femmes', '');
|
|
}
|
|
|
|
// Commentaire
|
|
setText('view_commentaire', event?.commentaire || event?.extendedProps?.commentaire || '');
|
|
|
|
// Bouton historique bénéficiaire (uniquement pour événements individuels)
|
|
const historiqueBtn = document.getElementById('showBeneficiaireHistoriqueBtn');
|
|
if (historiqueBtn) {
|
|
const beneficiaireId = event?.id_beneficiaire || event?.extendedProps?.id_beneficiaire;
|
|
if (eventType === 'individuel' && beneficiaireId) {
|
|
historiqueBtn.style.display = 'block';
|
|
historiqueBtn.setAttribute('data-benef', beneficiaireId);
|
|
} else {
|
|
historiqueBtn.style.display = 'none';
|
|
historiqueBtn.removeAttribute('data-benef');
|
|
}
|
|
}
|
|
|
|
// Vérifier et afficher le bouton "Détail incident(s)" si l'événement a des incidents
|
|
const eventId = event?.id || event?.extendedProps?.id;
|
|
if (eventId) {
|
|
checkAndDisplayIncidentsButton(eventId);
|
|
}
|
|
|
|
// Afficher l'alerte de statut si présent ou absent
|
|
const statut = event?.statut || event?.extendedProps?.statut || '';
|
|
const statutAlert = document.getElementById('statutAlert');
|
|
const statutAlertText = document.getElementById('statutAlertText');
|
|
|
|
if (statutAlert && statutAlertText) {
|
|
if (statut === 'absent' || statut === 'absence') {
|
|
statutAlert.className = 'alert alert-danger mb-3';
|
|
statutAlertText.textContent = 'La personne a été marquée comme absente à ce rendez-vous.';
|
|
statutAlert.style.display = 'block';
|
|
} else if (statut === 'present') {
|
|
statutAlert.className = 'alert alert-success mb-3';
|
|
statutAlertText.textContent = 'La personne a été présente à ce rendez-vous.';
|
|
statutAlert.style.display = 'block';
|
|
} else {
|
|
statutAlert.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Met à jour l'affichage de la modale selon le mode
|
|
* @param {string} mode - Mode actuel ('view', 'edit', 'create')
|
|
* @param {boolean} canEdit - Permission d'édition
|
|
* @param {boolean} canDelete - Permission de suppression
|
|
* @param {Object} eventData - Données de l'événement (optionnel)
|
|
*/
|
|
export function updateModalDisplay(mode, canEdit, canDelete, eventData = null) {
|
|
const viewBlock = document.getElementById('eventViewBlock');
|
|
const formBlock = document.getElementById('eventForm');
|
|
const statusButtons = document.getElementById('eventStatusButtons');
|
|
const viewFooter = document.getElementById('eventViewFooter');
|
|
const editFooter = document.getElementById('eventEditFooter');
|
|
const editBtn = document.getElementById('editEventBtn');
|
|
const deleteBtn = document.getElementById('deleteEvent');
|
|
const saveBtn = document.getElementById('saveEvent');
|
|
const cancelBtn = document.getElementById('cancelEditBtn');
|
|
const closeViewBtn = document.getElementById('closeViewBtn');
|
|
|
|
// Vérifier le statut et si l'événement est clôturé
|
|
const statut = eventData?.statut || eventData?.extendedProps?.statut || '';
|
|
const clotureFlag = eventData?.cloture_flag || eventData?.extendedProps?.cloture_flag;
|
|
const isEventCloture = clotureFlag === 1 || clotureFlag === '1' || clotureFlag === true;
|
|
const eventType = eventData?.type || eventData?.extendedProps?.type || '';
|
|
const isGroupe = eventType === 'groupe';
|
|
|
|
// Vérifier si les boutons de statut doivent être cachés
|
|
const shouldHideStatusButtons = statut === 'present' || statut === 'absence' || isEventCloture;
|
|
|
|
if (mode === 'view') {
|
|
if (viewBlock) viewBlock.style.display = 'block';
|
|
if (formBlock) formBlock.style.display = 'none';
|
|
if (viewFooter) viewFooter.style.display = 'block';
|
|
if (editFooter) editFooter.style.display = 'none';
|
|
if (editBtn) editBtn.style.display = canEdit ? 'inline-block' : 'none';
|
|
if (deleteBtn) deleteBtn.style.display = 'none';
|
|
if (saveBtn) saveBtn.style.display = 'none';
|
|
if (cancelBtn) cancelBtn.style.display = 'none';
|
|
if (closeViewBtn) closeViewBtn.style.display = 'inline-block';
|
|
|
|
// Cacher tous les boutons de statut en mode vue
|
|
if (statusButtons) statusButtons.style.display = 'none';
|
|
|
|
} else if (mode === 'edit' || mode === 'create') {
|
|
if (viewBlock) viewBlock.style.display = 'none';
|
|
if (formBlock) formBlock.style.display = 'block';
|
|
if (viewFooter) viewFooter.style.display = 'none';
|
|
if (editFooter) editFooter.style.display = 'block';
|
|
if (editBtn) editBtn.style.display = 'none';
|
|
if (deleteBtn) deleteBtn.style.display = (mode === 'edit' && canDelete) ? 'inline-block' : 'none';
|
|
if (saveBtn) saveBtn.style.display = 'inline-block';
|
|
if (cancelBtn) cancelBtn.style.display = 'inline-block';
|
|
if (closeViewBtn) closeViewBtn.style.display = 'none';
|
|
|
|
// Afficher ou cacher les boutons de statut selon le statut de l'événement
|
|
if (statusButtons) {
|
|
if (mode === 'edit' && canEdit && !shouldHideStatusButtons) {
|
|
statusButtons.style.display = 'block';
|
|
|
|
// Gérer l'affichage des boutons individuels selon le type d'événement
|
|
const allButtons = statusButtons.querySelectorAll('button');
|
|
allButtons.forEach(btn => {
|
|
// Masquer "Absent" pour les événements de groupe
|
|
if (btn.id === 'markAbsentBtn') {
|
|
btn.style.display = isGroupe ? 'none' : 'inline-block';
|
|
}
|
|
// Le bouton "Détail incident(s)" garde son état (géré par checkAndDisplayIncidentsButton)
|
|
else if (btn.id === 'viewIncidentsBtn') {
|
|
// Ne rien faire, l'état est géré ailleurs
|
|
}
|
|
// Afficher tous les autres boutons
|
|
else {
|
|
btn.style.display = 'inline-block';
|
|
}
|
|
});
|
|
} else {
|
|
statusButtons.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vérifie si un événement est passé
|
|
* @param {Object} eventData - Données de l'événement
|
|
* @returns {boolean} - True si l'événement est passé
|
|
*/
|
|
export function checkIfEventIsPast(eventData) {
|
|
if (!eventData) return false;
|
|
|
|
let eventDate = null;
|
|
let eventTime = null;
|
|
|
|
// Essayer différentes sources pour la date
|
|
if (eventData.date_rdv) {
|
|
eventDate = eventData.date_rdv;
|
|
eventTime = eventData.heure_rdv || '00:00';
|
|
} else if (eventData.start) {
|
|
const startDate = new Date(eventData.start);
|
|
eventDate = startDate.toISOString().split('T')[0];
|
|
eventTime = startDate.toTimeString().substring(0, 5);
|
|
} else if (eventData.extendedProps?.date_rdv) {
|
|
eventDate = eventData.extendedProps.date_rdv;
|
|
eventTime = eventData.extendedProps.heure_rdv || '00:00';
|
|
}
|
|
|
|
if (!eventDate) return false;
|
|
|
|
const eventDateTime = new Date(`${eventDate}T${eventTime}`);
|
|
const now = new Date();
|
|
|
|
return eventDateTime <= now;
|
|
}
|