add assets
This commit is contained in:
844
assets/bankily-admin.css
Normal file
844
assets/bankily-admin.css
Normal file
@@ -0,0 +1,844 @@
|
|||||||
|
/**
|
||||||
|
* Styles CSS pour l'interface d'administration B-PAY Bankily
|
||||||
|
* Fichier: assets/bankily-admin.css
|
||||||
|
* Version: 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* === VARIABLES CSS === */
|
||||||
|
:root {
|
||||||
|
--bankily-primary: #007cba;
|
||||||
|
--bankily-success: #28a745;
|
||||||
|
--bankily-warning: #ffc107;
|
||||||
|
--bankily-danger: #dc3545;
|
||||||
|
--bankily-info: #17a2b8;
|
||||||
|
--bankily-light: #f8f9fa;
|
||||||
|
--bankily-dark: #343a40;
|
||||||
|
--bankily-border: #dee2e6;
|
||||||
|
--bankily-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
--bankily-shadow-lg: 0 4px 8px rgba(0,0,0,0.15);
|
||||||
|
--bankily-border-radius: 8px;
|
||||||
|
--bankily-transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === LAYOUT GÉNÉRAL === */
|
||||||
|
.wrap .bankily-stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid var(--bankily-border);
|
||||||
|
border-radius: var(--bankily-border-radius);
|
||||||
|
padding: 24px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: var(--bankily-shadow);
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--bankily-shadow-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--bankily-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card h3 {
|
||||||
|
font-size: 2.8em;
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card p {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Couleurs des cartes statistiques */
|
||||||
|
.bankily-stat-card.total::before { background: var(--bankily-primary); }
|
||||||
|
.bankily-stat-card.total h3 { color: var(--bankily-primary); }
|
||||||
|
|
||||||
|
.bankily-stat-card.success::before { background: var(--bankily-success); }
|
||||||
|
.bankily-stat-card.success h3 { color: var(--bankily-success); }
|
||||||
|
|
||||||
|
.bankily-stat-card.pending::before { background: var(--bankily-warning); }
|
||||||
|
.bankily-stat-card.pending h3 { color: var(--bankily-warning); }
|
||||||
|
|
||||||
|
.bankily-stat-card.failed::before { background: var(--bankily-danger); }
|
||||||
|
.bankily-stat-card.failed h3 { color: var(--bankily-danger); }
|
||||||
|
|
||||||
|
.bankily-stat-card.amount::before { background: var(--bankily-info); }
|
||||||
|
.bankily-stat-card.amount h3 { color: var(--bankily-info); }
|
||||||
|
|
||||||
|
/* === ACTIONS RAPIDES === */
|
||||||
|
.bankily-quick-actions {
|
||||||
|
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||||
|
border: 1px solid var(--bankily-border);
|
||||||
|
border-radius: var(--bankily-border-radius);
|
||||||
|
padding: 24px;
|
||||||
|
margin: 20px 0 30px 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-quick-actions::before {
|
||||||
|
content: '⚡';
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
left: 20px;
|
||||||
|
background: var(--bankily-warning);
|
||||||
|
color: white;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-quick-actions h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-action-buttons .button {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-action-buttons .button-primary {
|
||||||
|
background: var(--bankily-primary);
|
||||||
|
border-color: var(--bankily-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-action-buttons .button-primary:hover {
|
||||||
|
background: #005a87;
|
||||||
|
border-color: #005a87;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === STATUTS DES TRANSACTIONS === */
|
||||||
|
.bankily-status {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.8px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-status-ts {
|
||||||
|
background: linear-gradient(135deg, #d4edda, #c3e6cb);
|
||||||
|
color: #155724;
|
||||||
|
border-color: #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-status-tf {
|
||||||
|
background: linear-gradient(135deg, #f8d7da, #f5c6cb);
|
||||||
|
color: #721c24;
|
||||||
|
border-color: #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-status-ta {
|
||||||
|
background: linear-gradient(135deg, #fff3cd, #ffeaa7);
|
||||||
|
color: #856404;
|
||||||
|
border-color: #ffeaa7;
|
||||||
|
animation: pulse-warning 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-warning {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.8; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === FILTRES ET RECHERCHE === */
|
||||||
|
.bankily-filters {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid var(--bankily-border);
|
||||||
|
border-radius: var(--bankily-border-radius);
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
box-shadow: var(--bankily-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-search-box {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-search-box input[type="text"] {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 300px;
|
||||||
|
padding: 10px 16px;
|
||||||
|
border: 2px solid var(--bankily-border);
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-search-box input[type="text"]:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--bankily-primary);
|
||||||
|
box-shadow: 0 0 0 3px rgba(0, 124, 186, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-advanced-filters {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid var(--bankily-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-filter-group label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-filter-group select,
|
||||||
|
.bankily-filter-group input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid var(--bankily-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-filter-group select:focus,
|
||||||
|
.bankily-filter-group input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--bankily-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === ACTIONS EN LOT === */
|
||||||
|
.bankily-bulk-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-bottom: 2px solid var(--bankily-border);
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: linear-gradient(90deg, rgba(0, 124, 186, 0.05) 0%, rgba(0, 124, 186, 0.02) 100%);
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin: 10px 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-bulk-actions select {
|
||||||
|
margin-right: 8px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-bulk-actions .button.action:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-bulk-actions .displaying-num {
|
||||||
|
color: #666;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TABLEAU DES TRANSACTIONS === */
|
||||||
|
.wp-list-table {
|
||||||
|
border-radius: var(--bankily-border-radius);
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: var(--bankily-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .transaction-row {
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .transaction-row:hover {
|
||||||
|
background-color: rgba(0, 124, 186, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .transaction-row.updated {
|
||||||
|
background-color: rgba(40, 167, 69, 0.1);
|
||||||
|
border-left: 4px solid var(--bankily-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .transaction-row.bankily-checking {
|
||||||
|
background-color: rgba(0, 124, 186, 0.1);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .transaction-row.bankily-success {
|
||||||
|
background-color: rgba(40, 167, 69, 0.15);
|
||||||
|
animation: flash-success 1.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .transaction-row.bankily-error {
|
||||||
|
background-color: rgba(220, 53, 69, 0.15);
|
||||||
|
animation: flash-error 1.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash-success {
|
||||||
|
0%, 100% { background-color: rgba(40, 167, 69, 0.15); }
|
||||||
|
50% { background-color: rgba(40, 167, 69, 0.3); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash-error {
|
||||||
|
0%, 100% { background-color: rgba(220, 53, 69, 0.15); }
|
||||||
|
50% { background-color: rgba(220, 53, 69, 0.3); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .operation-id {
|
||||||
|
font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .operation-id small {
|
||||||
|
color: #666;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions .button {
|
||||||
|
margin: 2px;
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions .button:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions .button.bankily-loading {
|
||||||
|
position: relative;
|
||||||
|
color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions .button.bankily-loading::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -6px;
|
||||||
|
margin-top: -6px;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top-color: transparent;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .error-message {
|
||||||
|
color: var(--bankily-danger);
|
||||||
|
font-style: italic;
|
||||||
|
cursor: help;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .error-message:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Statuts des commandes */
|
||||||
|
.order-status-completed { color: var(--bankily-success); font-weight: 600; }
|
||||||
|
.order-status-processing { color: var(--bankily-info); font-weight: 600; }
|
||||||
|
.order-status-on-hold { color: var(--bankily-warning); font-weight: 600; }
|
||||||
|
.order-status-cancelled { color: var(--bankily-danger); font-weight: 600; }
|
||||||
|
.order-status-refunded { color: #6c757d; font-weight: 600; }
|
||||||
|
.order-status-failed { color: var(--bankily-danger); font-weight: 600; }
|
||||||
|
.order-status-pending { color: #fd7e14; font-weight: 600; }
|
||||||
|
|
||||||
|
/* === BARRE DE PROGRESSION === */
|
||||||
|
#bankily-progress-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
z-index: 999999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-container {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: var(--bankily-border-radius);
|
||||||
|
padding: 40px;
|
||||||
|
min-width: 450px;
|
||||||
|
max-width: 90vw;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 3px solid var(--bankily-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-container h3 {
|
||||||
|
margin: 0 0 24px 0;
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
background: #e9ecef;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border: 2px solid var(--bankily-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(45deg, var(--bankily-primary), var(--bankily-info));
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-fill::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
rgba(255, 255, 255, 0.3) 25%,
|
||||||
|
transparent 25%,
|
||||||
|
transparent 50%,
|
||||||
|
rgba(255, 255, 255, 0.3) 50%,
|
||||||
|
rgba(255, 255, 255, 0.3) 75%,
|
||||||
|
transparent 75%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
background-size: 24px 24px;
|
||||||
|
animation: progress-stripes 1.5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes progress-stripes {
|
||||||
|
0% { background-position: 0 0; }
|
||||||
|
100% { background-position: 24px 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-text {
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-container p {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-container small {
|
||||||
|
color: #666;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === PAGINATION === */
|
||||||
|
.bankily-pagination {
|
||||||
|
text-align: center;
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-pagination .page-numbers {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 14px;
|
||||||
|
margin: 0 3px;
|
||||||
|
border: 2px solid var(--bankily-border);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--bankily-primary);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-pagination .page-numbers:hover {
|
||||||
|
background: var(--bankily-primary);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--bankily-primary);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-pagination .page-numbers.current {
|
||||||
|
background: var(--bankily-primary);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--bankily-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === NOTICES === */
|
||||||
|
.bankily-notice {
|
||||||
|
margin: 15px 0;
|
||||||
|
animation: slideDown 0.4s ease;
|
||||||
|
border-left: 4px solid var(--bankily-primary);
|
||||||
|
box-shadow: var(--bankily-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideDown {
|
||||||
|
from {
|
||||||
|
transform: translateY(-20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-notice.notice-success {
|
||||||
|
border-left-color: var(--bankily-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-notice.notice-error {
|
||||||
|
border-left-color: var(--bankily-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-notice.notice-warning {
|
||||||
|
border-left-color: var(--bankily-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-notice.notice-info {
|
||||||
|
border-left-color: var(--bankily-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === INDICATEUR DE CONNEXION === */
|
||||||
|
#bankily-connection-status {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 10px 16px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
z-index: 10000;
|
||||||
|
transition: var(--bankily-transition);
|
||||||
|
box-shadow: var(--bankily-shadow-lg);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bankily-connection-status.online {
|
||||||
|
background: linear-gradient(135deg, var(--bankily-success), #20c997);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--bankily-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
#bankily-connection-status.offline {
|
||||||
|
background: linear-gradient(135deg, var(--bankily-danger), #e83e8c);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--bankily-danger);
|
||||||
|
animation: pulse-offline 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-offline {
|
||||||
|
0%, 100% { opacity: 1; transform: scale(1); }
|
||||||
|
50% { opacity: 0.8; transform: scale(1.05); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TOOLTIPS === */
|
||||||
|
#bankily-tooltip {
|
||||||
|
background: var(--bankily-dark);
|
||||||
|
color: #fff;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
max-width: 300px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
box-shadow: var(--bankily-shadow-lg);
|
||||||
|
z-index: 999999;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === BADGES ET ICÔNES === */
|
||||||
|
.bankily-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 3px 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-badge.new {
|
||||||
|
background: linear-gradient(135deg, #e3f2fd, #bbdefb);
|
||||||
|
color: #1976d2;
|
||||||
|
border: 1px solid #90caf9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-badge.urgent {
|
||||||
|
background: linear-gradient(135deg, #ffebee, #ffcdd2);
|
||||||
|
color: #c62828;
|
||||||
|
border: 1px solid #ef9a9a;
|
||||||
|
animation: pulse-urgent 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-urgent {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.7; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === RESPONSIVE === */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.bankily-stats-grid {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card h3 {
|
||||||
|
font-size: 2.4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 782px) {
|
||||||
|
.bankily-stats-grid {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card h3 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-search-box {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-search-box input[type="text"] {
|
||||||
|
min-width: auto;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-action-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-action-buttons .button {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-bulk-actions {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-advanced-filters {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table .actions .button {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-container {
|
||||||
|
padding: 20px;
|
||||||
|
min-width: auto;
|
||||||
|
max-width: 95vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bankily-connection-status {
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.bankily-stats-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-quick-actions {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-filters {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table th,
|
||||||
|
.wp-list-table td {
|
||||||
|
padding: 8px 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === DARK MODE (optionnel) === */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--bankily-light: #2c3e50;
|
||||||
|
--bankily-border: #34495e;
|
||||||
|
--bankily-dark: #ecf0f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card {
|
||||||
|
background: var(--bankily-light);
|
||||||
|
border-color: var(--bankily-border);
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-quick-actions {
|
||||||
|
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
|
||||||
|
border-color: var(--bankily-border);
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-filters {
|
||||||
|
background: var(--bankily-light);
|
||||||
|
border-color: var(--bankily-border);
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-progress-container {
|
||||||
|
background: var(--bankily-light);
|
||||||
|
color: var(--bankily-dark);
|
||||||
|
border-color: var(--bankily-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === ANIMATIONS SUPPLÉMENTAIRES === */
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stats-grid .bankily-stat-card {
|
||||||
|
animation: fadeInUp 0.5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stats-grid .bankily-stat-card:nth-child(1) { animation-delay: 0.1s; }
|
||||||
|
.bankily-stats-grid .bankily-stat-card:nth-child(2) { animation-delay: 0.2s; }
|
||||||
|
.bankily-stats-grid .bankily-stat-card:nth-child(3) { animation-delay: 0.3s; }
|
||||||
|
.bankily-stats-grid .bankily-stat-card:nth-child(4) { animation-delay: 0.4s; }
|
||||||
|
.bankily-stats-grid .bankily-stat-card:nth-child(5) { animation-delay: 0.5s; }
|
||||||
|
|
||||||
|
/* === ACCESSIBILITÉ === */
|
||||||
|
.sr-only {
|
||||||
|
position: absolute !important;
|
||||||
|
width: 1px !important;
|
||||||
|
height: 1px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: -1px !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
clip: rect(0, 0, 0, 0) !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus visible pour la navigation clavier */
|
||||||
|
.bankily-stat-card:focus,
|
||||||
|
.button:focus,
|
||||||
|
input:focus,
|
||||||
|
select:focus,
|
||||||
|
.bankily-status:focus {
|
||||||
|
outline: 2px solid var(--bankily-primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === IMPRESSION === */
|
||||||
|
@media print {
|
||||||
|
.bankily-action-buttons,
|
||||||
|
.bankily-bulk-actions,
|
||||||
|
.wp-list-table .actions,
|
||||||
|
#bankily-connection-status,
|
||||||
|
.notice,
|
||||||
|
#bankily-progress-overlay {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-stat-card {
|
||||||
|
break-inside: avoid;
|
||||||
|
box-shadow: none;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-list-table {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-status {
|
||||||
|
border: 1px solid #000 !important;
|
||||||
|
background: #fff !important;
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
721
assets/bankily-admin.js
Normal file
721
assets/bankily-admin.js
Normal file
@@ -0,0 +1,721 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
});
|
||||||
|
});
|
||||||
435
assets/bankily-bpay.js
Normal file
435
assets/bankily-bpay.js
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
/**
|
||||||
|
* Script JavaScript pour le frontend B-PAY Bankily
|
||||||
|
* Fichier: assets/bankily-bpay.js
|
||||||
|
* Version: 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
jQuery(document).ready(function($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Variables globales
|
||||||
|
var bankily_form = 'form.checkout, form#order_review';
|
||||||
|
var bankily_gateway = '#payment_method_bankily_bpay';
|
||||||
|
|
||||||
|
// Initialisation
|
||||||
|
initializeBankilyCheckout();
|
||||||
|
|
||||||
|
function initializeBankilyCheckout() {
|
||||||
|
// Gestion de la sélection de la méthode de paiement
|
||||||
|
$(document).on('change', 'input[name="payment_method"]', function() {
|
||||||
|
toggleBankilyFields();
|
||||||
|
if ($(this).val() === 'bankily_bpay') {
|
||||||
|
// Focus sur le premier champ et pré-remplir en mode test
|
||||||
|
setTimeout(function() {
|
||||||
|
$('#bankily_phone').focus();
|
||||||
|
if (bankily_bpay_params.testmode === '1') {
|
||||||
|
fillTestData();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validation en temps réel
|
||||||
|
setupRealtimeValidation();
|
||||||
|
|
||||||
|
// Formatage des champs
|
||||||
|
setupFieldFormatting();
|
||||||
|
|
||||||
|
// Gestion de la soumission
|
||||||
|
$(bankily_form).on('checkout_place_order_bankily_bpay', function() {
|
||||||
|
return validateBankilyForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stylisation CSS
|
||||||
|
addBankilyStyles();
|
||||||
|
|
||||||
|
// État initial
|
||||||
|
toggleBankilyFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupRealtimeValidation() {
|
||||||
|
// Validation du numéro de téléphone
|
||||||
|
$(document).on('input blur', '#bankily_phone', function() {
|
||||||
|
validatePhoneField($(this));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validation du code PIN
|
||||||
|
$(document).on('input blur', '#bankily_passcode', function() {
|
||||||
|
validatePasscodeField($(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatePhoneField($field) {
|
||||||
|
var phone = $field.val().replace(/\D/g, ''); // Supprimer tous les caractères non numériques
|
||||||
|
var isValid = /^[0-9]{8}$/.test(phone);
|
||||||
|
|
||||||
|
// Mettre à jour la valeur avec uniquement les chiffres
|
||||||
|
$field.val(phone);
|
||||||
|
|
||||||
|
// Validation visuelle
|
||||||
|
updateFieldValidation($field, isValid, phone.length > 0,
|
||||||
|
'Format requis: 8 chiffres (ex: 22123456)');
|
||||||
|
|
||||||
|
// Limiter à 8 chiffres
|
||||||
|
if (phone.length > 8) {
|
||||||
|
$field.val(phone.substring(0, 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatePasscodeField($field) {
|
||||||
|
var passcode = $field.val();
|
||||||
|
var isValid = passcode.length >= 4 && passcode.length <= 6;
|
||||||
|
|
||||||
|
updateFieldValidation($field, isValid, passcode.length > 0,
|
||||||
|
'Le code PIN doit contenir entre 4 et 6 caractères');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFieldValidation($field, isValid, hasContent, errorMessage) {
|
||||||
|
$field.removeClass('valid invalid');
|
||||||
|
$field.next('.bankily-field-error').remove();
|
||||||
|
|
||||||
|
if (hasContent) {
|
||||||
|
if (isValid) {
|
||||||
|
$field.addClass('valid');
|
||||||
|
} else {
|
||||||
|
$field.addClass('invalid');
|
||||||
|
$field.after('<span class="bankily-field-error">' + errorMessage + '</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupFieldFormatting() {
|
||||||
|
// Permettre uniquement les chiffres pour le téléphone
|
||||||
|
$(document).on('keypress', '#bankily_phone', function(e) {
|
||||||
|
// Permettre uniquement les chiffres, backspace, delete, tab, escape, enter
|
||||||
|
if ($.inArray(e.keyCode, [46, 8, 9, 27, 13]) !== -1 ||
|
||||||
|
// Permettre Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X
|
||||||
|
(e.keyCode === 65 && e.ctrlKey === true) ||
|
||||||
|
(e.keyCode === 67 && e.ctrlKey === true) ||
|
||||||
|
(e.keyCode === 86 && e.ctrlKey === true) ||
|
||||||
|
(e.keyCode === 88 && e.ctrlKey === true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// S'assurer que c'est un chiffre
|
||||||
|
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Permettre uniquement les chiffres pour le code PIN
|
||||||
|
$(document).on('keypress', '#bankily_passcode', function(e) {
|
||||||
|
if ($.inArray(e.keyCode, [46, 8, 9, 27, 13]) !== -1 ||
|
||||||
|
(e.keyCode === 65 && e.ctrlKey === true) ||
|
||||||
|
(e.keyCode === 67 && e.ctrlKey === true) ||
|
||||||
|
(e.keyCode === 86 && e.ctrlKey === true) ||
|
||||||
|
(e.keyCode === 88 && e.ctrlKey === true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateBankilyForm() {
|
||||||
|
if (!$(bankily_gateway).is(':checked')) {
|
||||||
|
return true; // Pas notre méthode de paiement
|
||||||
|
}
|
||||||
|
|
||||||
|
var isValid = true;
|
||||||
|
var $phone = $('#bankily_phone');
|
||||||
|
var $passcode = $('#bankily_passcode');
|
||||||
|
|
||||||
|
// Supprimer les anciens messages d'erreur
|
||||||
|
$('.bankily-checkout-error').remove();
|
||||||
|
|
||||||
|
// Validation du téléphone
|
||||||
|
var phone = $phone.val().replace(/\D/g, '');
|
||||||
|
if (!phone || !/^[0-9]{8}$/.test(phone)) {
|
||||||
|
showCheckoutError($phone, 'Veuillez entrer un numéro de téléphone valide (8 chiffres)');
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation du code PIN
|
||||||
|
var passcode = $passcode.val();
|
||||||
|
if (!passcode || passcode.length < 4 || passcode.length > 6) {
|
||||||
|
showCheckoutError($passcode, 'Veuillez entrer votre code PIN B-PAY (4 à 6 chiffres)');
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
// Faire défiler vers le premier champ avec erreur
|
||||||
|
$('html, body').animate({
|
||||||
|
scrollTop: $('.payment_method_bankily_bpay').offset().top - 100
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
// Focus sur le premier champ invalide
|
||||||
|
setTimeout(function() {
|
||||||
|
$('.payment_method_bankily_bpay .invalid').first().focus();
|
||||||
|
}, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showCheckoutError($field, message) {
|
||||||
|
$field.addClass('invalid');
|
||||||
|
if (!$field.next('.bankily-checkout-error').length) {
|
||||||
|
$field.after('<div class="bankily-checkout-error">' + message + '</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleBankilyFields() {
|
||||||
|
if ($(bankily_gateway).is(':checked')) {
|
||||||
|
$('.payment_method_bankily_bpay').slideDown(300);
|
||||||
|
} else {
|
||||||
|
$('.payment_method_bankily_bpay').slideUp(300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillTestData() {
|
||||||
|
if (bankily_bpay_params.testmode === '1') {
|
||||||
|
$('#bankily_phone').val('22123456');
|
||||||
|
$('#bankily_passcode').val('1234');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBankilyStyles() {
|
||||||
|
var styles = `
|
||||||
|
<style id="bankily-bpay-frontend-styles">
|
||||||
|
.payment_method_bankily_bpay .form-row input.valid {
|
||||||
|
border-color: #28a745 !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay .form-row input.invalid {
|
||||||
|
border-color: #dc3545 !important;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-field-error,
|
||||||
|
.bankily-checkout-error {
|
||||||
|
color: #dc3545;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
|
display: block;
|
||||||
|
animation: slideDown 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideDown {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay .form-row {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay label {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay input[type="tel"],
|
||||||
|
.payment_method_bankily_bpay input[type="password"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: border-color 0.3s, box-shadow 0.3s;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay input[type="tel"]:focus,
|
||||||
|
.payment_method_bankily_bpay input[type="password"]:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #007cba;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(0, 124, 186, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay small {
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 3px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankily-test-notice {
|
||||||
|
background: #fff3cd !important;
|
||||||
|
border: 1px solid #ffeaa7 !important;
|
||||||
|
color: #856404 !important;
|
||||||
|
padding: 10px !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
margin-bottom: 15px !important;
|
||||||
|
border-left: 4px solid #ffc107 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wc-bankily_bpay-form {
|
||||||
|
background: #f9f9f9;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation de chargement */
|
||||||
|
.payment_method_bankily_bpay.processing::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay.processing::before {
|
||||||
|
content: '⏳ Traitement en cours...';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 11;
|
||||||
|
background: #007cba;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
#wc-bankily_bpay-form {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment_method_bankily_bpay input[type="tel"],
|
||||||
|
.payment_method_bankily_bpay input[type="password"] {
|
||||||
|
padding: 12px 14px;
|
||||||
|
font-size: 16px; /* Évite le zoom sur mobile */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (!$('#bankily-bpay-frontend-styles').length) {
|
||||||
|
$('head').append(styles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestion du chargement lors de la soumission
|
||||||
|
$(document).on('submit', bankily_form, function() {
|
||||||
|
if ($(bankily_gateway).is(':checked')) {
|
||||||
|
$('.payment_method_bankily_bpay').addClass('processing');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Nettoyer l'état de chargement si la soumission échoue
|
||||||
|
$(document).on('checkout_error', function() {
|
||||||
|
$('.payment_method_bankily_bpay').removeClass('processing');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Écouter les changements de checkout (pour WooCommerce AJAX)
|
||||||
|
$(document).on('updated_checkout', function() {
|
||||||
|
toggleBankilyFields();
|
||||||
|
|
||||||
|
// Réappliquer la validation sur les champs existants
|
||||||
|
setTimeout(function() {
|
||||||
|
$('#bankily_phone').trigger('blur');
|
||||||
|
$('#bankily_passcode').trigger('blur');
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Amélioration UX: Auto-complétion du préfixe
|
||||||
|
$(document).on('focus', '#bankily_phone', function() {
|
||||||
|
var $this = $(this);
|
||||||
|
if ($this.val() === '' && bankily_bpay_params.testmode !== '1') {
|
||||||
|
// Suggestion visuelle pour le format attendu
|
||||||
|
$this.attr('placeholder', '22XXXXXX');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('blur', '#bankily_phone', function() {
|
||||||
|
$(this).attr('placeholder', 'Exemple: 22123456');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Gestion des raccourcis clavier
|
||||||
|
$(document).on('keydown', '#bankily_phone, #bankily_passcode', function(e) {
|
||||||
|
// Enter pour aller au champ suivant
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $current = $(this);
|
||||||
|
var $next = $current.closest('.form-row').next('.form-row').find('input');
|
||||||
|
|
||||||
|
if ($next.length) {
|
||||||
|
$next.focus();
|
||||||
|
} else {
|
||||||
|
// Si c'est le dernier champ, déclencher la soumission
|
||||||
|
$(bankily_form).find('.place-order').click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validation immédiate lors du collage
|
||||||
|
$(document).on('paste', '#bankily_phone', function() {
|
||||||
|
var $this = $(this);
|
||||||
|
setTimeout(function() {
|
||||||
|
validatePhoneField($this);
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Messages d'aide contextuelle
|
||||||
|
$(document).on('focus', '#bankily_phone', function() {
|
||||||
|
if (!$(this).next('.bankily-help').length) {
|
||||||
|
$(this).after('<small class="bankily-help" style="color: #007cba;">💡 Saisissez votre numéro sans l\'indicatif (+222)</small>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('blur', '#bankily_phone', function() {
|
||||||
|
$(this).next('.bankily-help').fadeOut(300, function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('focus', '#bankily_passcode', function() {
|
||||||
|
if (!$(this).next('.bankily-help').length) {
|
||||||
|
$(this).after('<small class="bankily-help" style="color: #007cba;">🔐 Votre code PIN personnel B-PAY</small>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('blur', '#bankily_passcode', function() {
|
||||||
|
$(this).next('.bankily-help').fadeOut(300, function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fonctions utilitaires
|
||||||
|
function logDebug(message, data) {
|
||||||
|
if (typeof console !== 'undefined' && console.log && bankily_bpay_params.testmode === '1') {
|
||||||
|
console.log('[B-PAY Frontend] ' + message, data || '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log d'initialisation
|
||||||
|
logDebug('Script B-PAY initialisé', {
|
||||||
|
testmode: bankily_bpay_params.testmode,
|
||||||
|
gateway_selector: bankily_gateway
|
||||||
|
});
|
||||||
|
|
||||||
|
// Nettoyage lors du changement de page
|
||||||
|
$(window).on('beforeunload', function() {
|
||||||
|
$('.payment_method_bankily_bpay').removeClass('processing');
|
||||||
|
$('.bankily-field-error, .bankily-checkout-error, .bankily-help').remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user