PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.2.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.2.0
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / templates / payments / list.php

list.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.2.0, at templates/payments/list.php

1,058 lines 53.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Payments List Template
4 *
5 * @package Easy_Invoice
6 */
7
8 // Ensure we're in the correct namespace
9 namespace EasyInvoice\Templates\Payments;
10
11 // Exit if accessed directly
12 if (!defined('ABSPATH')) {
13 exit;
14 }
15
16 use EasyInvoice\Models\Payment;
17 use EasyInvoice\Models\Invoice;
18
19
20 // Extract data passed from controller
21 $payments = $payments ?? [];
22 $current_view = $current_view ?? 'all';
23 $status_filter = $status_filter ?? '';
24 $status_filters = $status_filters ?? [];
25 $trash_count = $trash_count ?? 0;
26 $stats = $stats ?? [];
27 $current_page = $current_page ?? 1;
28 $per_page = $per_page ?? 20;
29 $total_payments = $total_payments ?? 0;
30 $total_pages = $total_pages ?? 1;
31
32 // Ensure all required stats keys exist with default values
33 $stats = array_merge([
34 'total_payments' => 0,
35 'total_amount' => 0,
36 'completed_payments' => 0,
37 'pending_payments' => 0,
38 'failed_payments' => 0
39 ], $stats);
40
41 // Initialize amounts_by_currency array
42 $amounts_by_currency = [];
43 // Calculate stats from the payments array
44 foreach ($payments as $payment) {
45 $amount = floatval($payment->getAmount());
46 $status = $payment->getStatus();
47
48 $stats['total_amount'] += $amount;
49
50 switch ($status) {
51 case 'completed':
52 $stats['completed_payments']++;
53 break;
54 case 'pending':
55 $stats['pending_payments']++;
56 break;
57 case 'failed':
58 $stats['failed_payments']++;
59 break;
60 }
61
62 // Calculate currency breakdown
63 $payment_currency = $payment->getCurrency();
64
65 // If currency is empty or "global", get the actual currency that was used
66 if (empty($payment_currency) || $payment_currency === 'global') {
67 $actual_currency = get_post_meta($payment->getId(), '_currency', true);
68 $payment_currency = !empty($actual_currency) ? $actual_currency : get_option('easy_invoice_currency_code', 'USD');
69 }
70
71 // If currency is still "global", use the global setting
72 if ($payment_currency === 'global') {
73 $payment_currency = get_option('easy_invoice_currency_code', 'USD');
74 }
75
76 $payment_currency_symbol = $payment->getCurrencySymbol() ?: \EasyInvoice\Helpers\CurrencyHelper::getCurrencySymbol($payment_currency);
77
78 // Normalize currency code to uppercase for consistent grouping
79 $payment_currency = strtoupper($payment_currency);
80
81 // Group amounts by currency
82 if (!isset($amounts_by_currency[$payment_currency])) {
83 $amounts_by_currency[$payment_currency] = [
84 'amount' => 0,
85 'symbol' => $payment_currency_symbol
86 ];
87 }
88 $amounts_by_currency[$payment_currency]['amount'] += $amount;
89 }
90
91 // Check for bulk action notifications
92 $notification = false;
93
94 if (isset($_GET['bulk_trashed']) && $_GET['bulk_trashed'] > 0) {
95 $count = intval($_GET['bulk_trashed']);
96 easy_invoice_display_notification('success', sprintf(_n('%s payment moved to trash.', '%s payments moved to trash.', $count, 'easy-invoice'), $count));
97 $notification = true;
98 }
99
100 if (isset($_GET['bulk_restored']) && $_GET['bulk_restored'] > 0) {
101 $count = intval($_GET['bulk_restored']);
102 easy_invoice_display_notification('success', sprintf(_n('%s payment restored from trash.', '%s payments restored from trash.', $count, 'easy-invoice'), $count));
103 $notification = true;
104 }
105
106 if (isset($_GET['bulk_deleted']) && $_GET['bulk_deleted'] > 0) {
107 $count = intval($_GET['bulk_deleted']);
108 easy_invoice_display_notification('success', sprintf(_n('%s payment permanently deleted.', '%s payments permanently deleted.', $count, 'easy-invoice'), $count));
109 $notification = true;
110 }
111
112 if (isset($_GET['bulk_error'])) {
113 $error = sanitize_text_field($_GET['bulk_error']);
114 $error_message = 'An error occurred while processing the bulk action.';
115
116 if ($error === 'no_selection') {
117 $error_message = 'Please select at least one payment to perform this action.';
118 } elseif ($error === 'invalid_action') {
119 $error_message = 'Please select a valid bulk action.';
120 }
121
122 easy_invoice_display_notification('error', $error_message);
123 $notification = true;
124 }
125
126 ?>
127 <div class="p-8">
128 <!-- Header with Actions -->
129 <div class="ei-app-page-header bg-white border-b border-gray-200 px-6" style="margin-left: -2rem; margin-top: -2rem; margin-right: -2rem; padding-left: 2rem; padding-right: 2rem;">
130 <div class="flex items-center justify-between">
131 <div>
132 <h1 class="text-2xl font-bold text-gray-900"><?php _e('Payments', 'easy-invoice'); ?></h1>
133 <p class="mt-1 text-sm text-gray-500"><?php _e('Manage all payment records', 'easy-invoice'); ?></p>
134 </div>
135 <div class="flex items-center space-x-3">
136 <?php if (!easy_invoice_has_pro()): ?>
137 <button type="button" id="export-all-payments-btn" class="premium-export-btn inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors duration-200 relative">
138 <svg class="w-4 h-4 mr-2 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
139 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
140 </svg>
141 <?php _e('Export All', 'easy-invoice'); ?>
142 <svg class="ml-2 w-5 h-5 text-purple-600 crown-icon" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
143 <path d="M12 8L15 13.2L18 10.5L17.3 14H6.7L6 10.5L9 13.2L12 8M12 4L8.5 10L3 5L5 16H19L21 5L15.5 10L12 4Z"/>
144 </svg>
145 </button>
146 <script>
147 jQuery(document).ready(function($) {
148 $('#export-all-payments-btn').on('click', function(e) {
149 e.preventDefault();
150 // Show premium popup using the proper confirmation modal
151 if (typeof EasyInvoiceConfirmation !== 'undefined') {
152 EasyInvoiceConfirmation.showFeatureUpgrade('Export All Payments', 'Export all your payments to CSV, Excel, or PDF format for backup, analysis, or sharing with your team.');
153 } else {
154 // Fallback to toast if confirmation modal is not available
155 EasyInvoiceToast.error('<?php echo esc_js(__('Exporting all payments is a premium feature. Upgrade to Easy Invoice Pro to unlock this feature.', 'easy-invoice')); ?>');
156 }
157 });
158 });
159 </script>
160 <?php else: ?>
161 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;">
162 <input type="hidden" name="action" value="easy_invoice_export_all_payments" />
163 <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('easy_invoice_export_all_payments'); ?>" />
164 <button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-indigo-700 bg-indigo-100 hover:bg-indigo-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
165 <svg class="w-4 h-4 mr-2 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
166 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
167 </svg>
168 <?php _e('Export All', 'easy-invoice'); ?>
169 </button>
170 </form>
171 <?php endif; ?>
172
173 <a href="?page=easy-invoice-payment-new" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
174 <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
175 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
176 </svg>
177 <?php _e('Add New Payment', 'easy-invoice'); ?>
178 </a>
179 </div>
180 </div>
181 </div>
182
183 <!-- Stats Cards -->
184 <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8 mt-8">
185 <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
186 <div class="flex items-center">
187 <div class="rounded-full bg-indigo-100 p-3 mr-4">
188 <svg class="w-6 h-6 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
189 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
190 </svg>
191 </div>
192 <div>
193 <h3 class="text-sm font-medium text-gray-500">Total Payments</h3>
194 <p class="mt-1 text-2xl font-bold text-gray-900"><?php echo $stats['total_payments']; ?></p>
195 </div>
196 </div>
197 </div>
198 <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
199 <div class="flex items-center">
200 <div class="rounded-full bg-green-100 p-3 mr-4">
201 <svg class="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
202 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
203 </svg>
204 </div>
205 <div>
206 <h3 class="text-sm font-medium text-gray-500">Total Amount</h3>
207 <?php if (!empty($amounts_by_currency)): ?>
208 <div class="mt-1">
209 <?php foreach ($amounts_by_currency as $currency => $data): ?>
210 <p class="text-lg font-bold text-gray-900">
211 <?php echo $data['symbol'] . number_format($data['amount'], 2); ?>
212 <span class="text-sm font-normal text-gray-500"><?php echo strtoupper($currency ?? 'USD'); ?></span>
213 </p>
214 <?php endforeach; ?>
215 </div>
216 <?php else: ?>
217 <p class="mt-1 text-lg font-bold text-gray-900"><?php echo get_option('easy_invoice_currency_symbol', '$') . '0.00'; ?></p>
218 <?php endif; ?>
219 </div>
220 </div>
221 </div>
222 <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
223 <div class="flex items-center">
224 <div class="rounded-full bg-green-100 p-3 mr-4">
225 <svg class="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
226 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
227 </svg>
228 </div>
229 <div>
230 <h3 class="text-sm font-medium text-gray-500">Completed Payments</h3>
231 <p class="mt-1 text-2xl font-bold text-green-600"><?php echo $stats['completed_payments']; ?></p>
232 </div>
233 </div>
234 </div>
235 <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
236 <div class="flex items-center">
237 <div class="rounded-full bg-yellow-100 p-3 mr-4">
238 <svg class="w-6 h-6 text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
239 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
240 </svg>
241 </div>
242 <div>
243 <h3 class="text-sm font-medium text-gray-500">Pending Payments</h3>
244 <p class="mt-1 text-2xl font-bold text-yellow-600"><?php echo $stats['pending_payments']; ?></p>
245 </div>
246 </div>
247 </div>
248 </div>
249
250 <!-- Top Pagination -->
251 <?php if ($total_payments > 0): ?>
252 <div class="mb-4">
253 <div class="px-4 py-3 flex items-center justify-between">
254 <div class="flex items-center space-x-2">
255 <span class="text-sm text-gray-700">
256 Showing
257 <span class="font-medium"><?php echo number_format((($current_page - 1) * $per_page) + 1); ?></span>
258 to
259 <span class="font-medium"><?php echo number_format(min($current_page * $per_page, $total_payments)); ?></span>
260 of
261 <span class="font-medium"><?php echo number_format($total_payments); ?></span>
262 results
263 </span>
264 </div>
265 <?php if ($total_pages > 1): ?>
266 <div class="flex items-center space-x-2">
267 <span class="text-sm text-gray-500">Page <?php echo number_format($current_page); ?> of <?php echo number_format($total_pages); ?></span>
268 <?php
269 // Use WordPress's built-in pagination for top
270 $top_pagination_args = array(
271 'base' => add_query_arg('paged', '%#%'),
272 'format' => '',
273 'current' => $current_page,
274 'total' => $total_pages,
275 'prev_text' => '‹ Previous',
276 'next_text' => 'Next ›',
277 'type' => 'array',
278 'end_size' => 1,
279 'mid_size' => 2,
280 'add_args' => array(
281 'page' => 'easy-invoice-payments',
282 'view' => $current_view,
283 'status' => $status_filter
284 )
285 );
286
287 $top_pagination_links = paginate_links($top_pagination_args);
288
289 if ($top_pagination_links) {
290 echo '<div class="flex space-x-1">';
291 foreach ($top_pagination_links as $link) {
292 // Add null check to prevent passing null to easy_invoice_str_replace
293 if ($link === null) {
294 continue;
295 }
296
297 // Convert WordPress pagination to our styling
298 $link = easy_invoice_str_replace('page-numbers', 'px-3 py-2 text-sm font-medium border border-gray-300 rounded-md', $link);
299 $link = easy_invoice_str_replace('current', 'bg-indigo-50 border-indigo-500 text-indigo-600', $link);
300 $link = easy_invoice_str_replace('prev', 'bg-white text-gray-500 hover:bg-gray-50', $link);
301 $link = easy_invoice_str_replace('next', 'bg-white text-gray-500 hover:bg-gray-50', $link);
302 $link = easy_invoice_str_replace('dots', 'bg-white text-gray-700', $link);
303
304 // Add default styling for regular page numbers
305 if ($link && strpos($link, 'bg-indigo-50') === false && strpos($link, 'bg-white') === false) {
306 $link = easy_invoice_str_replace('border-gray-300', 'border-gray-300 bg-white text-gray-500 hover:bg-gray-50', $link);
307 }
308
309 echo $link;
310 }
311 echo '</div>';
312 }
313 ?>
314 </div>
315 <?php endif; ?>
316 </div>
317 </div>
318 <?php endif; ?>
319
320 <!-- Tabs with more modern styling -->
321 <div class="bg-white rounded-lg shadow mb-6 overflow-hidden">
322 <!-- Tabs with more modern styling -->
323 <div class="border-b border-gray-200 bg-gradient-to-r from-indigo-50 to-white">
324 <nav class="flex">
325 <?php
326 // View Tabs (All, Trash)
327 $views = array(
328 'all' => 'All (' . $stats['total_payments'] . ')',
329 'trash' => 'Trash (' . $trash_count . ')'
330 );
331
332 foreach ($views as $view => $label) {
333 $is_current = $current_view === $view;
334 $status_param = !empty($status_filter) && $view === 'all' ? '&status=' . $status_filter : '';
335 $class = $is_current
336 ? 'border-b-2 border-indigo-500 text-indigo-600 bg-white'
337 : 'border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300';
338 ?>
339 <a href="?page=easy-invoice-payments&view=<?php echo $view . $status_param; ?>"
340 class="flex items-center whitespace-nowrap py-4 px-6 font-medium text-sm transition-colors duration-200 <?php echo $class; ?>">
341 <?php echo $label; ?>
342 </a>
343 <?php } ?>
344 </nav>
345 </div>
346 </div>
347
348 <!-- Payments Table -->
349 <div class="bg-white shadow overflow-hidden sm:rounded-lg">
350 <!-- Bulk Actions -->
351 <div class="px-6 py-3 border-b border-gray-200 bg-gray-50">
352 <div class="flex items-center justify-between">
353 <div class="flex items-center space-x-4">
354 <form id="bulk-action-form" method="post" class="flex items-center gap-2">
355 <?php wp_nonce_field('easy_invoice_payment_bulk_action', 'easy_invoice_payment_bulk_nonce'); ?>
356 <input type="hidden" name="action" value="easy_invoice_payment_bulk_action">
357
358 <select name="bulk_action" class="block w-full px-3 py-2 border border-gray-300 rounded-md leading-5 bg-white text-gray-700 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
359 <option value="">Bulk Actions</option>
360 <?php if ($current_view === 'trash'): ?>
361 <option value="restore">Restore</option>
362 <option value="delete">Delete Permanently</option>
363 <?php else: ?>
364 <option value="trash">Move to Trash</option>
365 <option value="delete">Delete Permanently</option>
366 <?php endif; ?>
367 </select>
368
369 <button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
370 Apply
371 </button>
372 </form>
373 </div>
374 <div class="text-sm text-gray-500">
375 <span id="selected-count">0</span> payments selected
376 </div>
377 </div>
378 </div>
379
380 <div class="ei-table-responsive">
381 <table class="min-w-full divide-y divide-gray-200 ei-payments-table">
382 <thead class="bg-gray-50">
383 <tr>
384 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
385 <input type="checkbox" id="select-all-payments" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
386 </th>
387 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="id">
388 <div class="flex items-center space-x-1">
389 <span>Payment ID</span>
390 <div class="sort-indicator">
391 <i class="fas fa-sort text-gray-400"></i>
392 </div>
393 </div>
394 </th>
395 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="invoice">
396 <div class="flex items-center space-x-1">
397 <span>Invoice</span>
398 <div class="sort-indicator">
399 <i class="fas fa-sort text-gray-400"></i>
400 </div>
401 </div>
402 </th>
403 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="amount">
404 <div class="flex items-center space-x-1">
405 <span>Amount</span>
406 <div class="sort-indicator">
407 <i class="fas fa-sort text-gray-400"></i>
408 </div>
409 </div>
410 </th>
411 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="method">
412 <div class="flex items-center space-x-1">
413 <span>Method</span>
414 <div class="sort-indicator">
415 <i class="fas fa-sort text-gray-400"></i>
416 </div>
417 </div>
418 </th>
419 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="status">
420 <div class="flex items-center space-x-1">
421 <span>Status</span>
422 <div class="sort-indicator">
423 <i class="fas fa-sort text-gray-400"></i>
424 </div>
425 </div>
426 </th>
427 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="date">
428 <div class="flex items-center space-x-1">
429 <span>Date</span>
430 <div class="sort-indicator">
431 <i class="fas fa-sort text-gray-400"></i>
432 </div>
433 </div>
434 </th>
435 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100 hidden sm:table-cell" data-sort="type">
436 <div class="flex items-center space-x-1">
437 <span>Type</span>
438 <div class="sort-indicator">
439 <i class="fas fa-sort text-gray-400"></i>
440 </div>
441 </div>
442 </th>
443 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
444 Actions
445 </th>
446 </tr>
447 </thead>
448 <tbody class="bg-white divide-y divide-gray-200">
449 <?php if ($payments): ?>
450 <?php foreach ($payments as $payment): ?>
451 <?php
452 // $payment is already a Payment object, no need to create new one
453
454 // Get invoice information
455 $invoice_id = $payment->getInvoiceId();
456
457 // Temporarily show all payments regardless of invoice
458 ?>
459 <tr>
460 <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
461 <input type="checkbox" name="payment_ids[]" value="<?php echo $payment->getId(); ?>" form="bulk-action-form" class="payment-checkbox rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
462 </td>
463 <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
464 #<?php echo $payment->getId(); ?>
465 </td>
466 <td class="px-6 py-4 text-sm text-gray-500">
467 <?php if ($invoice_id): ?>
468 <?php
469 $invoice_post = get_post($invoice_id);
470 if ($invoice_post && $invoice_post->post_type === 'easy_invoice'):
471 $invoice = new \EasyInvoice\Models\Invoice($invoice_id);
472 ?>
473 <div>
474 <a href="<?php echo get_permalink($invoice->getId()); ?>" class="text-indigo-600 hover:text-indigo-900 font-medium" target="_blank">
475 <?php echo $invoice->getNumber(); ?>
476 </a>
477 <div class="text-xs text-gray-400 mt-1">
478 <?php echo esc_html($invoice->getTitle() ?: __('Untitled Invoice', 'easy-invoice')); ?>
479 </div>
480 </div>
481 <?php else: ?>
482 <span class="text-gray-400">
483 <?php _e('Invoice not found', 'easy-invoice'); ?>
484 <?php if (current_user_can('manage_options')): ?>
485 <br><small class="text-xs text-gray-500">ID: <?php echo $invoice_id; ?> (Type: <?php echo $invoice_post ? $invoice_post->post_type : 'null'; ?>)</small>
486 <?php endif; ?>
487 </span>
488 <?php endif; ?>
489 <?php else: ?>
490 <span class="text-gray-400">
491 <?php _e('No invoice ID', 'easy-invoice'); ?>
492 </span>
493 <?php endif; ?>
494 </td>
495 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
496 <?php echo $payment->getCurrencySymbol() . number_format($payment->getAmount(), 2); ?>
497 </td>
498 <td class="px-6 py-4 text-sm text-gray-500">
499 <?php
500 // Get payment method label dynamically from registered gateways
501 $payment_method = $payment->getPaymentMethod();
502 $gateway_manager = \EasyInvoice\EasyInvoice::getInstance()->getGatewayManager();
503 $gateways = $gateway_manager->getGateways();
504
505 // Try to get the gateway title from registered gateways
506 $method_label = ucfirst(easy_invoice_str_replace('_', ' ', $payment_method)); // Default fallback
507
508 foreach ($gateways as $gateway) {
509 if ($gateway->getName() === $payment_method) {
510 $method_label = $gateway_manager->getGatewayDisplayName($gateway->getName());
511 break;
512 }
513 }
514
515 // Special case for manual payments
516 if ($payment_method === 'manual') {
517 $method_label = __('Manual', 'easy-invoice');
518 }
519
520 echo esc_html($method_label);
521 ?>
522 </td>
523 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
524 <?php
525 $status = $payment->getStatus();
526 $status_class = '';
527 $status_text = '';
528
529 switch ($status) {
530 case 'completed':
531 $status_class = 'bg-green-100 text-green-800';
532 $status_text = __('Completed', 'easy-invoice');
533 break;
534 case 'pending':
535 $status_class = 'bg-yellow-100 text-yellow-800';
536 $status_text = __('Pending', 'easy-invoice');
537 break;
538 case 'failed':
539 $status_class = 'bg-red-100 text-red-800';
540 $status_text = __('Failed', 'easy-invoice');
541 break;
542 default:
543 $status_class = 'bg-gray-100 text-gray-800';
544 $status_text = ucfirst($status);
545 }
546 ?>
547 <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium <?php echo $status_class; ?>">
548 <?php echo $status_text; ?>
549 </span>
550 </td>
551 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
552 <?php echo $payment->getPaymentDate() ? date('M j, Y', strtotime($payment->getPaymentDate())) : date('M j, Y', strtotime($payment->getPost()->post_date)); ?>
553 </td>
554 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 hidden sm:table-cell">
555 <?php echo ucfirst($payment->getPaymentType() ?: 'one-time'); ?>
556 </td>
557 <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
558 <div class="flex items-center space-x-2">
559 <a href="?page=easy-invoice-payments&action=view&id=<?php echo $payment->getId(); ?>" class="text-indigo-600 hover:text-indigo-900">
560 <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
561 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
562 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
563 </svg>
564 </a>
565 <a href="?page=easy-invoice-payments&action=edit&id=<?php echo $payment->getId(); ?>" class="text-blue-600 hover:text-blue-900">
566 <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
567 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
568 </svg>
569 </a>
570 <?php if (in_array($status, ['pending', 'pending-bank', 'pending-cheque'])): ?>
571 <button type="button" class="approve-payment-btn text-green-600 hover:text-green-900"
572 data-payment-id="<?php echo $payment->getId(); ?>"
573 data-invoice-id="<?php echo $payment->getInvoiceId(); ?>"
574 data-nonce="<?php echo wp_create_nonce('easy_invoice_approve_payment'); ?>">
575 <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
576 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
577 </svg>
578 </button>
579 <?php endif; ?>
580
581 <?php
582 // Hook for additional payment actions (used by Pro plugin for receipts)
583 do_action('easy_invoice_payment_row_actions', $payment, $status);
584 ?>
585 </div>
586 </td>
587 </tr>
588 <?php endforeach; ?>
589 <?php else : ?>
590 <tr>
591 <td colspan="9" class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center">
592 <?php _e('No payments found.', 'easy-invoice'); ?>
593 </td>
594 </tr>
595 <?php endif; ?>
596 </tbody>
597 </table>
598 </div>
599 </div>
600
601 <!-- Bottom Pagination -->
602 <?php if ($total_payments > 0): ?>
603 <div class="mt-4">
604 <div class="px-4 py-3 flex items-center justify-between">
605 <div class="flex items-center space-x-2">
606 <span class="text-sm text-gray-700">
607 Showing
608 <span class="font-medium"><?php echo number_format((($current_page - 1) * $per_page) + 1); ?></span>
609 to
610 <span class="font-medium"><?php echo number_format(min($current_page * $per_page, $total_payments)); ?></span>
611 of
612 <span class="font-medium"><?php echo number_format($total_payments); ?></span>
613 results
614 </span>
615 </div>
616 <?php if ($total_pages > 1): ?>
617 <div class="flex items-center space-x-2">
618 <span class="text-sm text-gray-500">Page <?php echo number_format($current_page); ?> of <?php echo number_format($total_pages); ?></span>
619 <?php
620 // Use WordPress's built-in pagination for bottom
621 $bottom_pagination_args = array(
622 'base' => add_query_arg('paged', '%#%'),
623 'format' => '',
624 'current' => $current_page,
625 'total' => $total_pages,
626 'prev_text' => '‹ Previous',
627 'next_text' => 'Next ›',
628 'type' => 'array',
629 'end_size' => 1,
630 'mid_size' => 2,
631 'add_args' => array(
632 'page' => 'easy-invoice-payments',
633 'view' => $current_view,
634 'status' => $status_filter
635 )
636 );
637
638 $bottom_pagination_links = paginate_links($bottom_pagination_args);
639
640 if ($bottom_pagination_links) {
641 echo '<div class="flex space-x-1">';
642 foreach ($bottom_pagination_links as $link) {
643 // Add null check to prevent passing null to easy_invoice_str_replace
644 if ($link === null) {
645 continue;
646 }
647
648 // Convert WordPress pagination to our styling
649 $link = easy_invoice_str_replace('page-numbers', 'px-3 py-2 text-sm font-medium border border-gray-300 rounded-md', $link);
650 $link = easy_invoice_str_replace('current', 'bg-indigo-50 border-indigo-500 text-indigo-600', $link);
651 $link = easy_invoice_str_replace('prev', 'bg-white text-gray-500 hover:bg-gray-50', $link);
652 $link = easy_invoice_str_replace('next', 'bg-white text-gray-500 hover:bg-gray-50', $link);
653 $link = easy_invoice_str_replace('dots', 'bg-white text-gray-700', $link);
654
655 // Add default styling for regular page numbers
656 if ($link && strpos($link, 'bg-indigo-50') === false && strpos($link, 'bg-white') === false) {
657 $link = easy_invoice_str_replace('border-gray-300', 'border-gray-300 bg-white text-gray-500 hover:bg-gray-50', $link);
658 }
659
660 echo $link;
661 }
662 echo '</div>';
663 }
664 ?>
665 </div>
666 <?php endif; ?>
667 </div>
668 </div>
669 <?php endif; ?>
670 </div>
671
672 <!-- Approval Modal -->
673 <div id="payment-approval-modal" class="fixed inset-0 z-50 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
674 <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
675 <!-- Background overlay -->
676 <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
677
678 <!-- Modal panel -->
679 <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
680 <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
681 <div class="sm:flex sm:items-start">
682 <div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
683 <svg class="h-6 w-6 text-green-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
684 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
685 </svg>
686 </div>
687 <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
688 <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
689 <?php _e('Approve Payment', 'easy-invoice'); ?>
690 </h3>
691 <div class="mt-2">
692 <p class="text-sm text-gray-500">
693 <?php _e('You are about to approve this payment. This will mark the invoice as paid and update the payment records.', 'easy-invoice'); ?>
694 </p>
695 <div class="mt-4">
696 <label for="approval-notes" class="block text-sm font-medium text-gray-700">
697 <?php _e('Notes (optional)', 'easy-invoice'); ?>
698 </label>
699 <textarea id="approval-notes" name="notes" rows="3" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="<?php _e('Add any notes about this payment approval...', 'easy-invoice'); ?>"></textarea>
700 </div>
701 </div>
702 </div>
703 </div>
704 </div>
705 <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
706 <button type="button" id="confirm-approve-btn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-600 text-base font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:ml-3 sm:w-auto sm:text-sm">
707 <?php _e('Approve Payment', 'easy-invoice'); ?>
708 </button>
709 <button type="button" id="cancel-approve-btn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
710 <?php _e('Cancel', 'easy-invoice'); ?>
711 </button>
712 </div>
713 </div>
714 </div>
715 </div>
716
717 <!-- Notification area for AJAX responses -->
718 <div id="payment-approve-notification" class="fixed top-0 right-0 m-4 hidden">
719 <!-- Content will be injected via JavaScript -->
720 </div>
721
722 <style>
723 /* Add any additional custom styles here */
724 .ei-table-responsive{
725 width: 100%;
726 max-width: 100%;
727 overflow-x: auto;
728 -webkit-overflow-scrolling: touch;
729 }
730 .ei-payments-table{
731 width: 100%;
732 min-width: 900px;
733 }
734 @media (max-width: 640px) {
735 .ei-payments-table th,
736 .ei-payments-table td{
737 padding-left: 0.75rem !important;
738 padding-right: 0.75rem !important;
739 }
740 }
741 .payment-status {
742 display: inline-block;
743 padding: 3px 8px;
744 border-radius: 3px;
745 font-size: 12px;
746 font-weight: 600;
747 }
748 .status-completed {
749 background-color: #dff0d8;
750 color: #3c763d;
751 }
752 .status-pending {
753 background-color: #fcf8e3;
754 color: #8a6d3b;
755 }
756 .status-failed {
757 background-color: #f2dede;
758 color: #a94442;
759 }
760 </style>
761
762 <script>
763 // Define ajaxurl for AJAX requests
764 var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
765
766 jQuery(document).ready(function($) {
767 // Variables to store the current payment being approved
768 let currentInvoiceId = null;
769 let currentPaymentId = null;
770 let currentNonce = null;
771
772 // Handle Approve button click
773 $('.approve-payment-btn').on('click', function(e) {
774 e.preventDefault();
775
776 // Store the data for the current payment
777 currentInvoiceId = $(this).data('invoice-id');
778 currentPaymentId = $(this).data('payment-id');
779 currentNonce = $(this).data('nonce');
780
781 // Show the approval modal
782 $('#payment-approval-modal').removeClass('hidden');
783 });
784
785 // Handle Cancel button in modal
786 $('#cancel-approve-btn').on('click', function() {
787 // Hide the modal and reset the form
788 $('#payment-approval-modal').addClass('hidden');
789 $('#approval-notes').val('');
790 });
791
792 // Handle Confirm Approve button in modal
793 $('#confirm-approve-btn').on('click', function() {
794 // Get the notes from the textarea
795 const notes = $('#approval-notes').val();
796
797 // Disable the button to prevent double clicks
798 $(this).prop('disabled', true).text('Processing...');
799
800 // Make AJAX request to approve the payment
801 $.ajax({
802 url: ajaxurl,
803 type: 'POST',
804 data: {
805 action: 'easy_invoice_approve_payment',
806 invoice_id: currentInvoiceId,
807 nonce: currentNonce,
808 notes: notes
809 },
810 success: function(response) {
811 // Hide the modal
812 $('#payment-approval-modal').addClass('hidden');
813
814 if (response.success) {
815 // Show success toast
816 if (typeof EasyInvoiceToast !== 'undefined') {
817 EasyInvoiceToast.success('Payment approved successfully.');
818 }
819
820 // Refresh the page after a short delay
821 setTimeout(function() {
822 location.reload();
823 }, 1500);
824 } else {
825 // Show error toast
826 if (typeof EasyInvoiceToast !== 'undefined') {
827 EasyInvoiceToast.error('Failed to approve payment.');
828 }
829
830 // Re-enable the button
831 $('#confirm-approve-btn').prop('disabled', false).text('Approve Payment');
832 }
833 },
834 error: function() {
835 // Hide the modal
836 $('#payment-approval-modal').addClass('hidden');
837
838 // Show error toast
839 if (typeof EasyInvoiceToast !== 'undefined') {
840 EasyInvoiceToast.error('Server error occurred. Please try again.');
841 }
842
843 // Re-enable the button
844 $('#confirm-approve-btn').prop('disabled', false).text('Approve Payment');
845 }
846 });
847 });
848
849
850
851 // Close the modal if clicking outside of it
852 $(window).on('click', function(e) {
853 if ($(e.target).is('#payment-approval-modal')) {
854 $('#payment-approval-modal').addClass('hidden');
855 $('#approval-notes').val('');
856 }
857 });
858
859 // Close the modal with Escape key
860 $(document).on('keydown', function(e) {
861 if (e.key === "Escape" && !$('#payment-approval-modal').hasClass('hidden')) {
862 $('#payment-approval-modal').addClass('hidden');
863 $('#approval-notes').val('');
864 }
865 });
866
867 // Dismiss notification buttons
868 $('.notification-dismiss').on('click', function() {
869 $(this).closest('.rounded-md').remove();
870 });
871
872 // Payment Table Sorting and Filtering Functionality
873 let currentSort = { column: '', direction: '' };
874
875 // Initialize sorting and filtering
876 function initSortingAndFiltering() {
877 // Add click handlers to sortable headers
878 $('th[data-sort]').on('click', function() {
879 const column = $(this).data('sort');
880 const currentDirection = currentSort.column === column ? currentSort.direction : 'desc';
881 const newDirection = currentDirection === 'asc' ? 'desc' : 'asc';
882
883 currentSort = { column: column, direction: newDirection };
884 updateSortIndicator(column, newDirection);
885 sortTable(column, newDirection);
886 });
887 }
888
889 // Update sort indicator
890 function updateSortIndicator(activeColumn, direction) {
891 // Reset all indicators
892 $('.sort-indicator i').removeClass('fa-sort-up fa-sort-down').addClass('fa-sort text-gray-400');
893
894 // Set active indicator
895 $(`th[data-sort="${activeColumn}"] .sort-indicator i`)
896 .removeClass('fa-sort text-gray-400')
897 .addClass(direction === 'asc' ? 'fa-sort-up text-indigo-600' : 'fa-sort-down text-indigo-600');
898 }
899
900 // Sort table function
901 function sortTable(column, direction) {
902 const tbody = $('tbody');
903 const rows = tbody.find('tr').toArray();
904
905 rows.sort(function(a, b) {
906 let aValue, bValue;
907
908 switch(column) {
909 case 'id':
910 aValue = parseInt($(a).find('td:first-child').text().replace('#', ''));
911 bValue = parseInt($(b).find('td:first-child').text().replace('#', ''));
912 break;
913 case 'invoice':
914 aValue = $(a).find('td:nth-child(2) a').text().toLowerCase();
915 bValue = $(b).find('td:nth-child(2) a').text().toLowerCase();
916 break;
917 case 'amount':
918 aValue = parseFloat($(a).find('td:nth-child(3)').text().replace(/[^0-9.-]+/g, ''));
919 bValue = parseFloat($(b).find('td:nth-child(3)').text().replace(/[^0-9.-]+/g, ''));
920 break;
921 case 'method':
922 aValue = $(a).find('td:nth-child(4)').text().toLowerCase();
923 bValue = $(b).find('td:nth-child(4)').text().toLowerCase();
924 break;
925 case 'status':
926 aValue = $(a).find('td:nth-child(5) span').text().toLowerCase();
927 bValue = $(b).find('td:nth-child(5) span').text().toLowerCase();
928 break;
929 case 'date':
930 aValue = new Date($(a).find('td:nth-child(6)').text());
931 bValue = new Date($(b).find('td:nth-child(6)').text());
932 break;
933 case 'type':
934 aValue = $(a).find('td:nth-child(7)').text().toLowerCase();
935 bValue = $(b).find('td:nth-child(7)').text().toLowerCase();
936 break;
937 default:
938 return 0;
939 }
940
941 if (direction === 'asc') {
942 return aValue > bValue ? 1 : -1;
943 } else {
944 return aValue < bValue ? 1 : -1;
945 }
946 });
947
948 // Reorder rows with animation
949 tbody.find('tr').fadeOut(200, function() {
950 tbody.empty();
951 $.each(rows, function(index, row) {
952 tbody.append(row);
953 });
954 tbody.find('tr').fadeIn(200);
955 });
956 }
957
958 // Initialize sorting and filtering
959 initSortingAndFiltering();
960
961 // Payment Delete Functionality
962 let selectedPayments = [];
963
964 // Handle select all checkbox
965 $('#select-all-payments').on('change', function() {
966 const isChecked = $(this).is(':checked');
967 $('.payment-checkbox').prop('checked', isChecked);
968
969 if (isChecked) {
970 selectedPayments = $('.payment-checkbox').map(function() {
971 return $(this).val();
972 }).get();
973 } else {
974 selectedPayments = [];
975 }
976
977 updateBulkActionButton();
978 });
979
980 // Handle individual checkboxes
981 $(document).on('change', '.payment-checkbox', function() {
982 const paymentId = $(this).val();
983 const isChecked = $(this).is(':checked');
984
985 if (isChecked) {
986 if (!selectedPayments.includes(paymentId)) {
987 selectedPayments.push(paymentId);
988 }
989 } else {
990 selectedPayments = selectedPayments.filter(id => id !== paymentId);
991 }
992
993 // Update select all checkbox
994 const totalCheckboxes = $('.payment-checkbox').length;
995 const checkedCheckboxes = $('.payment-checkbox:checked').length;
996
997 if (checkedCheckboxes === 0) {
998 $('#select-all-payments').prop('checked', false).prop('indeterminate', false);
999 } else if (checkedCheckboxes === totalCheckboxes) {
1000 $('#select-all-payments').prop('checked', true).prop('indeterminate', false);
1001 } else {
1002 $('#select-all-payments').prop('checked', false).prop('indeterminate', true);
1003 }
1004
1005 updateBulkActionButton();
1006 });
1007
1008 // Update bulk action button state
1009 function updateBulkActionButton() {
1010 const button = $('#bulk-action-form button[type="submit"]');
1011 const countSpan = $('#selected-count');
1012
1013 if (selectedPayments.length > 0) {
1014 button.prop('disabled', false);
1015 countSpan.text(selectedPayments.length);
1016 } else {
1017 button.prop('disabled', true);
1018 countSpan.text('0');
1019 }
1020 }
1021
1022 // Form submission validation for bulk actions
1023 $("#bulk-action-form").on("submit", function(e) {
1024 e.preventDefault();
1025
1026 var bulkAction = $("select[name='bulk_action']").val();
1027 if (!bulkAction) {
1028 EasyInvoiceToast.error('Please select a bulk action.');
1029 return;
1030 }
1031
1032 if (selectedPayments.length === 0) {
1033 EasyInvoiceToast.error('Please select at least one payment.');
1034 return;
1035 }
1036
1037 // Confirm bulk actions
1038 if (bulkAction === 'trash') {
1039 EasyInvoiceConfirmation.confirmAction('trash', selectedPayments.length + ' payment(s)', function() {
1040 $("#bulk-action-form")[0].submit();
1041 });
1042 return;
1043 } else if (bulkAction === 'delete') {
1044 EasyInvoiceConfirmation.confirmAction('delete', selectedPayments.length + ' payment(s)', function() {
1045 $("#bulk-action-form")[0].submit();
1046 });
1047 return;
1048 } else if (bulkAction === 'restore') {
1049 EasyInvoiceConfirmation.confirmAction('restore', selectedPayments.length + ' payment(s)', function() {
1050 $("#bulk-action-form")[0].submit();
1051 });
1052 return;
1053 } else {
1054 $("#bulk-action-form")[0].submit();
1055 }
1056 });
1057 });
1058 </script>