// Intercepteur global pour gérer les erreurs 401 (session expirée) const originalFetch = window.fetch; window.fetch = async function (...args) { const response = await originalFetch.apply(this, args); if (response.status === 401) { try { const data = await response.clone().json(); if (data.redirect) { alert( "Votre session a expiré. Vous allez être redirigé vers la page de connexion.", ); window.location.href = data.redirect; } } catch (e) { // Si ce n'est pas du JSON, on laisse passer } } return response; }; //gestion des form villes et adresse const ADDOK_URL = "https://api-adresse.data.gouv.fr/search/"; function debounce(fn, delay) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } /** * Objectif : Configurer un champ d'adresse avec autocomplétion en utilisant une API externe. * Paramètres : * - param1 (string) : L'identifiant de l'élément input où l'utilisateur saisit l'adresse. * - param2 (string) : L'identifiant de l'élément où les suggestions d'autocomplétion seront affichées. * - requete (string) : La requête supplémentaire à ajouter à l'URL de l'API. */ async function setupadresse(param1, param2, requete) { const inputElement = document.getElementById(param1); const suggestionsElement = document.getElementById(param2); if (!inputElement || !suggestionsElement) { console.error("Éléments DOM non trouvés"); return; } inputElement.addEventListener( "input", debounce(async function () { const query = inputElement.value; // Si la longueur de la requête est inférieure à 3, efface les suggestions if (query.length < 3) { suggestionsElement.innerHTML = ""; return; } try { // Envoie une requête à l'API pour obtenir des suggestions d'autocomplétion const response = await fetch( `${ADDOK_URL}?q=${query}&limit=5${requete}`, ); const data = await response.json(); suggestionsElement.innerHTML = ""; // Si des suggestions sont disponibles, les affiche if (data.features.length > 0) { data.features.forEach((feature) => { const suggestion = document.createElement("div"); suggestion.classList.add("autocomplete-suggestion"); // Détermine le contenu de la suggestion en fonction de la requête if (requete === "&type=municipality") { suggestion.textContent = `${feature.properties.city} (${feature.properties.postcode})`; } else { suggestion.textContent = feature.properties.label; } // Ajoute un écouteur d'événement 'click' à chaque suggestion suggestion.addEventListener("click", function () { if (requete === "&type=municipality") { inputElement.value = `${feature.properties.city} (${feature.properties.postcode})`; } else { inputElement.value = feature.properties.label; } suggestionsElement.innerHTML = ""; }); // Ajoute la suggestion à l'élément de suggestions suggestionsElement.appendChild(suggestion); }); } } catch (error) { console.error("Erreur lors de la récupération des suggestions:", error); } }, 300), ); } /** * Objectif : Décoder une chaîne base64 et parser le JSON. * Paramètres : * - encodedString (string) : La chaîne encodée en base64. * Retourne : * - (object) : L'objet JSON décodé. */ function decodeBase64Json(encodedString) { return JSON.parse( new TextDecoder().decode( Uint8Array.from(atob(encodedString), (c) => c.charCodeAt(0)), ), ); } /** * Objectif : Afficher les informations d'une personne dans une fenêtre contextuelle en fonction de son rôle (bénévole ou jeune). * Paramètres : * - personne (string) : Une chaîne encodée en base64 contenant les informations de la personne au format JSON. */ function PopUpInfos(personne) { // Décode la chaîne base64 et parse le JSON const personneData = decodeBase64Json(personne); let content = ""; // Si la personne est un bénévole (contient voeu1), affiche les informations correspondantes if (personneData.voeu1) { const isGroupRole = ["responsable de groupe", "accompagnateur"].includes( (personneData.voeu1 || "").trim().toLowerCase(), ); content = `

${personneData.voeu1 || "—"}

${isGroupRole && personneData.groupe_nom ? `

${personneData.groupe_nom}

` : ""}

${personneData.tel}

${personneData.email}


Contact d'urgence: ${personneData.contact_urgence}

${personneData.tel_urgence}


Problèmes médicaux: ${personneData.alergie || "aucun"}

Régime: ${personneData.regime || "aucun"}

Date de naissance: ${formatDateFR(personneData.date_naissance)}


${(["responsable de groupe", "accompagnateur"].includes((personneData.voeu1 || "").trim().toLowerCase()) ? personneData.groupe_paiement : true) ? `

Paiement : ${personneData.paye ? '' : ''}

` : ""}

B3 : ${personneData.B2depose ? (personneData.B2valide ? '' : "👁 déposé") : ''}

`; } else { // Si la personne est un jeune, affiche les informations correspondantes content = `

${ new Date().getFullYear() - new Date(personneData.date_naissance).getFullYear() } ans (${formatDateFR(personneData.date_naissance)})

${personneData.groupe_nom ? `

${personneData.groupe_nom}

` : ""}

${personneData.prenom_responsable} ${ personneData.nom_responsable }

${personneData.email_responsable}

${personneData.tel_responsable}


Régime: ${personneData.regime || "aucun"}

${personneData.groupe_paiement ? `

Paiement : ${personneData.paye ? '' : ''}

` : ""} `; } // Affiche la fenêtre contextuelle avec les informations de la personne const overlayPoste = document.getElementById("overlayPoste"); const namediv = document.getElementById("namediv"); const modifdiv = document.getElementById("modif"); modifdiv.innerHTML = ""; const contentdiv = document.getElementById("contentdiv"); if (overlayPoste && namediv && contentdiv) { overlayPoste.style.display = "flex"; namediv.innerHTML = `${personneData.prenom} ${personneData.nom}`; contentdiv.innerHTML = content; } else { console.error("Éléments DOM non trouvés"); } } function toggleField(number) { //affiche le champ regime ou alergie var regimeInput = document.getElementById(number); if (document.getElementById(number.concat("_oui")).checked) { regimeInput.style.display = "block"; } else { regimeInput.style.display = "none"; } } const formatDateFR = (dateString) => { const date = new Date(dateString); const day = String(date.getDate()).padStart(2, "0"); const month = String(date.getMonth() + 1).padStart(2, "0"); const year = date.getFullYear(); return `${day}-${month}-${year}`; }; function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(";").shift(); } function cleanmessage(time = 10) { setTimeout(() => { document.getElementById("paramMessage").innerText = ""; document.getElementById("paramMessage").style.display = "none"; }, time * 1000); } function aff_message(message, backgroundColor) { document.getElementById("paramMessage").innerText = message; document.getElementById("paramMessage").style.backgroundColor = backgroundColor; document.getElementById("paramMessage").style.display = "block"; } /** * Objectif : Remplir un formulaire de modification des informations d'un jeune en fonction de son ID et du statut administrateur de l'utilisateur. * Paramètres : * - id (string) : L'identifiant du jeune dont les informations doivent être modifiées. */ async function formModifJeune(id) { try { // Récupère les informations du jeune à partir de l'API const response = await fetch("/infojeune/" + id); const data = await response.json(); // Met à jour le titre de la section de modification const namediv = document.getElementById("namediv"); if (namediv) { namediv.innerText = `Modifiez le profil de ${data.prenom} ${data.nom}`; } // Remplit le formulaire avec les informations du jeune const modifDiv = document.getElementById("modif"); if (modifDiv) { modifDiv.innerHTML = `
${ data.isAdmin ? `
` : `` }
`; } // Sélectionne la classe actuelle du jeune let selectElement = document.getElementById("classe_modif"); if (selectElement) { selectElement.value = data.classe; } // Sélectionne le genre actuel du jeune selectElement = document.getElementById("genre_modif"); if (selectElement) { selectElement.value = data.genre; } // Si l'utilisateur est administrateur, récupère la liste des groupes et remplit le select if (data.isAdmin != 0) { try { const data2 = await fetch("/list_groupe").then((r) => r.json()); const select = document.getElementById("groupe_id"); if (select) { const frag = document.createDocumentFragment(); data2.forEach((group) => { const option = document.createElement("option"); option.value = group.id; option.textContent = group.nom; if (group.id === data.groupe_id) option.selected = true; frag.appendChild(option); }); select.appendChild(frag); } } catch (error) { console.error("Error fetching group list:", error); } } // Affiche la fenêtre contextuelle const overlayPoste = document.getElementById("overlayPoste"); if (overlayPoste) { overlayPoste.style.display = "flex"; } } catch (error) { console.error("Error fetching user data:", error); } } function formValidePaiement(id, name, paye, paiementref, type) { document.getElementById("namediv").innerHTML = `Paiement de ${decodeURIComponent(name)}`; // Définition des états des radios avec icônes let checkedPayé = paye ? "checked" : ""; let checkedNonPayé = !paye ? "checked" : ""; // Formulaire stylisé avec classes CSS document.getElementById("modif").innerHTML = `




`; // Affichage du formulaire document.getElementById("overlayPoste").style.display = "flex"; // Gestion du bouton Valider document.getElementById("Valide1").addEventListener("click", function () { let selectedStatus = document.querySelector( 'input[name="statusPaiement"]:checked', ).value; let refPaiement = document.getElementById("refPaiement").value; // Redirection avec les paramètres en GET window.location.href = `/modifPaiemnt/${type}/${id}/${selectedStatus}/${encodeURIComponent( refPaiement, )}`; }); } function formValideB3Direct(id, name) { document.getElementById("namediv").innerHTML = `Valider le B3 de ${decodeURIComponent(name)}`; document.getElementById("modif").innerHTML = `

Valider un B3 reçu par un autre moyen (mail, messagerie...)

`; document.getElementById("overlayPoste").style.display = "flex"; document.getElementById("Valide1").addEventListener("click", function () { window.location.href = `/valideB3Direct/${id}`; }); } function suppr(type, id) { let message = ""; let fetchUrl = ""; let redirectUrl = ""; if (type === "ben") { fetchUrl = "/infoBen/" + id; redirectUrl = "/suppr_ben/" + id; // URL de redirection pour la suppression du bénévole } else if (type === "jeune") { fetchUrl = "/infojeune/" + id; redirectUrl = "/suppr_jeune/" + id; // URL de redirection pour la suppression du jeune } else if (type === "groupe") { fetchUrl = "/list_groupe"; // URL pour récupérer les infos du groupe redirectUrl = "/suppr_groupe/" + id; // URL de redirection pour la suppression du groupe } fetch(fetchUrl) .then((response) => response.json()) .then((data) => { // Construire le message d'information if (type === "groupe") { data.forEach((groupe) => { if (groupe.id == id) { nomgroupe = groupe.nom; } }); message = `Supprimer le groupe ${nomgroupe}`; } else { message = `Supprimer l'inscription de ${data.prenom} ${data.nom}`; } const confirmDelete = confirm(message); if (confirmDelete) { window.location.href = redirectUrl; } }) .catch((error) => console.error("Erreur lors de la récupération des informations:", error), ); } function afficheplanben(id) { window.open( `/calendar/${id} `, "_blank", "location=yes,height=570,width=800,scrollbars=yes,status=yes", ); } // affiche feuille medicale function openMedicalFile(id) { window.open("/fiche-medicale/".concat(id)); } function formModifBenevole(id) { fetch("/infoBen/" + id) .then((response) => response.json()) .then((data) => { document.getElementById("namediv").innerText = `Modifiez le profil de ${data.prenom} ${data.nom}`; document.getElementById("modif").innerHTML = `
${ data.isAdmin && ["responsable de groupe", "accompagnateur"].includes( (data.voeu1 || "").trim().toLowerCase(), ) ? `
` : `` }
`; const select = document.getElementById("groupe_id"); if (select && select.tagName === "SELECT") { fetch("/list_groupe") .then((response) => response.json()) .then((data2) => { const frag = document.createDocumentFragment(); const emptyOption = document.createElement("option"); emptyOption.value = ""; emptyOption.textContent = "Sans groupe"; frag.appendChild(emptyOption); data2.forEach((group) => { const option = document.createElement("option"); option.value = group.id; option.textContent = group.nom; if (group.id === data.groupe_id) option.selected = true; frag.appendChild(option); }); select.appendChild(frag); document.getElementById("overlayPoste").style.display = "flex"; }) .catch((error) => console.error("Error fetching group list:", error)); } else { document.getElementById("overlayPoste").style.display = "flex"; } }); } //downlad excel from table function exporterTableauxEnExcel(nom, tabs) { var wb = XLSX.utils.book_new(); tabs.forEach((tab) => { var tableau1 = document.getElementById(tab); var data = []; var rows = tableau1.querySelectorAll("tr"); rows.forEach((row) => { var rowData = []; var cells = row.querySelectorAll("th, td"); cells.forEach((cell, index) => { if ( cell.id !== "omit-column" && !cell.classList.contains("omit-column") ) { rowData.push(cell.innerText); } }); data.push(rowData); }); var ws1 = XLSX.utils.aoa_to_sheet(data); XLSX.utils.book_append_sheet(wb, ws1, tab); }); var currentDate = formatDateFR(new Date().toISOString()); var name = `${nom}_${currentDate}.xlsx`; XLSX.writeFile(wb, name); } function downladBadgeZIP(id, jeune, ben) { // Transformer les listes de jeunes et bénévoles en une chaîne de caractères const jeunes = jeune.split(",").map(Number).join(","); const benevoles = ben.split(",").map(Number).join(","); // Télécharger le fichier ZIP contenant tous les badges const zipUrl = `/download-pdf-zip?id=${id}&jeunes=${jeunes}&benevoles=${benevoles}`; window.location.href = zipUrl; } function downladBadgeZIPListe(type, liste, filtre = "") { // Transformer les listes de jeunes et bénévoles en une chaîne de caractères liste = liste.split(",").map(Number).join(","); // Télécharger le fichier ZIP contenant tous les badges let zipUrl = `/download-pdf-liste-zip?type=${type}&liste=${liste}`; if (filtre && filtre !== "tous") zipUrl += `&filtre=${encodeURIComponent(filtre)}`; window.location.href = zipUrl; } function toggleSection(name, toog, nonclique) { const formContent = document.getElementById(name); const toggleButton = document.getElementById(toog); let cookiedisplay = null; if (nonclique != null) { cookiedisplay = getCookie(name); if (cookiedisplay == null) { cookiedisplay = nonclique; } } const date = new Date(); date.setTime(date.getTime() + 15 * 60 * 1000); // expire apres 15 min const expires = "expires=" + date.toUTCString(); if ( cookiedisplay == "block" || (!nonclique && (formContent.style.display === "none" || formContent.style.display === "")) ) { formContent.style.display = "block"; // Afficher le contenu toggleButton.classList.add("rotate"); // Tourner la flèche vers le bas document.cookie = `${name}=block;${expires};SameSite=Strict; path=/; secure`; } else if ( cookiedisplay == "none" || (!nonclique && formContent.style.display === "block") ) { formContent.style.display = "none"; // Masquer le contenu toggleButton.classList.remove("rotate"); // Tourner la flèche vers la droite document.cookie = `${name}=none;${expires};SameSite=Strict; path=/; secure`; } } function loadQuill(quill, name, editor, content) { // Vérifier si Quill est déjà chargé if (typeof Quill === "undefined") { // Créer un élément pour charger le CSS de Quill var link = document.createElement("link"); link.rel = "stylesheet"; link.href = "https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.snow.css"; document.head.appendChild(link); // Créer un élément