/** * CREDIT MANAGER - JavaScript Functions * Gestion du modal et des interactions */ jQuery(document).ready(function($) { 'use strict'; // Variables globales let currentCreditId = null; // Variables pour DataTables let creditsTable; // Variables pour les filtres let currentFilters = {}; // Initialiser Select2 function initSelect2() { if (typeof $.fn.select2 === 'function') { $('#credit-type').select2({ placeholder: 'Sélectionnez un type de crédit', allowClear: true, width: '100%' }); // Initialiser Select2 sur les filtres $('#filter-societe, #filter-status, #filter-type, #filter-credit-code').select2({ allowClear: true, width: '100%' }); } else { // Si Select2 n'est pas encore disponible, réessayer dans 100ms setTimeout(initSelect2, 100); } } // Initialiser Select2 au chargement du document $(document).ready(function() { initSelect2(); }); // Initialiser DataTables function initDataTable() { creditsTable = $('#credits-table').DataTable({ processing: true, serverSide: false, responsive: true, pageLength: 25, lengthMenu: [[10, 25, 50, 100, -1], [10, 25, 50, 100, "Tous"]], dom: 'Bfrtip', buttons: [ { extend: 'excelHtml5', text: ' Excel', className: 'btn-export-excel', title: 'Export Crédits - ' + new Date().toLocaleDateString('fr-FR'), exportOptions: { columns: ':not(:last-child)' // Exclure la colonne Actions } }, { extend: 'csvHtml5', text: ' CSV', className: 'btn-export-csv', title: 'Export Crédits', exportOptions: { columns: ':not(:last-child)' // Exclure la colonne Actions } } ], language: { "sProcessing": "Traitement en cours...", "sSearch": "Rechercher:", "sLengthMenu": "Afficher _MENU_ éléments", "sInfo": "Affichage de l'élément _START_ à _END_ sur _TOTAL_ éléments", "sInfoEmpty": "Affichage de l'élément 0 à 0 sur 0 élément", "sInfoFiltered": "(filtré de _MAX_ éléments au total)", "sLoadingRecords": "Chargement en cours...", "sZeroRecords": "Aucun élément à afficher", "sEmptyTable": "Aucune donnée disponible dans le tableau", "paginate": { "sFirst": "Premier", "sPrevious": "Précédent", "sNext": "Suivant", "sLast": "Dernier" }, "buttons": { "excel": "Excel", "csv": "CSV" } }, columns: [ { data: 'id', title: 'ID', defaultContent: '' }, { data: 'type_credit', title: 'Type', defaultContent: '' }, { data: 'nom', title: 'Nom', defaultContent: '' }, { data: 'prenom', title: 'Prénom', defaultContent: '' }, { data: 'adresse', title: 'Adresse', defaultContent: '' }, { data: 'localite', title: 'Localité', defaultContent: '' }, { data: 'email', title: 'Email', defaultContent: '' }, { data: null, title: 'Téléphone/GSM', render: function(data, type, row) { let phones = []; if (row.telephone) phones.push(row.telephone); if (row.gsm) phones.push(row.gsm); return phones.join('
'); } }, { data: 'societe_credit', title: 'Société', defaultContent: '' }, { data: 'montant', title: 'Montant', render: function(data, type, row) { return formatCurrency(row.montant); } }, { data: 'date', title: 'Date', render: function(data, type, row) { return formatDate(row.date); } }, { data: 'date_signature', title: 'Date Signature', defaultContent: '' }, { data: 'numero_dossier', title: 'N° Dossier', defaultContent: '' }, { data: 'code', title: 'Code', defaultContent: '' }, { data: null, title: 'Statut', orderable: false, searchable: false, render: function(data, type, row) { const map = { '-1': { label: 'Refusé', cls: 'status-refused' }, '0': { label: 'À valider', cls: 'status-pending' }, '1': { label: 'Validé non signé', cls: 'status-accepted-unsigned' }, '2': { label: 'Validé classé', cls: 'status-accepted-filed' } }; const key = String(row.status ?? '0'); const conf = map[key] || map['0']; return '' + conf.label + ''; } }, { data: null, title: 'Actions', orderable: false, searchable: false, render: function(data, type, row) { // Récupérer le statut actuel const currentStatus = parseInt(row.status ?? '0'); return `
`; } } ] }); } // Charger les données des crédits function loadCredits(options = {}) { const silent = !!options.silent; // Vérifier que creditManagerAjax est défini if (typeof creditManagerAjax === 'undefined') { console.error('ERROR: creditManagerAjax is not defined!'); showNotification('Erreur de configuration JavaScript', 'error'); return; } // Vérifier que le nonce est défini if (!creditManagerAjax.nonce) { console.error('ERROR: Nonce is not defined in creditManagerAjax!'); console.log('creditManagerAjax object:', creditManagerAjax); showNotification('Erreur: Nonce manquant', 'error'); return; } // Afficher une notification de chargement (si non silencieux) if (!silent) { showNotification('Chargement des crédits...', 'saving'); } // Préparer les données avec les filtres let ajaxData = { action: 'credit_manager_list', nonce: creditManagerAjax.nonce }; // Ajouter les filtres s'ils existent Object.assign(ajaxData, currentFilters); // Debug: Afficher les données envoyées console.log('=== AJAX Request ==='); console.log('URL:', creditManagerAjax.ajaxurl); console.log('Nonce:', creditManagerAjax.nonce); console.log('Filters:', currentFilters); console.log('Ajax Data:', ajaxData); $.ajax({ url: creditManagerAjax.ajaxurl, type: 'POST', data: ajaxData, success: function(response) { console.log('=== AJAX Response ==='); console.log('Response:', response); if (response.success) { console.log('Success! Credits count:', response.data.credits ? response.data.credits.length : 0); console.log('Status counts:', response.data.status_counts); // Détruire la table existante si elle existe if (creditsTable) { creditsTable.destroy(); } // Réinitialiser le tableau HTML $('#credits-table tbody').empty(); // Réinitialiser DataTables initDataTable(); // Ajouter les données if (response.data.credits && response.data.credits.length > 0) { // Assainir les lignes pour correspondre aux colonnes attendues const requiredFields = ['id','type_credit','nom','prenom','adresse','localite','email','telephone','gsm','societe_credit','montant','date','date_signature','numero_dossier','code']; const sanitized = response.data.credits.map(function(row, idx){ if (typeof row !== 'object' || row === null) { console.warn('Row is not an object at index', idx); row = {}; } requiredFields.forEach(function(k){ if (typeof row[k] === 'undefined') { row[k] = (k === 'montant') ? 0 : ''; } }); return row; }); creditsTable.clear(); creditsTable.rows.add(sanitized); creditsTable.draw(); if (!silent) { showNotification(response.data.credits.length + ' crédit(s) chargé(s)', 'success'); } } else { if (!silent) { showNotification('Aucun crédit trouvé', 'info'); } } // Mettre à jour les compteurs avec les données du serveur if (response.data.status_counts) { updateStatusCountsFromData(response.data.status_counts, response.data.total_all); } } else { console.error('AJAX Error:', response.data); showNotification('Erreur: ' + response.data, 'error'); } }, error: function(xhr, status, error) { console.error('=== AJAX Connection Error ==='); console.error('Status:', status); console.error('Error:', error); console.error('Response:', xhr.responseText); showNotification('Erreur de connexion: ' + error, 'error'); } }); } // Formater la devise function formatCurrency(amount) { return new Intl.NumberFormat('fr-FR', { style: 'currency', currency: 'EUR' }).format(amount || 0); } // Formater la date function formatDate(dateString) { if (!dateString) return ''; return new Date(dateString).toLocaleDateString('fr-FR'); } /** * Affiche une notification moderne (style toast) * @param {string} message - Le message à afficher * @param {string} type - Le type de notification: 'success', 'saving', 'error', 'info' */ function showNotification(message, type = 'success') { let indicator = $('.auto-save-indicator'); // Créer l'indicateur s'il n'existe pas if (indicator.length === 0) { indicator = $('
'); $('body').append(indicator); } // Mapper le type 'info' vers 'saving' pour une meilleure visibilité if (type === 'info') { type = 'saving'; } // Retirer toutes les classes de type et ajouter la nouvelle indicator.removeClass('show saving error').addClass('show ' + type); indicator.text(message); // Masquer après 3 secondes (5 secondes pour les erreurs) const duration = type === 'error' ? 5000 : 3000; setTimeout(() => { indicator.removeClass('show'); }, duration); } // Alias pour compatibilité avec l'ancien code function showMessage(message, type) { showNotification(message, type); } // Ouvrir le modal window.openCreditModal = function(creditId = null) { currentCreditId = creditId; if (creditId) { loadCreditData(creditId); } else { $('#credit-form')[0].reset(); $('.credit-modal-header h2').text('Nouveau crédit'); // Réinitialiser Select2 $('#credit-type').val([]).trigger('change'); } $('.credit-modal').addClass('show').show(); // Réinitialiser Select2 après ouverture de la modal setTimeout(function() { if (typeof $.fn.select2 === 'function') { // Détruire l'instance existante si elle existe if ($('#credit-type').hasClass('select2-hidden-accessible')) { $('#credit-type').select2('destroy'); } initSelect2(); } }, 100); }; // Fermer le modal window.closeCreditModal = function() { $('.credit-modal').addClass('closing'); setTimeout(function() { $('.credit-modal').removeClass('show closing').hide(); currentCreditId = null; }, 300); }; // Charger les données d'un crédit function loadCreditData(creditId) { $.ajax({ url: creditManagerAjax.ajaxurl, type: 'POST', data: { action: 'credit_manager_get', nonce: creditManagerAjax.nonce, credit_id: creditId }, success: function(response) { if (response.success) { const credit = response.data.credit; $('.credit-modal-header h2').text('Modifier le crédit'); // Remplir le formulaire if (credit.type_credit) { const typeCreditArray = typeof credit.type_credit === 'string' ? credit.type_credit.split(',') : credit.type_credit; $('#credit-type').val(typeCreditArray); } else { $('#credit-type').val([]); } $('#credit-nom').val(credit.nom || ''); $('#credit-prenom').val(credit.prenom || ''); $('#credit-adresse').val(credit.adresse || ''); $('#credit-localite').val(credit.localite || ''); $('#credit-email').val(credit.email || ''); $('#credit-telephone').val(credit.telephone || ''); $('#credit-gsm').val(credit.gsm || ''); $('#credit-type-habitation').val(credit.type_habitation || ''); $('#credit-societe').val(credit.societe_credit || ''); $('#credit-montant').val(credit.montant || ''); $('#credit-date').val(credit.date || ''); $('#credit-signature').val(credit.date_signature || ''); $('#credit-numero-dossier').val(credit.numero_dossier || ''); $('#credit-code').val(credit.code || ''); $('#credit-remarques').val(credit.remarques || ''); showNotification('Crédit chargé avec succès', 'success'); } else { showNotification('✕ Erreur lors du chargement: ' + response.data, 'error'); } }, error: function(xhr, status, error) { showNotification('✕ Erreur de connexion lors du chargement: ' + error, 'error'); } }); } // Sauvegarder le crédit window.saveCredit = function() { // Afficher la notification de sauvegarde showNotification('Sauvegarde en cours...', 'saving'); const formData = { action: currentCreditId ? 'credit_manager_update' : 'credit_manager_create', nonce: creditManagerAjax.nonce, type_credit: $('#credit-type').val(), nom: $('#credit-nom').val(), prenom: $('#credit-prenom').val(), adresse: $('#credit-adresse').val(), localite: $('#credit-localite').val(), email: $('#credit-email').val(), telephone: $('#credit-telephone').val(), gsm: $('#credit-gsm').val(), type_habitation: $('#credit-type-habitation').val(), societe_credit: $('#credit-societe').val(), montant: $('#credit-montant').val(), date: $('#credit-date').val(), signature: $('#credit-signature').val(), numero_dossier: $('#credit-numero-dossier').val(), code: $('#credit-code').val(), remarques: $('#credit-remarques').val() }; if (currentCreditId) { formData.credit_id = currentCreditId; } $.ajax({ url: creditManagerAjax.ajaxurl, type: 'POST', data: formData, success: function(response) { if (response.success) { showNotification('✓ ' + response.data.message, 'success'); closeCreditModal(); loadCredits({ silent: true }); } else { showNotification('✕ Erreur: ' + response.data, 'error'); } }, error: function(xhr, status, error) { showNotification('✕ Erreur de connexion: ' + error, 'error'); } }); }; // Supprimer un crédit window.deleteCredit = function(creditId) { // Confirmation plus détaillée const confirmMessage = '⚠️ ATTENTION ⚠️\n\n' + 'Vous êtes sur le point de supprimer définitivement ce crédit.\n\n' + 'Cette action est IRRÉVERSIBLE et supprimera toutes les données associées.\n\n' + 'Êtes-vous absolument certain de vouloir continuer ?'; if (!confirm(confirmMessage)) { return; } // Double confirmation pour plus de sécurité if (!confirm('Dernière chance !\n\nConfirmez-vous la suppression définitive de ce crédit ?')) { return; } // Afficher un message de chargement showNotification('Suppression en cours...', 'saving'); $.ajax({ url: creditManagerAjax.ajaxurl, type: 'POST', data: { action: 'credit_manager_delete', nonce: creditManagerAjax.nonce, credit_id: creditId }, success: function(response) { if (response.success) { showNotification('✓ ' + response.data.message, 'success'); loadCredits({ silent: true }); } else { showNotification('✕ Erreur: ' + response.data, 'error'); } }, error: function(xhr, status, error) { showNotification('✕ Erreur de connexion lors de la suppression: ' + error, 'error'); } }); }; // Modifier un crédit window.editCredit = function(creditId) { openCreditModal(creditId); }; // Mettre à jour le statut d'un crédit window.updateCreditStatus = function(creditId, status) { let statusLabel = ''; let confirmMessage = ''; switch(status) { case 'accepte_non_signe': statusLabel = 'Accepté non signé'; confirmMessage = 'Êtes-vous sûr de vouloir marquer ce crédit comme "Accepté non signé" ?'; break; case 'accepte_classe': statusLabel = 'Accepté classé'; confirmMessage = 'Êtes-vous sûr de vouloir marquer ce crédit comme "Accepté classé" ?'; break; case 'refuse': statusLabel = 'Refusé'; confirmMessage = 'Êtes-vous sûr de vouloir marquer ce crédit comme "Refusé" ?'; break; } if (!confirm(confirmMessage)) { return; } showNotification('Mise à jour du statut en cours...', 'saving'); $.ajax({ url: creditManagerAjax.ajaxurl, type: 'POST', data: { action: 'credit_manager_update_status', nonce: creditManagerAjax.nonce, credit_id: creditId, status: status }, success: function(response) { if (response.success) { showNotification('✓ Statut mis à jour : ' + statusLabel, 'success'); loadCredits({ silent: true }); } else { showNotification('✕ Erreur: ' + response.data, 'error'); } }, error: function(xhr, status, error) { showNotification('✕ Erreur de connexion lors de la mise à jour: ' + error, 'error'); } }); }; // Fermer le modal en cliquant à l'extérieur $(document).on('click', '.credit-modal', function(e) { if (e.target === this) { closeCreditModal(); } }); // Toggle des filtres $('#toggle-filters').on('click', function() { $('#credit-filters-form').slideToggle(300); $(this).find('.dashicons').toggleClass('dashicons-arrow-down-alt2 dashicons-arrow-up-alt2'); }); // Soumission du formulaire de filtres $('#credit-filters-form').on('submit', function(e) { e.preventDefault(); // Récupérer les valeurs du formulaire currentFilters = { societe_credit: $('#filter-societe').val(), code_postal: $('#filter-code-postal').val(), status: $('#filter-status').val(), type_credit: $('#filter-type').val(), credit_code_select: $('#filter-credit-code').val(), montant_min: $('#filter-montant-min').val(), montant_max: $('#filter-montant-max').val(), date_signature_debut: $('#filter-date-debut').val(), date_signature_fin: $('#filter-date-fin').val() }; // Compter le nombre de filtres actifs let activeFiltersCount = 0; Object.keys(currentFilters).forEach(key => { if (currentFilters[key] !== '' && currentFilters[key] !== null) { activeFiltersCount++; } }); if (activeFiltersCount > 0) { showNotification('Application de ' + activeFiltersCount + ' filtre(s)...', 'saving'); } // Recharger les données avec les filtres loadCredits(); }); // Réinitialiser les filtres $('#reset-filters').on('click', function() { $('#credit-filters-form')[0].reset(); currentFilters = {}; showNotification('Filtres réinitialisés', 'success'); loadCredits(); }); // Fonction pour mettre à jour les compteurs depuis les données du serveur function updateStatusCountsFromData(statusCounts, totalAll) { // Mettre à jour les affichages avec les compteurs reçus du serveur $('[data-count-status="0"]').text('(' + (statusCounts['0'] || 0) + ')'); $('[data-count-status="1"]').text('(' + (statusCounts['1'] || 0) + ')'); $('[data-count-status="2"]').text('(' + (statusCounts['2'] || 0) + ')'); $('[data-count-status="-1"]').text('(' + (statusCounts['-1'] || 0) + ')'); $('#total-count').text('(' + (totalAll || 0) + ')'); console.log('Status counts updated from server:', statusCounts, 'Total:', totalAll); } // Gestionnaire pour les boutons de filtre rapide par statut $('.status-filter-btn').on('click', function() { const status = $(this).data('status'); // Retirer la classe active de tous les boutons $('.status-filter-btn').removeClass('active'); // Ajouter la classe active au bouton cliqué $(this).addClass('active'); // Réinitialiser les autres filtres du formulaire $('#credit-filters-form')[0].reset(); // Appliquer le filtre de statut if (status === '') { // Bouton "Tous" - réinitialiser les filtres currentFilters = {}; showNotification('Affichage de tous les crédits', 'success'); } else { // Filtre par statut spécifique currentFilters = { status: status }; const statusLabels = { '0': 'À valider', '1': 'Validé non signé', '2': 'Validé classé', '-1': 'Refusé' }; showNotification('Filtre : ' + statusLabels[status], 'saving'); } // Recharger les crédits loadCredits(); }); // Mailchimp - tester la connexion (page admin Mailchimp) $('#cred-mailchimp-test').on('click', function(e) { e.preventDefault(); var $out = $('#cred-mailchimp-test-result'); if ($out.length) { $out.text('Test en cours…'); } else { showNotification('Test de connexion en cours…', 'saving'); } $.post(creditManagerAjax.ajaxurl, { action: 'cred_mailchimp_ping', nonce: creditManagerAjax.mailchimpPingNonce || '' }).done(function(resp){ if ($out.length) { $out.text(resp && resp.success ? 'Connexion OK' : ('Échec: ' + ((resp && resp.data && resp.data.message) ? resp.data.message : 'Error'))); } else { if (resp && resp.success) { showNotification('Connexion Mailchimp OK', 'success'); } else { showNotification('Échec: ' + ((resp && resp.data && resp.data.message) ? resp.data.message : 'Error'), 'error'); } } }).fail(function(xhr){ var msg = (xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) ? xhr.responseJSON.data.message : xhr.statusText; if ($out.length) { $out.text('Échec: ' + msg); } else { showNotification('Échec: ' + msg, 'error'); } }); }); // Sendy - tester la connexion (page admin Sendy) $('#cred-sendy-test').on('click', function(e) { e.preventDefault(); var $out = $('#cred-sendy-test-result'); if ($out.length) { $out.text('Test en cours…'); } else { showNotification('Test de connexion en cours…', 'saving'); } $.post(creditManagerAjax.ajaxurl, { action: 'cred_sendy_ping', nonce: creditManagerAjax.sendyPingNonce || '' }).done(function(resp){ if ($out.length) { $out.text(resp && resp.success ? 'Connexion OK' : ('Échec: ' + ((resp && resp.data && resp.data.message) ? resp.data.message : 'Error'))); } else { if (resp && resp.success) { showNotification('Connexion Sendy OK', 'success'); } else { showNotification('Échec: ' + ((resp && resp.data && resp.data.message) ? resp.data.message : 'Error'), 'error'); } } }).fail(function(xhr){ var msg = (xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) ? xhr.responseJSON.data.message : xhr.statusText; if ($out.length) { $out.text('Échec: ' + msg); } else { showNotification('Échec: ' + msg, 'error'); } }); }); // Initialiser uniquement sur la page Crédit (évite le chargement sur Mailchimp/Sendy) if (jQuery('#credits-table').length > 0) { loadCredits(); } });