Files
PayConnect-by-SallTech/assets/bankily-admin.js
2025-08-23 21:15:12 +00:00

721 lines
24 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Script JavaScript pour l'interface d'administration B-PAY Bankily
* Fichier: assets/bankily-admin.js
* Version: 1.0.0
*/
jQuery(document).ready(function($) {
'use strict';
// Variables globales
var checking = false;
var autoRefreshInterval;
// Initialisation
initializeAdminInterface();
function initializeAdminInterface() {
// Gestion des checkboxes
$('#cb-select-all').on('change', function() {
$('input[name="transaction_ids[]"]').prop('checked', this.checked);
updateBulkActionsState();
});
// Mise à jour de l'état des actions groupées
$(document).on('change', 'input[name="transaction_ids[]"]', function() {
updateBulkActionsState();
});
// Auto-refresh pour les transactions en attente
if (window.location.href.indexOf('bankily-pending') > -1) {
startAutoRefresh();
}
// Initialiser les tooltips
initializeTooltips();
// Gestion du temps réel
updateTimeStamps();
setInterval(updateTimeStamps, 60000); // Mettre à jour chaque minute
// Recherche en temps réel
setupLiveSearch();
// Raccourcis clavier
setupKeyboardShortcuts();
// Indicateur de connexion
checkConnectionStatus();
setInterval(checkConnectionStatus, 30000);
}
function updateBulkActionsState() {
var selectedCount = $('input[name="transaction_ids[]"]:checked').length;
var $bulkButton = $('.button.action');
if (selectedCount > 0) {
$bulkButton.prop('disabled', false).text('Appliquer (' + selectedCount + ')');
} else {
$bulkButton.prop('disabled', true).text('Appliquer');
}
}
function initializeTooltips() {
$('.error-message, [data-tooltip]').each(function() {
var $this = $(this);
var title = $this.attr('title') || $this.data('tooltip');
if (title) {
$this.on('mouseenter', function(e) {
showTooltip(e.pageX, e.pageY, title);
});
$this.on('mouseleave', function() {
hideTooltip();
});
$this.on('mousemove', function(e) {
updateTooltipPosition(e.pageX, e.pageY);
});
}
});
}
function showTooltip(x, y, text) {
var $tooltip = $('#bankily-tooltip');
if ($tooltip.length === 0) {
$tooltip = $('<div id="bankily-tooltip"></div>').appendTo('body');
}
$tooltip.text(text)
.css({
position: 'absolute',
left: x + 10,
top: y - 30,
background: '#333',
color: '#fff',
padding: '5px 10px',
borderRadius: '4px',
fontSize: '12px',
zIndex: 9999,
maxWidth: '300px',
wordWrap: 'break-word'
})
.fadeIn(200);
}
function hideTooltip() {
$('#bankily-tooltip').fadeOut(200);
}
function updateTooltipPosition(x, y) {
$('#bankily-tooltip').css({
left: x + 10,
top: y - 30
});
}
function updateTimeStamps() {
$('.transaction-row').each(function() {
var $row = $(this);
var createdAt = $row.find('[data-timestamp]').data('timestamp');
if (createdAt) {
var timeAgo = formatTimeAgo(new Date(createdAt * 1000));
$row.find('.time-ago').text(timeAgo);
}
});
}
function formatTimeAgo(date) {
var now = new Date();
var diffMs = now - date;
var diffMins = Math.floor(diffMs / 60000);
var diffHours = Math.floor(diffMins / 60);
var diffDays = Math.floor(diffHours / 24);
if (diffDays > 0) {
return diffDays + ' jour' + (diffDays > 1 ? 's' : '');
} else if (diffHours > 0) {
return diffHours + ' heure' + (diffHours > 1 ? 's' : '');
} else if (diffMins > 0) {
return diffMins + ' minute' + (diffMins > 1 ? 's' : '');
} else {
return 'À l\'instant';
}
}
function startAutoRefresh() {
// Rafraîchir automatiquement toutes les 30 secondes si il y a des transactions en attente
if ($('.bankily-status-ta').length > 0) {
autoRefreshInterval = setTimeout(function() {
if (!checking) {
showNotice('info', 'Actualisation automatique...', 2000);
setTimeout(function() {
window.location.reload();
}, 1000);
}
}, 30000);
}
}
function setupLiveSearch() {
var searchTimeout;
var $searchInput = $('input[name="search"]');
if ($searchInput.length) {
$searchInput.on('input', function() {
clearTimeout(searchTimeout);
var query = $(this).val().toLowerCase();
searchTimeout = setTimeout(function() {
filterTransactions(query);
}, 300);
});
}
}
function filterTransactions(query) {
if (!query) {
$('.transaction-row').show();
updateDisplayedCount();
return;
}
$('.transaction-row').each(function() {
var $row = $(this);
var text = $row.text().toLowerCase();
if (text.indexOf(query) !== -1) {
$row.show();
} else {
$row.hide();
}
});
updateDisplayedCount();
}
function updateDisplayedCount() {
var visibleCount = $('.transaction-row:visible').length;
$('.displaying-num').text(visibleCount + ' élément' + (visibleCount > 1 ? 's' : ''));
}
function setupKeyboardShortcuts() {
$(document).on('keydown', function(e) {
// Ctrl+R pour rafraîchir
if (e.ctrlKey && e.keyCode === 82) {
e.preventDefault();
window.location.reload();
}
// Ctrl+A pour sélectionner tout
if (e.ctrlKey && e.keyCode === 65 && $('.transaction-row').length > 0) {
e.preventDefault();
$('#cb-select-all').prop('checked', true).trigger('change');
}
// Échap pour désélectionner
if (e.keyCode === 27) {
$('#cb-select-all').prop('checked', false).trigger('change');
hideProgressBar();
}
});
}
function checkConnectionStatus() {
$.ajax({
url: bankily_admin_ajax.ajax_url,
type: 'POST',
data: {
action: 'bankily_ping',
nonce: bankily_admin_ajax.nonce
},
timeout: 5000,
success: function() {
updateConnectionStatus(true);
},
error: function() {
updateConnectionStatus(false);
}
});
}
function updateConnectionStatus(isOnline) {
var $indicator = $('#bankily-connection-status');
if ($indicator.length === 0) {
$indicator = $('<div id="bankily-connection-status"></div>').appendTo('body');
}
$indicator.removeClass('online offline')
.addClass(isOnline ? 'online' : 'offline')
.text(isOnline ? '🟢 En ligne' : '🔴 Hors ligne');
}
// Fonctions globales pour les boutons (exposées au scope global)
window.bankilyCheckTransaction = function(operationId, transactionId) {
if (checking) {
return;
}
checking = true;
var $button = $('button[onclick*="' + transactionId + '"]').first();
var originalText = $button.text();
var $row = $('#transaction-' + transactionId);
$button.prop('disabled', true).addClass('bankily-loading').text(bankily_admin_ajax.strings.checking);
$row.addClass('bankily-checking');
$.ajax({
url: bankily_admin_ajax.ajax_url,
type: 'POST',
data: {
action: 'bankily_check_transaction',
operation_id: operationId,
transaction_id: transactionId,
nonce: bankily_admin_ajax.nonce
},
success: function(response) {
if (response.success) {
updateTransactionRow(transactionId, response.data);
showNotice('success', response.data.message);
// Animation de succès
$row.addClass('bankily-success');
setTimeout(function() {
$row.removeClass('bankily-success');
}, 2000);
} else {
showNotice('error', response.data);
$row.addClass('bankily-error');
setTimeout(function() {
$row.removeClass('bankily-error');
}, 2000);
}
},
error: function(xhr, status, error) {
showNotice('error', 'Erreur de connexion: ' + error);
$row.addClass('bankily-error');
setTimeout(function() {
$row.removeClass('bankily-error');
}, 2000);
},
complete: function() {
$button.prop('disabled', false)
.removeClass('bankily-loading')
.text(originalText);
$row.removeClass('bankily-checking');
checking = false;
}
});
};
window.bankilyCheckAllPending = function() {
if (checking) {
return;
}
var $pendingRows = $('.bankily-status-ta').closest('tr');
if ($pendingRows.length === 0) {
showNotice('info', 'Aucune transaction en attente à vérifier.');
return;
}
if (!confirm('Vérifier toutes les ' + $pendingRows.length + ' transactions en attente ?\n\nCela peut prendre plusieurs minutes.')) {
return;
}
checking = true;
var transactionIds = [];
$pendingRows.each(function() {
var $checkbox = $(this).find('input[name="transaction_ids[]"]');
if ($checkbox.length > 0) {
transactionIds.push($checkbox.val());
}
});
if (transactionIds.length === 0) {
checking = false;
showNotice('warning', 'Impossible de récupérer les IDs des transactions.');
return;
}
var $progressBar = showProgressBar(transactionIds.length);
// Traitement par lots pour éviter de surcharger le serveur
processBatch(transactionIds, 0, $progressBar, 5); // Taille de lot : 5
};
function processBatch(transactionIds, startIndex, $progressBar, batchSize) {
var batch = transactionIds.slice(startIndex, startIndex + batchSize);
if (batch.length === 0) {
hideProgressBar();
checking = false;
showNotice('success', 'Vérification terminée pour toutes les transactions.');
// Rafraîchir la page après un délai
setTimeout(function() {
window.location.reload();
}, 2000);
return;
}
updateProgressBar($progressBar, startIndex, transactionIds.length);
$.ajax({
url: bankily_admin_ajax.ajax_url,
type: 'POST',
data: {
action: 'bankily_bulk_check',
transaction_ids: batch,
nonce: bankily_admin_ajax.nonce
},
success: function(response) {
if (response.success) {
response.data.forEach(function(result) {
if (result.status === 'success') {
updateTransactionRow(result.id, {
status: result.new_status,
status_label: getStatusLabel(result.new_status)
});
}
});
}
// Délai entre les lots
setTimeout(function() {
processBatch(transactionIds, startIndex + batchSize, $progressBar, batchSize);
}, 2000); // 2 secondes entre les lots
},
error: function() {
hideProgressBar();
checking = false;
showNotice('error', 'Erreur lors de la vérification groupée.');
}
});
}
function updateTransactionRow(transactionId, data) {
var $row = $('#transaction-' + transactionId);
if (data.status) {
var $statusCell = $row.find('.bankily-status');
$statusCell.removeClass('bankily-status-ts bankily-status-tf bankily-status-ta')
.addClass('bankily-status-' + data.status.toLowerCase())
.text(data.status_label || getStatusLabel(data.status));
}
if (data.transaction_id) {
var $operationCell = $row.find('.operation-id');
if (!$operationCell.find('small').length) {
$operationCell.append('<br><small>TXN: ' + data.transaction_id + '</small>');
}
}
// Mettre à jour le compteur de tentatives
var $attemptsCell = $row.find('td').eq(-2);
var currentAttempts = parseInt($attemptsCell.text()) || 0;
$attemptsCell.text(currentAttempts + 1);
// Mettre à jour l'heure de dernière vérification
var now = new Date();
var $lastCheckedCell = $row.find('td').eq(-3);
$lastCheckedCell.text(formatDateTime(now));
// Animation de mise à jour
$row.addClass('updated');
setTimeout(function() {
$row.removeClass('updated');
}, 2000);
}
function getStatusLabel(status) {
var labels = {
'TS': bankily_admin_ajax.strings.success,
'TF': bankily_admin_ajax.strings.failed,
'TA': bankily_admin_ajax.strings.pending
};
return labels[status] || status;
}
function formatDateTime(date) {
return date.toLocaleDateString('fr-FR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
function showProgressBar(total) {
var progressHtml = `
<div id="bankily-progress-overlay">
<div class="bankily-progress-container">
<h3>🔄 Vérification des transactions en cours...</h3>
<div class="bankily-progress-bar">
<div class="bankily-progress-fill" style="width: 0%"></div>
</div>
<div class="bankily-progress-text">0 / ${total}</div>
<p><small>⏱ Cette opération peut prendre plusieurs minutes. Veuillez patienter...</small></p>
<button type="button" class="button button-secondary" onclick="bankilyStopProcessing()">
Annuler
</button>
</div>
</div>
`;
$('body').append(progressHtml);
return $('#bankily-progress-overlay');
}
function updateProgressBar($progressBar, current, total) {
var percentage = (current / total) * 100;
$progressBar.find('.bankily-progress-fill').css('width', percentage + '%');
$progressBar.find('.bankily-progress-text').text(current + ' / ' + total + ' (' + Math.round(percentage) + '%)');
}
function hideProgressBar() {
$('#bankily-progress-overlay').fadeOut(function() {
$(this).remove();
});
}
window.bankilyStopProcessing = function() {
if (confirm('Êtes-vous sûr de vouloir arrêter le processus ?')) {
checking = false;
hideProgressBar();
showNotice('warning', 'Processus arrêté par l\'utilisateur.');
}
};
window.bankilyBulkAction = function() {
var action = $('#bulk-action-selector-top').val();
var selectedIds = [];
$('input[name="transaction_ids[]"]:checked').each(function() {
selectedIds.push($(this).val());
});
if (selectedIds.length === 0) {
showNotice('warning', 'Veuillez sélectionner au moins une transaction.');
return;
}
if (!confirm(bankily_admin_ajax.strings.confirm_bulk + '\n\n' + selectedIds.length + ' transactions sélectionnées.')) {
return;
}
switch (action) {
case 'check':
bankilyBulkCheck(selectedIds);
break;
case 'mark-failed':
bankilyBulkMarkFailed(selectedIds);
break;
default:
showNotice('warning', 'Veuillez sélectionner une action.');
}
};
function bankilyBulkCheck(transactionIds) {
if (checking) {
return;
}
checking = true;
var $progressBar = showProgressBar(transactionIds.length);
processBatch(transactionIds, 0, $progressBar, 3); // Taille de lot réduite pour les actions manuelles
}
function bankilyBulkMarkFailed(transactionIds) {
if (checking) {
return;
}
checking = true;
$.ajax({
url: bankily_admin_ajax.ajax_url,
type: 'POST',
data: {
action: 'bankily_bulk_mark_failed',
transaction_ids: transactionIds,
nonce: bankily_admin_ajax.nonce
},
success: function(response) {
if (response.success) {
transactionIds.forEach(function(id) {
updateTransactionRow(id, {
status: 'TF',
status_label: getStatusLabel('TF')
});
});
showNotice('success', response.data.message);
} else {
showNotice('error', 'Erreur lors du marquage des transactions.');
}
},
error: function() {
showNotice('error', bankily_admin_ajax.strings.error);
},
complete: function() {
checking = false;
}
});
}
window.bankilyMarkAsFailed = function(transactionId) {
if (!confirm('Êtes-vous sûr de vouloir marquer cette transaction comme échouée ?\n\nCette action est irréversible.')) {
return;
}
bankilyBulkMarkFailed([transactionId]);
};
window.bankilyExportTransactions = function() {
showNotice('info', 'Préparation de l\'export...');
var url = bankily_admin_ajax.ajax_url + '?action=bankily_export_transactions&nonce=' + bankily_admin_ajax.nonce;
// Créer un lien de téléchargement invisible
var $link = $('<a>').attr({
href: url,
download: 'bankily-transactions-' + new Date().toISOString().split('T')[0] + '.csv'
}).appendTo('body');
$link[0].click();
$link.remove();
showNotice('success', 'Export lancé. Le téléchargement va commencer.', 3000);
};
window.bankilyCleanOldTransactions = function() {
if (!confirm('Êtes-vous sûr de vouloir supprimer les transactions de plus de 6 mois ?\n\n⚠ Cette action est irréversible !')) {
return;
}
$.ajax({
url: bankily_admin_ajax.ajax_url,
type: 'POST',
data: {
action: 'bankily_clean_old_transactions',
nonce: bankily_admin_ajax.nonce
},
success: function(response) {
if (response.success) {
showNotice('success', response.data.message);
} else {
showNotice('error', 'Erreur lors du nettoyage.');
}
},
error: function() {
showNotice('error', bankily_admin_ajax.strings.error);
}
});
};
function showNotice(type, message, autoHide = 5000) {
// Supprimer les anciennes notices
$('.bankily-notice').remove();
var noticeClass = 'notice-' + type;
var icon = {
'success': '✅',
'error': '❌',
'warning': '⚠️',
'info': ''
}[type] || '';
var noticeHtml = `
<div class="notice ${noticeClass} is-dismissible bankily-notice" style="position: relative; z-index: 999999;">
<p><strong>${icon} ${message}</strong></p>
<button type="button" class="notice-dismiss">
<span class="screen-reader-text">Ignorer cette notice.</span>
</button>
</div>
`;
// Ajouter la nouvelle notice
$('.wrap h1').first().after(noticeHtml);
// Gestion du bouton de fermeture
$('.notice-dismiss').on('click', function() {
$(this).closest('.notice').fadeOut();
});
// Auto-fermeture
if (autoHide && autoHide > 0) {
setTimeout(function() {
$('.bankily-notice').fadeOut();
}, autoHide);
}
// Faire défiler vers la notice
$('html, body').animate({
scrollTop: $('.bankily-notice').offset().top - 100
}, 300);
}
// Amélioration UX : Confirmation avant fermeture de page si traitement en cours
window.addEventListener('beforeunload', function(e) {
if (checking) {
e.preventDefault();
e.returnValue = 'Une vérification est en cours. Êtes-vous sûr de vouloir quitter ?';
return e.returnValue;
}
});
// Nettoyage lors du déchargement de la page
$(window).on('unload', function() {
if (autoRefreshInterval) {
clearTimeout(autoRefreshInterval);
}
checking = false;
});
// Stats en temps réel (si sur le tableau de bord)
if (window.location.href.indexOf('bankily-transactions') > -1 && window.location.href.indexOf('pending') === -1) {
setInterval(function() {
if (!checking) {
updateDashboardStats();
}
}, 60000); // Mettre à jour toutes les minutes
}
function updateDashboardStats() {
$.ajax({
url: bankily_admin_ajax.ajax_url,
type: 'POST',
data: {
action: 'bankily_get_dashboard_stats',
nonce: bankily_admin_ajax.nonce
},
success: function(response) {
if (response.success) {
updateStatCards(response.data);
}
},
error: function() {
console.log('Erreur lors de la mise à jour des stats');
}
});
}
function updateStatCards(stats) {
$('.bankily-stat-card.total h3').text(stats.total || 0);
$('.bankily-stat-card.success h3').text(stats.success || 0);
$('.bankily-stat-card.pending h3').text(stats.pending || 0);
$('.bankily-stat-card.failed h3').text(stats.failed || 0);
$('.bankily-stat-card.amount h3').text((stats.total_amount || 0).toLocaleString('fr-FR') + ' MRU');
}
// Log d'initialisation
console.log('[B-PAY Admin] Interface d\'administration initialisée', {
checking: checking,
page: window.location.href,
ajax_url: bankily_admin_ajax.ajax_url
});
});