/** * INITIALISATION GÉNÉRALE */ /** * Gère la pré-connexion via cookie (chargement du formulaire et focus intelligent). * Récupère le login mémorisé et place le curseur dans le champ approprié. */ function connexion_cookie() { const racine = $("#racineWeb").val() || ""; const msgErreur = $("#msgErreur").val(); $.ajax({ url: racine + "Ajaxconnexioncookie/", type: 'POST', cache: false, // Utilisation d'un objet pour un encodage automatique sécurisé data: { msgErreur: msgErreur }, success: function(data) { // Injection du formulaire de connexion $("#div_ajaxconnexion").html(data); // Initialisation des composants stylisés if ($.isFunction($.fn.selectpicker)) { $(".selectpicker").selectpicker('refresh'); } }, error: function(xhr, status, error) { console.error("Erreur lors du chargement des cookies de connexion:", error); }, complete: function() { // Gestion intelligente du focus const $loginField = $("#login"); const $mdpField = $("#mdp"); const $codeSocieteField = $("#codeSociete"); // Si un login est déjà présent (issu du cookie) if ($loginField.val() && $loginField.val().trim() !== "") { // On place le curseur sur le mot de passe $mdpField.focus(); } else { // Sinon, on commence par le début (Code Société ou Login) if ($codeSocieteField.length > 0) { $codeSocieteField.focus(); } else { $loginField.focus(); } } } }); } $(function() { // 1. Initialisation des composants au chargement de la page appliquerDataTable('.tabliste'); // 2. Lancement du cycle de rafraîchissement automatique const vueActuelle = $("#vue").val(); // On ne lance le timer que si l'utilisateur est connecté (pas sur la vue Connexion) if (vueActuelle !== "Connexion") { setInterval(function() { // On vérifie si l'onglet est actif pour éviter des requêtes inutiles if (!document.hidden) { raffraichier_gabarit(); } }, 60000); // 60 secondes } }); /** * Fonction principale de rafraîchissement du gabarit (UI et Session) * Gère la mise à jour des données et la redirection forcée en cas de déconnexion. */ function raffraichier_gabarit() { const racine = $("#racineWeb").val() || "/"; const vueActuelle = $("#vue").val(); const codeLangue = $("#codeLangue").val() || "fr_FR"; $.ajax({ url: racine + "Ajaxgabarit/", type: 'GET', cache: false, success: function(data) { // 1. On transforme la chaîne 'data' en objet jQuery pour manipulation const $dataFrag = $(data); // 2. Injection dans le DOM $("#div_ajaxgabarit").html($dataFrag); // 3. RECUPERATION SECURISEE DU CODE SOCIETE // On essaie d'abord dans le DOM, puis dans le fragment reçu si le DOM est lent let codeSociete = $("#div_ajaxgabarit").find("#codeSociete").val() || $dataFrag.filter("#codeSociete").val() || $("#codeSociete").val(); // Debug en console pour vérifier la capture console.log("Check Session - codeSociete trouvé :", codeSociete); // 4. VERIFICATION DE LA SESSION if ((!codeSociete || codeSociete.trim() === "") && vueActuelle !== "Connexion") { const msg = "Votre session a expiré. Veuillez vous reconnecter."; const msgEng = "Your session has expired. Please log in again."; // On bloque l'écran avec confirm_ebene confirm_ebene(msg, msgEng).then(() => { window.location.assign(racine + "Connexion/deconnecter/"); }); return; } // Si on arrive ici, la session est valide }, error: function(xhr) { // Si le serveur renvoie une erreur HTTP (401, 403, 500) if (xhr.status === 401 && vueActuelle !== "Connexion") { window.location.assign(racine + "Connexion/deconnecter/"); } }, complete: function() { // Ré-initialisation des composants sur le nouveau HTML if ($.isFunction($.fn.datepicker)) { $(".datepicker").datepicker(); } /* if (typeof raffraichier_messagerie === "function") { raffraichier_messagerie(); } */ } }); } /** * GESTION DU MENU BURGER * Gère l'affichage mobile et la fermeture lors d'un clic extérieur. */ document.addEventListener('DOMContentLoaded', () => { const burgerToggle = document.getElementById('burgerMenuToggle'); const burgerDropdown = document.getElementById('burgerDropdown'); if (burgerToggle && burgerDropdown) { // Alterne la classe 'show' au clic sur le bouton burgerToggle.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); burgerDropdown.classList.toggle('show'); }); // Ferme le menu si on clique n'importe où ailleurs sur le document document.addEventListener('click', (e) => { if (!e.target.closest('.burger-menu-container')) { burgerDropdown.classList.remove('show'); } }); // Empêche la fermeture si on clique à l'intérieur du menu lui-même burgerDropdown.addEventListener('click', (e) => e.stopPropagation()); } }); /** * FORMATAGE DES MESSAGES (Responsive) * Ajoute des balises
pour forcer le retour à la ligne selon la taille d'écran. */ function formatMessageForSwal(message) { if (!message) return ''; const screenWidth = window.innerWidth; // Détermine la limite de caractères avant le saut de ligne const maxLineLength = screenWidth < 576 ? 40 : (screenWidth < 768 ? 60 : 80); if (message.length <= maxLineLength && !message.includes('\n')) return message; const words = message.split(' '); let lines = []; let currentLine = ''; words.forEach(word => { if ((currentLine + ' ' + word).length > maxLineLength && currentLine !== '') { lines.push(currentLine); currentLine = word; } else { currentLine = currentLine ? currentLine + ' ' + word : word; } }); if (currentLine) lines.push(currentLine); return lines.join('
'); } /** * AJUSTEMENT DYNAMIQUE SWEETALERT * Redimensionne la popup et gère le scroll interne pour les longs textes. */ function adjustSwalContent() { const popup = Swal.getPopup(); const title = Swal.getTitle(); const htmlContainer = Swal.getHtmlContainer(); if (popup && title) { const screenWidth = window.innerWidth; // Application de styles responsives directs if (screenWidth < 576) { Object.assign(popup.style, { maxWidth: '95vw', width: '95vw', margin: '10px' }); } else { Object.assign(popup.style, { maxWidth: screenWidth < 768 ? '85vw' : '500px', width: '100%' }); } // Gestion du scroll si le titre est trop grand const maxTitleHeight = Math.min(window.innerHeight * 0.6, 400); if (title.scrollHeight > maxTitleHeight) { Object.assign(title.style, { overflowY: 'auto', maxHeight: maxTitleHeight + 'px', paddingRight: '10px' }); } } } /** * WRAPPER GÉNÉRIQUE SWEETALERT * Centralise les paramètres communs pour alert_ebene, confirm_ebene, etc. */ function baseSwal(options) { return Swal.fire({ ...options, customClass: { popup: 'responsive-swal-popup', title: 'responsive-swal-title', htmlContainer: 'responsive-swal-html' }, didOpen: adjustSwalContent, willOpen: () => { document.body.style.overflow = 'hidden'; }, willClose: () => { document.body.style.overflow = 'auto'; } }); } /** * ALERTE SIMPLE * Affiche une information bilingue. */ function alert_ebene(p_msg, p_msg_eng) { const codeLangue = $("#codeLangue").val(); const message = (codeLangue === "en_US") ? p_msg_eng : p_msg; baseSwal({ title: formatMessageForSwal(message), icon: 'info', confirmButtonText: codeLangue === "en_US" ? 'OK' : 'D\'accord' }); } /** * CONFIRMATION * Affiche une boîte de dialogue Oui/Non et retourne une promesse. */ function confirm_ebene(p_msg, p_msg_eng) { const codeLangue = $("#codeLangue").val(); const message = (codeLangue === "en_US") ? p_msg_eng : p_msg; return baseSwal({ title: formatMessageForSwal(message), icon: 'warning', showCancelButton: true, confirmButtonText: codeLangue === "en_US" ? 'Yes' : 'Oui', cancelButtonText: codeLangue === "en_US" ? 'No' : 'Non' }).then(result => result.isConfirmed); } /** * SAISIE TEXTE (PROMPT) * Ouvre une modale avec champ de saisie et exécute un callback avec la valeur. */ function prompt_ebene(p_msg, p_msg_eng, p_retour, callback) { const codeLangue = $("#codeLangue").val(); const message = (codeLangue === "en_US") ? p_msg_eng : p_msg; baseSwal({ title: formatMessageForSwal(message), input: 'text', inputValue: p_retour, showCancelButton: true, confirmButtonText: 'OK', cancelButtonText: codeLangue === "en_US" ? 'Cancel' : 'Annuler' }).then(result => { callback(result.isConfirmed ? result.value : null); }); } /** * CHANGEMENT DE MOT DE PASSE * Demande confirmation avant redirection. */ function change_password() { const v_msg = "Attention, vous serez déconnecté par la suite! Voulez-vous changer votre mot de passe?"; const v_msgEng = "Attention, you will be logged out afterwards! Do you want to change your password?"; confirm_ebene(v_msg, v_msgEng).then(isConfirmed => { if (isConfirmed) { window.location.assign($("#racineWeb").val() + "Changermotpass/"); } }); } /** * AFFICHAGE BÉNÉFICIAIRE * Prépare le contexte serveur avant de charger la fiche bénéficiaire. */ function ajax_context_beneficiaire_afficher(idBeneficiaire, okId) { // Affiche un loader pendant le chargement $("#contenu").html('
'); $.ajax({ url: $("#racineWeb").val() + "Ajaxcontextbeneficiaire/", type: 'post', data: { idBeneficiaire, okId }, complete: () => { window.location.assign($("#racineWeb").val() + "Fichebeneficiaire/" + idBeneficiaire); } }); } /** * GESTION DE LA LANGUE À LA CONNEXION * Met à jour le bloc de connexion via AJAX lors du changement de langue. */ function changer_langue_connexion() { const codeLangue = $("#langue").val(); $.ajax({ url: $("#racineWeb").val() + "Ajaxconnexioncookie/changerlangue/", type: 'post', data: { codeLangue }, success: (data) => $("#div_detail_connexion").html(data), complete: () => $(".selectpicker").selectpicker('refresh') }); } /** * CONFIGURATION DATATABLES * Initialise un tableau DataTable avec options génériques. * * @param {string|jQuery} selector - Sélecteur du tableau (ex: '.tabliste' ou '#myTable') * @param {object} options - Options personnalisées (langue, boutons, ordre, etc.) */ function appliquerDataTable(selector = '.tabliste', options = {}) { const codeLangue = $("#codeLangue").val() || 'fr_FR'; const translations = { fr_FR: { lengthMenu: "Affiche _MENU_ par page", zeroRecords: "Aucune donnée trouvée", info: "_PAGE_ sur _PAGES_", search: "Recherche:", paginate: { next: "►", previous: "◄" } }, en_US: { lengthMenu: "Display _MENU_ records", zeroRecords: "Nothing found", info: "Showing page _PAGE_ of _PAGES_", search: "Search:", paginate: { next: "►", previous: "◄" } } }; $(selector).each(function() { const $table = $(this); // Colonnes marquées comme 'data-hidden' const hiddenTargets = []; $table.find('thead th').each((idx, th) => { if ($(th).data('hidden')) hiddenTargets.push(idx); }); const instance = $table.DataTable($.extend(true, { destroy: true, responsive: true, order: [[0, "desc"]], language: translations[codeLangue] || translations.fr_FR, columnDefs: [{ targets: hiddenTargets, visible: false }], dom: 'Bfrtip', buttons: ['copy', 'csv', 'excel', 'pdf', 'print'] }, options)); // Ajustement après rendu $table.on('init.dt', function () { if (instance && instance.responsive) { instance.columns.adjust(); instance.responsive.recalc(); } }); }); } /** * MESSAGERIE ET NOTIFICATIONS * Récupère le nombre de messages et déconnecte si session expirée. */ function raffraichier_messagerie() { if (!navigator.onLine) { $("#test_connexion").css('background-color', 'red'); return; } $.ajax({ url: $("#racineWeb").val() + "Ajaxmessagerie/", success: (data) => { $("#nbMessagesNonLus").html(data); $("#span_notification").text($("#msgNonLus").val()); // Sécurité : redirection forcée si le serveur indique une déconnexion nécessaire if ($("#deconnexion").val() === '1') { window.location.assign($("#racineWeb").val() + "Connexion/deconnecter/"); } } }); } // Réajuster les popups SweetAlert lors du redimensionnement de la fenêtre window.addEventListener('resize', () => { if (Swal.isVisible()) setTimeout(adjustSwalContent, 100); }); /** * Sélectionne une police d'assurance et met à jour les champs cachés globaux. * Cette fonction est généralement appelée lors d'un clic sur une ligne de tableau * ou un bouton de sélection dans une liste de polices. */ function selectionner_police(id, no) { debugger; // Mise à jour de l'ID de la police dans le champ caché prévu pour le traitement serveur $("#idPolice_C").val(id); // Mise à jour du numéro de police pour l'affichage ou les recherches secondaires $("#numeroPolice_C").val(no); // Note : On pourrait ajouter ici un retour visuel (ex: surbrillance de la ligne sélectionnée) console.log(`Police sélectionnée : ID ${id} / N° ${no}`); afficher_police_id(id); } /** * Vérifie la sélection d'une police et lance la mise à jour du contexte. * Utilisée généralement avant d'afficher le détail d'un contrat. */ function afficher_police_id(idPolice) { debugger; // Récupération de l'ID depuis le champ caché //const idPolice = $("#idPolice_C").val(); // Vérifie si l'ID est présent et non composé uniquement d'espaces if (idPolice > "0") { ajax_context_police_afficher(idPolice); } else { // Optionnel : Alerte si aucune police n'est sélectionnée console.warn("Aucun identifiant de police trouvé pour l'affichage."); } } /** * Définit le contexte de la police côté serveur via AJAX avant redirection. * @param {string|number} idPolice - L'identifiant de la police à mettre en session. */ function ajax_context_police_afficher(idPolice) { debugger; const racine = $("#racineWeb").val() || "/"; $.ajax({ url: racine + "Ajaxcontextpolice/", type: 'POST', // On envoie un objet pour que jQuery gère proprement l'encodage data: { idPolice: idPolice }, beforeSend: function() { // Optionnel : On pourrait afficher un petit loader ici }, success: function() { // Le contexte est mis à jour avec succès console.log("Contexte police mis à jour."); }, error: function(xhr, status, error) { // Alerte l'utilisateur en cas de problème technique const msg = "Erreur lors de la préparation du dossier police."; const msgEng = "Error while preparing the policy file."; if (typeof alert_ebene === "function") { alert_ebene(msg, msgEng); } else { alert(msg); } }, complete: function() { // Redirection vers la fiche de la police après le traitement AJAX window.location.assign(racine + "Fichepolice/"); } }); } /** * Charge la liste des quittances pour une police sur une période donnée. */ function afficher_quittances_police_periode() { debugger; // 1. Récupération des paramètres const racine = $("#racineWeb").val() || "/"; const idPolice = $("#idPolice_C").val(); const debut = $("#debut").val(); const fin = $("#fin").val(); const $conteneur = $("#div_quittancepolice"); // 2. Vérification de l'ID Police (Correction du bug numeroPolice) if (!idPolice || idPolice.trim() === "") { console.warn("Affichage quittances impossible : ID Police manquant."); return; } // 3. Préparation de l'interface (Loader) $conteneur.html(`
Chargement...

Chargement des quittances...

`); // 4. Appel AJAX $.ajax({ url: racine + "Ajaxfichepolice/", type: 'POST', data: { idPolice: idPolice, debut: debut, fin: fin }, success: function(data) { // Injection du résultat $conteneur.hide().html(data).fadeIn(); }, error: function(xhr, status, error) { $conteneur.html(`
${_("Erreur lors du chargement des quittances.")}
`); console.error("Erreur AJAX Quittances:", status, error); } }); } function afficher_emission(idEmission) { if (idEmission>"0") { window.location.assign($("#racineWeb" ).val()+"Emission/"+idEmission+"/"); } }