| @@ -63,9 +63,10 @@ | ||
| 63 | 63 | 'wallet' => '<path d="M3 7a2 2 0 0 1 2-2h14v4"/><rect x="3" y="7" width="18" height="12" rx="2"/><path d="M16 13h.01"/>', |
| 64 | 64 | ]; |
| 65 | 65 | $id = strtolower($gateway_id); |
| 66 | 66 | $key = 'card'; |
| 67 | - if (false !== strpos($id, 'bank') || false !== strpos($id, 'transfer') || false !== strpos($id, 'wire')) { $key = 'bank'; } | |
| 67 | + if (isset($paths[strtolower($icon)])) { $key = strtolower($icon); } | |
| 68 | + elseif (false !== strpos($id, 'bank') || false !== strpos($id, 'transfer') || false !== strpos($id, 'wire')) { $key = 'bank'; } | |
| 68 | 69 | elseif (false !== strpos($id, 'cheque') || false !== strpos($id, 'check')) { $key = 'cheque'; } |
| 69 | 70 | elseif (false !== strpos($id, 'cash')) { $key = 'cash'; } |
| 70 | 71 | elseif (false !== strpos($id, 'paypal') || false !== strpos($id, 'paystack') || false !== strpos($id, 'mollie')) { $key = 'wallet'; } |
| 71 | 72 | return '<svg ' . $a . '>' . $paths[$key] . '</svg>'; |
| @@ -356,8 +357,24 @@ | ||
| 356 | 357 | margin-top: 8px; |
| 357 | 358 | font-size: 13px; |
| 358 | 359 | } |
| 359 | 360 | |
| 361 | +.gateway-content .ei-offline h4 { margin: 0 0 10px; font-size: 15px; font-weight: 600; color: #111827; } | |
| 362 | +.gateway-content .ei-offline__details { width: 100%; border-collapse: collapse; margin-bottom: 12px; font-size: 13px; } | |
| 363 | +.gateway-content .ei-offline__details th { text-align: left; padding: 6px 8px 6px 0; color: #6b7280; font-weight: 500; width: 40%; vertical-align: top; } | |
| 364 | +.gateway-content .ei-offline__details td { padding: 6px 0; color: #111827; font-weight: 600; word-break: break-word; } | |
| 365 | +.gateway-content .ei-offline__instructions { font-size: 13px; color: #374151; line-height: 1.5; margin-bottom: 10px; } | |
| 366 | +.gateway-content .ei-offline__instructions p { margin: 0 0 8px; } | |
| 367 | +.gateway-content .ei-offline__form { margin-top: 14px; padding-top: 14px; border-top: 1px solid #e5e7eb; } | |
| 368 | +.gateway-content .ei-offline__lead { font-size: 13px; color: #374151; margin: 0 0 10px; } | |
| 369 | +.gateway-content .ei-offline__form .form-group { margin-bottom: 12px; } | |
| 370 | +.gateway-content .ei-offline__form label { display: block; font-size: 13px; font-weight: 600; color: #111827; margin-bottom: 4px; } | |
| 371 | +.gateway-content .ei-offline__optional { font-weight: 400; color: #6b7280; } | |
| 372 | +.gateway-content .ei-offline__required { color: #dc2626; } | |
| 373 | +.gateway-content .ei-offline__form input[type="text"], | |
| 374 | +.gateway-content .ei-offline__form textarea { width: 100%; box-sizing: border-box; border: 1px solid #d1d5db; border-radius: 8px; padding: 9px 12px; font-size: 14px; background: #fff; } | |
| 375 | +.gateway-content .ei-offline__form input[type="file"] { display: block; width: 100%; font-size: 13px; color: #374151; } | |
| 376 | +.gateway-content .ei-offline__form .reference-note { margin: 4px 0 0; font-size: 12px; color: #6b7280; } | |
| 360 | 377 | .gateway-content .payment-proof-form { |
| 361 | 378 | margin-top: 24px; |
| 362 | 379 | padding-top: 20px; |
| 363 | 380 | border-top: 1px solid #e5e7eb; |
| @@ -835,8 +852,9 @@ | ||
| 835 | 852 | .then(response => { |
| 836 | 853 | if (response.success && response.data.instructions) { |
| 837 | 854 | contentDiv.innerHTML = response.data.instructions; |
| 838 | 855 | contentDiv.style.display = 'block'; |
| 856 | + applyOfflineState(contentDiv); | |
| 839 | 857 | } else { |
| 840 | 858 | contentDiv.style.display = 'none'; |
| 841 | 859 | } |
| 842 | 860 | }) |
| @@ -874,8 +892,23 @@ | ||
| 874 | 892 | } |
| 875 | 893 | |
| 876 | 894 | |
| 877 | 895 | |
| 896 | + // An offline method (bank transfer, cheque, cash, …) is not charged here: | |
| 897 | + // the button becomes "Submit payment details" and a required receipt is | |
| 898 | + // checked before anything is sent. | |
| 899 | + window.eiOfflineSelected = false; | |
| 900 | + function applyOfflineState(contentDiv) { | |
| 901 | + var offline = contentDiv ? contentDiv.querySelector('[data-ei-offline]') : null; | |
| 902 | + window.eiOfflineSelected = !!offline; | |
| 903 | + if (!payButton || !payButton.querySelector('.button-text')) { return; } | |
| 904 | + if (offline) { | |
| 905 | + payButton.querySelector('.button-text').textContent = offline.getAttribute('data-ei-submit-label') || 'Submit payment details'; | |
| 906 | + } else { | |
| 907 | + updatePayButtonText(); | |
| 908 | + } | |
| 909 | + } | |
| 910 | + | |
| 878 | 911 | function handlePaymentSubmit(e) { |
| 879 | 912 | e.preventDefault(); |
| 880 | 913 | payButton.disabled = true; |
| 881 | 914 | |
| @@ -883,8 +916,17 @@ | ||
| 883 | 916 | showPaymentMessage('Please select a payment method first.', 'error'); |
| 884 | 917 | payButton.disabled = false; |
| 885 | 918 | return; |
| 886 | 919 | } |
| 920 | + if (window.eiOfflineSelected) { | |
| 921 | + var required = paymentForm.querySelector('input[type="file"][data-ei-required]'); | |
| 922 | + if (required && !(required.files && required.files.length)) { | |
| 923 | + showPaymentMessage(<?php echo wp_json_encode(__('Please attach your receipt or proof of payment.', 'easy-invoice')); ?>, 'error'); | |
| 924 | + payButton.disabled = false; | |
| 925 | + required.focus(); | |
| 926 | + return; | |
| 927 | + } | |
| 928 | + } | |
| 887 | 929 | |
| 888 | 930 | // Show loading state |
| 889 | 931 | payButton.querySelector('.button-text').classList.add('hidden'); |
| 890 | 932 | payButton.querySelector('.button-loader').classList.remove('hidden'); |
| @@ -953,8 +995,17 @@ | ||
| 953 | 995 | }, 1000); |
| 954 | 996 | return; |
| 955 | 997 | } |
| 956 | 998 | |
| 999 | + if (data.offline) { | |
| 1000 | + payButton.querySelector('.button-loader').classList.add('hidden'); | |
| 1001 | + payButton.querySelector('.button-text').classList.remove('hidden'); | |
| 1002 | + payButton.querySelector('.button-text').textContent = <?php echo wp_json_encode(__('Submitted', 'easy-invoice')); ?>; | |
| 1003 | + payButton.disabled = true; | |
| 1004 | + showPaymentMessage(data.message || 'Thank you — we will confirm your payment shortly.', 'success'); | |
| 1005 | + setTimeout(function () { window.location.reload(); }, 2500); | |
| 1006 | + return; | |
| 1007 | + } | |
| 957 | 1008 | // For successful payments without redirect |
| 958 | 1009 | // Update button state |
| 959 | 1010 | payButton.querySelector('.button-text').textContent = 'Payment Successful!'; |
| 960 | 1011 | payButton.querySelector('.button-loader').classList.add('hidden'); |
| @@ -989,8 +1040,9 @@ | ||
| 989 | 1040 | |
| 990 | 1041 | function updatePayButtonText() { |
| 991 | 1042 | // No button when the panel has no payment methods to offer. |
| 992 | 1043 | if (!payButton || !payButton.querySelector('.button-text')) { return; } |
| 1044 | + if (window.eiOfflineSelected) { return; } | |
| 993 | 1045 | const hiddenPaymentAmount = document.getElementById('payment_amount'); |
| 994 | 1046 | const paymentAmount = hiddenPaymentAmount ? hiddenPaymentAmount.value : '0'; |
| 995 | 1047 | const money = <?php echo wp_json_encode(easy_invoice_money_format_spec($invoice)); ?>; |
| 996 | 1048 | const payLabel = <?php echo wp_json_encode(__('Pay', 'easy-invoice')); ?>; |