| @@ -38,17 +38,17 @@ | ||
| 38 | 38 | $text_class = 'text-blue-800'; |
| 39 | 39 | $icon = '<svg class="h-5 w-5 text-blue-400" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>'; |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | - echo '<div class="rounded-md ' . $bg_class . ' p-4 mb-4">'; | |
| 42 | + echo '<div class="rounded-md ' . esc_html($bg_class) . ' p-4 mb-4">'; | |
| 43 | 43 | echo '<div class="flex">'; |
| 44 | - echo '<div class="flex-shrink-0">' . $icon . '</div>'; | |
| 44 | + echo '<div class="flex-shrink-0">' . wp_kses_post($icon) . '</div>'; | |
| 45 | 45 | echo '<div class="ml-3">'; |
| 46 | - echo '<p class="text-sm font-medium ' . $text_class . '">' . $message . '</p>'; | |
| 46 | + echo '<p class="text-sm font-medium ' . esc_html($text_class) . '">' . esc_html($message) . '</p>'; | |
| 47 | 47 | echo '</div>'; |
| 48 | 48 | echo '<div class="ml-auto pl-3">'; |
| 49 | 49 | echo '<div class="-mx-1.5 -my-1.5">'; |
| 50 | - echo '<button type="button" class="inline-flex rounded-md p-1.5 ' . $text_class . ' hover:bg-green-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 notification-dismiss">'; | |
| 50 | + echo '<button type="button" class="inline-flex rounded-md p-1.5 ' . esc_html($text_class) . ' hover:bg-green-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 notification-dismiss">'; | |
| 51 | 51 | echo '<span class="sr-only">Dismiss</span>'; |
| 52 | 52 | echo '<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">'; |
| 53 | 53 | echo '<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />'; |
| 54 | 54 | echo '</svg>'; |
| @@ -68,9 +68,10 @@ | ||
| 68 | 68 | if ($updated_count > 0) { |
| 69 | 69 | // Show a one-time notification |
| 70 | 70 | add_action('admin_notices', function() use ($updated_count) { |
| 71 | 71 | echo '<div class="notice notice-success is-dismissible">'; |
| 72 | - echo '<p>' . sprintf(__('%d draft invoices updated to published status for proper permalinks.', 'easy-invoice'), $updated_count) . '</p>'; | |
| 72 | + /* translators: %d: number updated. */ | |
| 73 | + echo '<p>' . sprintf(esc_html__('%d draft invoices updated to published status for proper permalinks.', 'easy-invoice'), (int) $updated_count) . '</p>'; | |
| 73 | 74 | echo '</div>'; |
| 74 | 75 | }); |
| 75 | 76 | } |
| 76 | 77 | |
| @@ -95,8 +96,9 @@ | ||
| 95 | 96 | $notification = false; |
| 96 | 97 | |
| 97 | 98 | if (isset($_GET['bulk_trashed']) && $_GET['bulk_trashed'] > 0) { |
| 98 | 99 | $count = intval($_GET['bulk_trashed']); |
| 100 | + /* translators: %s: number of items. */ | |
| 99 | 101 | easy_invoice_display_notification('success', sprintf(_n('%s invoice moved to trash.', '%s invoices moved to trash.', $count, 'easy-invoice'), $count)); |
| 100 | 102 | $notification = true; |
| 101 | 103 | } |
| 102 | 104 | |
| @@ -101,8 +103,9 @@ | ||
| 101 | 103 | } |
| 102 | 104 | |
| 103 | 105 | if (isset($_GET['bulk_restored']) && $_GET['bulk_restored'] > 0) { |
| 104 | 106 | $count = intval($_GET['bulk_restored']); |
| 107 | + /* translators: %s: number of items. */ | |
| 105 | 108 | easy_invoice_display_notification('success', sprintf(_n('%s invoice restored from trash.', '%s invoices restored from trash.', $count, 'easy-invoice'), $count)); |
| 106 | 109 | $notification = true; |
| 107 | 110 | } |
| 108 | 111 | |
| @@ -107,8 +110,9 @@ | ||
| 107 | 110 | } |
| 108 | 111 | |
| 109 | 112 | if (isset($_GET['bulk_deleted']) && $_GET['bulk_deleted'] > 0) { |
| 110 | 113 | $count = intval($_GET['bulk_deleted']); |
| 114 | + /* translators: %s: number of items. */ | |
| 111 | 115 | easy_invoice_display_notification('success', sprintf(_n('%s invoice permanently deleted.', '%s invoices permanently deleted.', $count, 'easy-invoice'), $count)); |
| 112 | 116 | $notification = true; |
| 113 | 117 | } |
| 114 | 118 | |
| @@ -113,8 +117,9 @@ | ||
| 113 | 117 | } |
| 114 | 118 | |
| 115 | 119 | if (isset($_GET['bulk_drafted']) && $_GET['bulk_drafted'] > 0) { |
| 116 | 120 | $count = intval($_GET['bulk_drafted']); |
| 121 | + /* translators: %s: number of items. */ | |
| 117 | 122 | easy_invoice_display_notification('success', sprintf(_n('%s invoice set to draft status.', '%s invoices set to draft status.', $count, 'easy-invoice'), $count)); |
| 118 | 123 | $notification = true; |
| 119 | 124 | } |
| 120 | 125 | |
| @@ -119,8 +124,9 @@ | ||
| 119 | 124 | } |
| 120 | 125 | |
| 121 | 126 | if (isset($_GET['bulk_published']) && $_GET['bulk_published'] > 0) { |
| 122 | 127 | $count = intval($_GET['bulk_published']); |
| 128 | + /* translators: %s: number of items. */ | |
| 123 | 129 | easy_invoice_display_notification('success', sprintf(_n('%s invoice published successfully.', '%s invoices published successfully.', $count, 'easy-invoice'), $count)); |
| 124 | 130 | $notification = true; |
| 125 | 131 | } |
| 126 | 132 | |
| @@ -160,29 +166,30 @@ | ||
| 160 | 166 | // Get stats from all invoices, not just the current page |
| 161 | 167 | $invoice_controller = new \EasyInvoice\Controllers\InvoiceController(); |
| 162 | 168 | $stats = $invoice_controller->getInvoiceStats(); |
| 163 | 169 | |
| 164 | -// Add total invoices count from current page for display purposes | |
| 165 | -$stats['total_invoices'] = count($formatted_invoices); | |
| 170 | +// The controller passes the real counts (found_posts and SQL counts); the | |
| 171 | +// template used to overwrite the total with the size of the current page and | |
| 172 | +// load every trashed / draft invoice as a model just to count them. | |
| 173 | +$all_count = (int) ($stats['total_invoices'] ?? 0); | |
| 174 | +if (!isset($trash_count)) { | |
| 175 | + $trash_count = (int) $repository->count(['post_status' => 'trash']); | |
| 176 | +} | |
| 177 | +if (!isset($draft_count)) { | |
| 178 | + $draft_count = (int) $repository->count(['meta_key' => '_easy_invoice_status', 'meta_value' => 'draft']); // phpcs:ignore WordPress.DB.SlowDBQuery | |
| 179 | +} | |
| 166 | 180 | |
| 167 | -// Get trash count for tab display | |
| 168 | -$trash_args = ['post_status' => 'trash']; | |
| 169 | -$trash_invoices = $repository->all($trash_args); | |
| 170 | -$trash_count = count($trash_invoices); | |
| 171 | - | |
| 172 | -// Get draft count for tab display | |
| 173 | -$draft_args = ['post_status' => 'draft']; | |
| 174 | -$draft_invoices = $repository->all($draft_args); | |
| 175 | -$draft_count = count($draft_invoices); | |
| 176 | - | |
| 177 | 181 | // Define available status filters |
| 182 | +// The statuses an invoice can actually hold — "Pending" was offered but no | |
| 183 | +// invoice is ever in that state, while "Available" (every new invoice) was not. | |
| 178 | 184 | $status_filters = array( |
| 179 | - 'paid' => 'Paid', | |
| 180 | - 'unpaid' => 'Unpaid', | |
| 181 | - 'pending' => 'Pending', | |
| 182 | - 'draft' => 'Draft', | |
| 183 | - 'overdue' => 'Overdue', | |
| 184 | - 'cancelled' => 'Cancelled' | |
| 185 | + 'available' => __('Available', 'easy-invoice'), | |
| 186 | + 'paid' => __('Paid', 'easy-invoice'), | |
| 187 | + 'partial' => __('Partially paid', 'easy-invoice'), | |
| 188 | + 'unpaid' => __('Unpaid', 'easy-invoice'), | |
| 189 | + 'overdue' => __('Overdue', 'easy-invoice'), | |
| 190 | + 'draft' => __('Draft', 'easy-invoice'), | |
| 191 | + 'cancelled' => __('Cancelled', 'easy-invoice'), | |
| 185 | 192 | ); |
| 186 | 193 | |
| 187 | 194 | ?> |
| 188 | 195 | <div class="p-8"> |
| @@ -188,28 +195,43 @@ | ||
| 188 | 195 | <div class="p-8"> |
| 189 | 196 | <div class="ei-app-page-header bg-white border-b border-gray-200 px-6" style="margin-left: -2rem; margin-top: -2rem; padding-left:2rem; padding-right:2rem; margin-right: -2rem;"> |
| 190 | 197 | <div class="flex items-center justify-between"> |
| 191 | 198 | <div> |
| 192 | - <h1 class="text-2xl font-bold text-gray-900"><?php _e('Invoices', 'easy-invoice'); ?></h1> | |
| 193 | - <p class="mt-1 text-sm text-gray-500"><?php _e('Manage and track your invoices', 'easy-invoice'); ?></p> | |
| 199 | + <h1 class="text-2xl font-bold text-gray-900"><?php esc_html_e('Invoices', 'easy-invoice'); ?></h1> | |
| 200 | + <p class="mt-1 text-sm text-gray-500"><?php esc_html_e('Manage and track your invoices', 'easy-invoice'); ?></p> | |
| 194 | 201 | </div> |
| 195 | 202 | <div class="flex items-center space-x-3"> |
| 196 | 203 | <?php if (isset($_GET['rewrite_flushed'])): ?> |
| 197 | 204 | <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-2 rounded-md text-sm"> |
| 198 | - <?php _e('Rewrite rules flushed successfully!', 'easy-invoice'); ?> | |
| 205 | + <?php esc_html_e('Rewrite rules flushed successfully!', 'easy-invoice'); ?> | |
| 199 | 206 | </div> |
| 200 | 207 | <?php endif; ?> |
| 201 | 208 | |
| 202 | 209 | <?php if (isset($_GET['post_types_registered'])): ?> |
| 203 | 210 | <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-2 rounded-md text-sm"> |
| 204 | - <?php _e('Post types registered successfully!', 'easy-invoice'); ?> | |
| 211 | + <?php esc_html_e('Post types registered successfully!', 'easy-invoice'); ?> | |
| 205 | 212 | </div> |
| 206 | 213 | <?php endif; ?> |
| 207 | 214 | |
| 208 | - <a href="<?php echo wp_nonce_url(admin_url('admin-post.php?action=flush_easy_invoice_rewrite_rules'), 'flush_easy_invoice_rewrite_rules'); ?>" | |
| 215 | + <?php | |
| 216 | + // "Flush Rewrite Rules" is a troubleshooting action, not something a | |
| 217 | + // user does as part of their job — but it rendered unconditionally as | |
| 218 | + // a prominent button right beside the primary "Create New Invoice" CTA | |
| 219 | + // on every admin's screen. It is now hidden by default and shown when | |
| 220 | + // WP_DEBUG is on, or when a site opts in via the filter. | |
| 221 | + // | |
| 222 | + // Kept rather than deleted because it is the manual escape hatch if | |
| 223 | + // invoice permalinks ever 404. | |
| 224 | + $ei_show_maintenance_tools = apply_filters( | |
| 225 | + 'easy_invoice_show_maintenance_tools', | |
| 226 | + defined('WP_DEBUG') && WP_DEBUG | |
| 227 | + ); | |
| 228 | + if ($ei_show_maintenance_tools) : ?> | |
| 229 | + <a href="<?php echo esc_url(wp_nonce_url(admin_url('admin-post.php?action=flush_easy_invoice_rewrite_rules'), 'flush_easy_invoice_rewrite_rules')); ?>" | |
| 209 | 230 | class="bg-yellow-100 text-yellow-700 hover:bg-yellow-200 px-4 py-2 rounded-md text-sm font-medium transition-colors duration-200"> |
| 210 | - <?php _e('Flush Rewrite Rules', 'easy-invoice'); ?> | |
| 231 | + <?php esc_html_e('Flush Rewrite Rules', 'easy-invoice'); ?> | |
| 211 | 232 | </a> |
| 233 | + <?php endif; ?> | |
| 212 | 234 | |
| 213 | 235 | <?php |
| 214 | 236 | // "Export All" is part of the bulk_operations addon |
| 215 | 237 | // (Personal tier). Gate three states: |
| @@ -220,14 +242,14 @@ | ||
| 220 | 242 | ?> |
| 221 | 243 | <?php if ($ei_bulk_ops_loaded): ?> |
| 222 | 244 | <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;"> |
| 223 | 245 | <input type="hidden" name="action" value="easy_invoice_export_all_invoices" /> |
| 224 | - <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('easy_invoice_export_all_invoices'); ?>" /> | |
| 246 | + <input type="hidden" name="_wpnonce" value="<?php echo esc_attr(wp_create_nonce('easy_invoice_export_all_invoices')); ?>" /> | |
| 225 | 247 | <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"> |
| 226 | 248 | <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"> |
| 227 | 249 | <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> |
| 228 | 250 | </svg> |
| 229 | - <?php _e('Export All', 'easy-invoice'); ?> | |
| 251 | + <?php esc_html_e('Export All', 'easy-invoice'); ?> | |
| 230 | 252 | </button> |
| 231 | 253 | </form> |
| 232 | 254 | <?php elseif (!easy_invoice_has_pro()): ?> |
| 233 | 255 | <button type="button" id="export-all-invoices-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"> |
| @@ -233,9 +255,9 @@ | ||
| 233 | 255 | <button type="button" id="export-all-invoices-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"> |
| 234 | 256 | <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"> |
| 235 | 257 | <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> |
| 236 | 258 | </svg> |
| 237 | - <?php _e('Export All', 'easy-invoice'); ?> | |
| 259 | + <?php esc_html_e('Export All', 'easy-invoice'); ?> | |
| 238 | 260 | <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"> |
| 239 | 261 | <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"/> |
| 240 | 262 | </svg> |
| 241 | 263 | </button> |
| @@ -251,14 +273,16 @@ | ||
| 251 | 273 | }); |
| 252 | 274 | }); |
| 253 | 275 | </script> |
| 254 | 276 | <?php endif; ?> |
| 255 | - <a href="#" id="create-new-invoice-btn" 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"> | |
| 277 | + <?php if (easy_invoice_user_can('ei_create_invoice')) : ?> | |
| 278 | +<a href="#" id="create-new-invoice-btn" 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"> | |
| 256 | 279 | <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> |
| 257 | 280 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path> |
| 258 | 281 | </svg> |
| 259 | - <?php _e('Create New Invoice', 'easy-invoice'); ?> | |
| 282 | + <?php esc_html_e('Create New Invoice', 'easy-invoice'); ?> | |
| 260 | 283 | </a> |
| 284 | +<?php endif; ?> | |
| 261 | 285 | </div> |
| 262 | 286 | </div> |
| 263 | 287 | </div> |
| 264 | 288 | |
| @@ -270,10 +294,10 @@ | ||
| 270 | 294 | <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> |
| 271 | 295 | </svg> |
| 272 | 296 | </div> |
| 273 | 297 | <div> |
| 274 | - <h3 class="text-sm font-medium text-gray-500">Total Invoices</h3> | |
| 275 | - <p class="mt-1 text-2xl font-bold text-gray-900"><?php echo $stats['total_invoices']; ?></p> | |
| 298 | + <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e('Total Invoices', 'easy-invoice'); ?></h3> | |
| 299 | + <p class="mt-1 text-2xl font-bold text-gray-900"><?php echo esc_html($stats['total_invoices']); ?></p> | |
| 276 | 300 | </div> |
| 277 | 301 | </div> |
| 278 | 302 | </div> |
| 279 | 303 | <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1"> |
| @@ -283,9 +307,9 @@ | ||
| 283 | 307 | <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> |
| 284 | 308 | </svg> |
| 285 | 309 | </div> |
| 286 | 310 | <div> |
| 287 | - <h3 class="text-sm font-medium text-gray-500">Total Revenue</h3> | |
| 311 | + <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e('Total Revenue', 'easy-invoice'); ?></h3> | |
| 288 | 312 | <?php if (is_array($stats['total_revenue']) && !empty($stats['total_revenue'])): ?> |
| 289 | 313 | <div class="mt-1"> |
| 290 | 314 | <?php foreach ($stats['total_revenue'] as $currency => $data): ?> |
| 291 | 315 | <?php |
| @@ -294,10 +318,10 @@ | ||
| 294 | 318 | $temp_invoice->setCurrencyCode($currency); |
| 295 | 319 | $formatter = new \EasyInvoice\Helpers\InvoiceFormatter($temp_invoice); |
| 296 | 320 | ?> |
| 297 | 321 | <p class="text-lg font-bold text-gray-900"> |
| 298 | - <?php echo $formatter->format($data['amount']); ?> | |
| 299 | - <span class="text-sm font-normal text-gray-500"><?php echo $currency; ?></span> | |
| 322 | + <?php echo esc_html($formatter->format($data['amount'])); ?> | |
| 323 | + <span class="text-sm font-normal text-gray-500"><?php echo esc_html($currency); ?></span> | |
| 300 | 324 | </p> |
| 301 | 325 | <?php endforeach; ?> |
| 302 | 326 | </div> |
| 303 | 327 | <?php else: ?> |
| @@ -313,19 +337,18 @@ | ||
| 313 | 337 | <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> |
| 314 | 338 | </svg> |
| 315 | 339 | </div> |
| 316 | 340 | <div> |
| 317 | - <h3 class="text-sm font-medium text-gray-500">Total Value</h3> | |
| 341 | + <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e('Total Value', 'easy-invoice'); ?></h3> | |
| 318 | 342 | <?php if (is_array($stats['total_value']) && !empty($stats['total_value'])): ?> |
| 319 | 343 | <div class="mt-1"> |
| 320 | 344 | <?php foreach ($stats['total_value'] as $currency => $data): ?> |
| 321 | 345 | <?php |
| 322 | - $formatter = new \EasyInvoice\Helpers\InvoiceFormatter($data['invoice_object']); | |
| 323 | - $formatted_amount = $formatter->format($data['amount']); | |
| 346 | + $formatted_amount = easy_invoice_format_money((float) $data['amount'], null, (string) $currency); | |
| 324 | 347 | ?> |
| 325 | 348 | <div class="text-lg font-bold text-gray-900"> |
| 326 | - <?php echo $formatted_amount; ?> | |
| 327 | - <span class="text-xs font-normal text-gray-500 ml-1">(<?php echo $data['invoices']; ?> <?php echo $data['invoices'] > 1 ? 'invoices' : 'invoice'; ?>)</span> | |
| 349 | + <?php echo esc_html($formatted_amount); ?> | |
| 350 | + <span class="text-xs font-normal text-gray-500 ml-1">(<?php echo esc_html($data['invoices']); ?> <?php echo $data['invoices'] > 1 ? 'invoices' : 'invoice'; ?>)</span> | |
| 328 | 351 | </div> |
| 329 | 352 | <?php endforeach; ?> |
| 330 | 353 | </div> |
| 331 | 354 | <?php else: ?> |
| @@ -341,10 +364,10 @@ | ||
| 341 | 364 | <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> |
| 342 | 365 | </svg> |
| 343 | 366 | </div> |
| 344 | 367 | <div> |
| 345 | - <h3 class="text-sm font-medium text-gray-500">Paid Invoices</h3> | |
| 346 | - <p class="mt-1 text-2xl font-bold text-green-600"><?php echo $stats['paid_invoices']; ?></p> | |
| 368 | + <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e('Paid Invoices', 'easy-invoice'); ?></h3> | |
| 369 | + <p class="mt-1 text-2xl font-bold text-green-600"><?php echo esc_html($stats['paid_invoices']); ?></p> | |
| 347 | 370 | </div> |
| 348 | 371 | </div> |
| 349 | 372 | </div> |
| 350 | 373 | <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1"> |
| @@ -354,10 +377,10 @@ | ||
| 354 | 377 | <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> |
| 355 | 378 | </svg> |
| 356 | 379 | </div> |
| 357 | 380 | <div> |
| 358 | - <h3 class="text-sm font-medium text-gray-500">Pending Invoices</h3> | |
| 359 | - <p class="mt-1 text-2xl font-bold text-yellow-600"><?php echo $stats['pending_invoices']; ?></p> | |
| 381 | + <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e('Outstanding', 'easy-invoice'); ?></h3> | |
| 382 | + <p class="mt-1 text-2xl font-bold text-yellow-600"><?php echo esc_html($stats['pending_invoices']); ?></p> | |
| 360 | 383 | </div> |
| 361 | 384 | </div> |
| 362 | 385 | </div> |
| 363 | 386 | </div> |
| @@ -420,9 +443,9 @@ | ||
| 420 | 443 | if ($link && strpos($link, 'bg-indigo-50') === false && strpos($link, 'bg-white') === false) { |
| 421 | 444 | $link = easy_invoice_str_replace('border-gray-300', 'border-gray-300 bg-white text-gray-500 hover:bg-gray-50', $link); |
| 422 | 445 | } |
| 423 | 446 | |
| 424 | - echo $link; | |
| 447 | + echo wp_kses_post($link); | |
| 425 | 448 | } |
| 426 | 449 | echo '</div>'; |
| 427 | 450 | } |
| 428 | 451 | ?> |
| @@ -437,9 +460,9 @@ | ||
| 437 | 460 | <nav class="flex"> |
| 438 | 461 | <?php |
| 439 | 462 | // View Tabs (All, Draft, Trash) |
| 440 | 463 | $views = array( |
| 441 | - 'all' => 'All (' . $stats['total_invoices'] . ')', | |
| 464 | + 'all' => 'All (' . $all_count . ')', | |
| 442 | 465 | 'draft' => 'Draft (' . $draft_count . ')', |
| 443 | 466 | 'trash' => 'Trash (' . $trash_count . ')' |
| 444 | 467 | ); |
| 445 | 468 | |
| @@ -453,9 +476,9 @@ | ||
| 453 | 476 | ? 'border-b-2 border-indigo-500 text-indigo-600 bg-white' |
| 454 | 477 | : 'border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'; |
| 455 | 478 | ?> |
| 456 | 479 | <a href="?page=easy-invoice-all&view=<?php echo esc_attr($view . $status_param); ?>" |
| 457 | - class="flex items-center whitespace-nowrap py-4 px-6 font-medium text-sm transition-colors duration-200 <?php echo $class; ?>"> | |
| 480 | + class="flex items-center whitespace-nowrap py-4 px-6 font-medium text-sm transition-colors duration-200 <?php echo esc_attr($class); ?>"> | |
| 458 | 481 | <?php if ($view === 'all'): ?> |
| 459 | 482 | <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> |
| 460 | 483 | <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> |
| 461 | 484 | </svg> |
| @@ -467,9 +490,9 @@ | ||
| 467 | 490 | <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> |
| 468 | 491 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path> |
| 469 | 492 | </svg> |
| 470 | 493 | <?php endif; ?> |
| 471 | - <?php echo $label; ?> | |
| 494 | + <?php echo esc_html($label); ?> | |
| 472 | 495 | </a> |
| 473 | 496 | <?php |
| 474 | 497 | } |
| 475 | 498 | ?> |
| @@ -477,23 +500,24 @@ | ||
| 477 | 500 | </div> |
| 478 | 501 | |
| 479 | 502 | <div class="p-4 flex flex-wrap items-center justify-between bg-white border-b border-gray-100"> |
| 480 | 503 | <div class="flex items-center space-x-2 my-2"> |
| 481 | - <form id="bulk-action-form" method="post" class="flex items-center gap-2"> | |
| 504 | + <?php if (easy_invoice_user_can('ei_create_invoice')) : ?> | |
| 505 | +<form id="bulk-action-form" method="post" class="flex items-center gap-2"> | |
| 482 | 506 | <?php wp_nonce_field('easy_invoice_bulk_action', 'easy_invoice_bulk_nonce'); ?> |
| 483 | 507 | <input type="hidden" name="action" value="easy_invoice_bulk_action"> |
| 484 | 508 | |
| 485 | - <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"> | |
| 486 | - <option value="">Bulk Actions</option> | |
| 509 | + <select name="bulk_action" aria-label="Bulk action for selected invoices" 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"> | |
| 510 | + <option value=""><?php esc_html_e('Bulk Actions', 'easy-invoice'); ?></option> | |
| 487 | 511 | <?php if ($current_view === 'trash'): ?> |
| 488 | - <option value="restore">Restore</option> | |
| 489 | - <option value="delete">Delete Permanently</option> | |
| 512 | + <option value="restore"><?php esc_html_e('Restore', 'easy-invoice'); ?></option> | |
| 513 | + <option value="delete"><?php esc_html_e('Delete Permanently', 'easy-invoice'); ?></option> | |
| 490 | 514 | <?php elseif ($current_view === 'draft'): ?> |
| 491 | - <option value="publish">Publish</option> | |
| 492 | - <option value="trash">Move to Trash</option> | |
| 515 | + <option value="publish"><?php esc_html_e('Publish', 'easy-invoice'); ?></option> | |
| 516 | + <option value="trash"><?php esc_html_e('Move to Trash', 'easy-invoice'); ?></option> | |
| 493 | 517 | <?php else: ?> |
| 494 | - <option value="trash">Move to Trash</option> | |
| 495 | - <option value="draft">Set to Draft</option> | |
| 518 | + <option value="trash"><?php esc_html_e('Move to Trash', 'easy-invoice'); ?></option> | |
| 519 | + <option value="draft"><?php esc_html_e('Set to Draft', 'easy-invoice'); ?></option> | |
| 496 | 520 | <?php endif; ?> |
| 497 | 521 | <option value="export" data-requires-pro="1"><?php esc_html_e('Export Selected (Pro)', 'easy-invoice'); ?></option> |
| 498 | 522 | </select> |
| 499 | 523 | |
| @@ -500,8 +524,9 @@ | ||
| 500 | 524 | <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 whitespace-nowrap"> |
| 501 | 525 | Apply |
| 502 | 526 | </button> |
| 503 | 527 | </form> |
| 528 | +<?php endif; ?> | |
| 504 | 529 | </div> |
| 505 | 530 | |
| 506 | 531 | <?php if ($current_view !== 'trash'): ?> |
| 507 | 532 | <div class="flex items-center gap-2"> |
| @@ -536,19 +561,19 @@ | ||
| 536 | 561 | </div> |
| 537 | 562 | <input type="text" |
| 538 | 563 | name="search" |
| 539 | 564 | value="<?php echo esc_attr($search_query); ?>" |
| 540 | - placeholder="<?php _e('Search invoices, numbers, or clients...', 'easy-invoice'); ?>" | |
| 565 | + placeholder="<?php echo esc_js(__('Search invoices, numbers, or clients...', 'easy-invoice')); ?>" | |
| 541 | 566 | class="block w-64 pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> |
| 542 | 567 | </div> |
| 543 | 568 | |
| 544 | 569 | <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"> |
| 545 | - <?php _e('Search', 'easy-invoice'); ?> | |
| 570 | + <?php esc_html_e('Search', 'easy-invoice'); ?> | |
| 546 | 571 | </button> |
| 547 | 572 | |
| 548 | 573 | <?php if (!empty($search_query)): ?> |
| 549 | 574 | <a href="<?php echo esc_url(remove_query_arg('search', $_SERVER['REQUEST_URI'])); ?>" class="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"> |
| 550 | - <?php _e('Clear', 'easy-invoice'); ?> | |
| 575 | + <?php esc_html_e('Clear', 'easy-invoice'); ?> | |
| 551 | 576 | </a> |
| 552 | 577 | <?php endif; ?> |
| 553 | 578 | </form> |
| 554 | 579 | </div> |
| @@ -557,9 +582,9 @@ | ||
| 557 | 582 | |
| 558 | 583 | <?php if ($current_view !== 'trash'): ?> |
| 559 | 584 | <div class="p-4 bg-white border-b border-gray-100"> |
| 560 | 585 | <div class="flex flex-wrap items-center gap-2 my-2"> |
| 561 | - <span class="text-sm text-gray-500 mr-2">Filter by status:</span> | |
| 586 | + <span class="text-sm text-gray-500 mr-2"><?php esc_html_e('Filter by status:', 'easy-invoice'); ?></span> | |
| 562 | 587 | <div class="flex flex-wrap gap-1"> |
| 563 | 588 | <?php |
| 564 | 589 | // Build base URL with current view, recurring filter, client filter and search query |
| 565 | 590 | $base_url = '?page=easy-invoice-all&view=' . $current_view; |
| @@ -578,9 +603,11 @@ | ||
| 578 | 603 | </a> |
| 579 | 604 | |
| 580 | 605 | <?php |
| 581 | 606 | $status_colors = [ |
| 607 | + 'available' => 'bg-blue-100 text-blue-800 ring-1 ring-blue-300', | |
| 582 | 608 | 'paid' => 'bg-green-100 text-green-800 ring-1 ring-green-300', |
| 609 | + 'partial' => 'bg-yellow-100 text-yellow-800 ring-1 ring-yellow-300', | |
| 583 | 610 | 'unpaid' => 'bg-yellow-100 text-yellow-800 ring-1 ring-yellow-300', |
| 584 | 611 | 'pending' => 'bg-blue-100 text-blue-800 ring-1 ring-blue-300', |
| 585 | 612 | 'draft' => 'bg-gray-100 text-gray-800 ring-1 ring-gray-300', |
| 586 | 613 | 'overdue' => 'bg-red-100 text-red-800 ring-1 ring-red-300', |
| @@ -600,10 +627,10 @@ | ||
| 600 | 627 | // Build URL with status filter |
| 601 | 628 | $status_url = $base_url . '&status=' . urlencode($status_key); |
| 602 | 629 | ?> |
| 603 | 630 | <a href="<?php echo esc_url($status_url); ?>" |
| 604 | - class="<?php echo $base_class . ' ' . $color_class; ?>"> | |
| 605 | - <?php echo $status_label; ?> | |
| 631 | + class="<?php echo esc_html($base_class) . ' ' . esc_html($color_class); ?>"> | |
| 632 | + <?php echo esc_html($status_label); ?> | |
| 606 | 633 | </a> |
| 607 | 634 | <?php endforeach; ?> |
| 608 | 635 | </div> |
| 609 | 636 | <?php do_action('easy_invoice_inline_type_filter'); ?> |
| @@ -615,28 +642,28 @@ | ||
| 615 | 642 | </div> |
| 616 | 643 | |
| 617 | 644 | <div class="bg-white rounded-lg shadow overflow-hidden"> |
| 618 | 645 | <div class="overflow-x-auto"> |
| 619 | - <table class="min-w-full divide-y divide-gray-200"> | |
| 646 | + <table class="min-w-full divide-y divide-gray-200 ei-invoices-table"> | |
| 620 | 647 | <thead> |
| 621 | 648 | <tr class="bg-gray-50"> |
| 622 | 649 | <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-10 border-b border-gray-200"> |
| 623 | - <input type="checkbox" id="select-all" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"> | |
| 650 | + <input type="checkbox" id="select-all" aria-label="Select all invoices on this page" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"> | |
| 624 | 651 | </th> |
| 625 | 652 | <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-200"> |
| 626 | - <?php _e('Invoice', 'easy-invoice'); ?> | |
| 653 | + <?php esc_html_e('Invoice', 'easy-invoice'); ?> | |
| 627 | 654 | </th> |
| 628 | 655 | <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-200"> |
| 629 | - <?php _e('Client', 'easy-invoice'); ?> | |
| 656 | + <?php esc_html_e('Client', 'easy-invoice'); ?> | |
| 630 | 657 | </th> |
| 631 | 658 | <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-200"> |
| 632 | - <?php _e('Status', 'easy-invoice'); ?> | |
| 659 | + <?php esc_html_e('Status', 'easy-invoice'); ?> | |
| 633 | 660 | </th> |
| 634 | 661 | <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-200"> |
| 635 | - <?php _e('Amount', 'easy-invoice'); ?> | |
| 662 | + <?php esc_html_e('Amount', 'easy-invoice'); ?> | |
| 636 | 663 | </th> |
| 637 | 664 | <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider border-b border-gray-200"> |
| 638 | - <?php _e('Due Date', 'easy-invoice'); ?> | |
| 665 | + <?php esc_html_e('Due Date', 'easy-invoice'); ?> | |
| 639 | 666 | </th> |
| 640 | 667 | <?php do_action('easy_invoice_after_invoice_listing_header'); ?> |
| 641 | 668 | </tr> |
| 642 | 669 | </thead> |
| @@ -683,22 +710,20 @@ | ||
| 683 | 710 | |
| 684 | 711 | // Format the display title |
| 685 | 712 | $display_title = $invoice_title ?: 'Untitled Invoice'; |
| 686 | 713 | |
| 687 | - // Determine classes for status badge | |
| 688 | - $status_class = 'bg-gray-100 text-gray-800 ring-1 ring-gray-200'; | |
| 689 | - if ($status === 'paid') { | |
| 690 | - $status_class = 'bg-green-100 text-green-800 ring-1 ring-green-200'; | |
| 691 | - } elseif ($status === 'pending') { | |
| 692 | - $status_class = 'bg-yellow-100 text-yellow-800 ring-1 ring-yellow-200'; | |
| 693 | - } elseif ($status === 'overdue') { | |
| 694 | - $status_class = 'bg-red-100 text-red-800 ring-1 ring-red-200'; | |
| 695 | - } | |
| 714 | + // An invoice still owed after its due date reads as overdue | |
| 715 | + // whatever its stored status says (nothing flips the status | |
| 716 | + // by itself); the underlying status stays for the filters. | |
| 717 | + $status = \EasyInvoice\Helpers\InvoiceStatus::displayKey((string) $status, $due_date ? (string) $due_date : null); | |
| 718 | + $status_class = 'available' === $status | |
| 719 | + ? 'bg-gray-100 text-gray-800 ring-1 ring-gray-200' | |
| 720 | + : \EasyInvoice\Helpers\InvoiceStatus::badgeClass($status); | |
| 696 | 721 | ?> |
| 697 | 722 | <?php do_action('easy_invoice_before_invoice_listing_row', $invoice); ?> |
| 698 | - <tr class="hover:bg-gray-50 transition-colors duration-150" data-invoice-id="<?php echo $invoice_id; ?>"> | |
| 723 | + <tr class="hover:bg-gray-50 transition-colors duration-150" data-invoice-id="<?php echo (int) $invoice_id; ?>"> | |
| 699 | 724 | <td class="px-6 py-4 whitespace-nowrap"> |
| 700 | - <input type="checkbox" name="invoice_ids[]" value="<?php echo $invoice_id; ?>" form="bulk-action-form" class="invoice-checkbox rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"> | |
| 725 | + <input type="checkbox" name="invoice_ids[]" value="<?php echo (int) $invoice_id; ?>" form="bulk-action-form" aria-label="<?php /* translators: %s: invoice number. */ echo esc_attr(sprintf(__('Select invoice %s', 'easy-invoice'), $invoice_number)); ?>" class="invoice-checkbox rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"> | |
| 701 | 726 | </td> |
| 702 | 727 | <td class="px-6 py-4 whitespace-nowrap"> |
| 703 | 728 | <?php if ($current_view === 'trash'): ?> |
| 704 | 729 | <div class="text-sm font-medium text-gray-900"> |
| @@ -704,9 +729,15 @@ | ||
| 704 | 729 | <div class="text-sm font-medium text-gray-900"> |
| 705 | 730 | <?php echo esc_html($display_title); ?> |
| 706 | 731 | </div> |
| 707 | 732 | <div class="text-xs text-gray-500 mt-1"> |
| 708 | - <?php echo apply_filters('easy_invoice_invoice_number_display', esc_html($invoice_number), $invoice); ?> | |
| 733 | + <?php echo wp_kses_post(apply_filters('easy_invoice_invoice_number_display', esc_html($invoice_number), $invoice)); ?> | |
| 734 | + <?php if ('draft' !== get_post_meta($invoice_id, '_easy_invoice_status', true)) : ?> | |
| 735 | + <span class="ei-viewed ml-2 inline-flex items-center gap-1 <?php echo \EasyInvoice\Services\DocumentViews::summary($invoice_id)['count'] ? 'text-emerald-600' : 'text-gray-400'; ?>" title="<?php echo esc_attr(\EasyInvoice\Services\DocumentViews::summary($invoice_id)['from'] ? sprintf(/* translators: %s: anonymised IP. */ __('Last opened from %s', 'easy-invoice'), \EasyInvoice\Services\DocumentViews::summary($invoice_id)['from']) : ''); ?>"> | |
| 736 | + <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><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"/></svg> | |
| 737 | + <?php echo esc_html(\EasyInvoice\Services\DocumentViews::label($invoice_id)); ?> | |
| 738 | + </span> | |
| 739 | + <?php endif; ?> | |
| 709 | 740 | <?php |
| 710 | 741 | // Check if this invoice was converted from a quote |
| 711 | 742 | $quote_info = \EasyInvoice\Helpers\QuoteInvoiceHelper::getQuoteInfoFromInvoice($invoice_id); |
| 712 | 743 | if ($quote_info): ?> |
| @@ -721,19 +752,25 @@ | ||
| 721 | 752 | </span> |
| 722 | 753 | <?php endif; ?> |
| 723 | 754 | </div> |
| 724 | 755 | <div class="row-actions mt-1"> |
| 725 | - <span class="restore"><a href="#" class="restore-invoice" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"></path></svg><?php _e('Restore', 'easy-invoice'); ?></a></span> | |
| 726 | - <span class="delete"><a href="#" class="delete-permanently text-red-600" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg><?php _e('Delete Permanently', 'easy-invoice'); ?></a></span> | |
| 756 | + <span class="restore"><a href="#" class="restore-invoice" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"></path></svg><?php esc_html_e('Restore', 'easy-invoice'); ?></a></span> | |
| 757 | + <span class="delete"><a href="#" class="delete-permanently text-red-600" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg><?php esc_html_e('Delete Permanently', 'easy-invoice'); ?></a></span> | |
| 727 | 758 | </div> |
| 728 | 759 | <?php elseif ($current_view === 'draft'): ?> |
| 729 | 760 | <div class="text-sm font-medium text-gray-900"> |
| 730 | - <a href="<?php echo get_permalink($invoice_id); ?>" class="text-indigo-600 hover:text-indigo-900"> | |
| 731 | - <?php echo apply_filters('easy_invoice_invoice_title', esc_html($display_title), $invoice); ?> | |
| 761 | + <a href="<?php echo esc_url(get_permalink($invoice_id)); ?>" class="text-indigo-600 hover:text-indigo-900"> | |
| 762 | + <?php echo wp_kses_post(apply_filters('easy_invoice_invoice_title', esc_html($display_title), $invoice)); ?> | |
| 732 | 763 | </a> |
| 733 | 764 | </div> |
| 734 | 765 | <div class="text-xs text-gray-500 mt-1"> |
| 735 | - <?php echo apply_filters('easy_invoice_invoice_number_display', esc_html($invoice_number), $invoice); ?> | |
| 766 | + <?php echo wp_kses_post(apply_filters('easy_invoice_invoice_number_display', esc_html($invoice_number), $invoice)); ?> | |
| 767 | + <?php if ('draft' !== get_post_meta($invoice_id, '_easy_invoice_status', true)) : ?> | |
| 768 | + <span class="ei-viewed ml-2 inline-flex items-center gap-1 <?php echo \EasyInvoice\Services\DocumentViews::summary($invoice_id)['count'] ? 'text-emerald-600' : 'text-gray-400'; ?>" title="<?php echo esc_attr(\EasyInvoice\Services\DocumentViews::summary($invoice_id)['from'] ? sprintf(/* translators: %s: anonymised IP. */ __('Last opened from %s', 'easy-invoice'), \EasyInvoice\Services\DocumentViews::summary($invoice_id)['from']) : ''); ?>"> | |
| 769 | + <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><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"/></svg> | |
| 770 | + <?php echo esc_html(\EasyInvoice\Services\DocumentViews::label($invoice_id)); ?> | |
| 771 | + </span> | |
| 772 | + <?php endif; ?> | |
| 736 | 773 | <?php |
| 737 | 774 | // Check if this invoice was converted from a quote |
| 738 | 775 | $quote_info = \EasyInvoice\Helpers\QuoteInvoiceHelper::getQuoteInfoFromInvoice($invoice_id); |
| 739 | 776 | if ($quote_info): ?> |
| @@ -748,18 +785,18 @@ | ||
| 748 | 785 | </span> |
| 749 | 786 | <?php endif; ?> |
| 750 | 787 | </div> |
| 751 | 788 | <div class="row-actions mt-1"> |
| 752 | - <span class="edit"><a href="<?php echo admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoice_id); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php _e('Edit', 'easy-invoice'); ?></a></span> | |
| 753 | - <span class="publish"><a href="#" class="publish-invoice" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg><?php _e('Publish', 'easy-invoice'); ?></a></span> | |
| 754 | - <span class="trash"><a href="#" class="trash-invoice text-red-600" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg><?php _e('Trash', 'easy-invoice'); ?></a></span> | |
| 755 | - <span class="email"><a href="#" class="email-invoice" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg><?php _e('Send Email', 'easy-invoice'); ?></a></span> | |
| 756 | - <span class="pdf"><a href="<?php echo get_permalink($invoice_id); ?>?auto_download_pdf=1" target="_blank" class="download-pdf" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php _e('Download PDF', 'easy-invoice'); ?></a></span> | |
| 789 | + <span class="edit"><a href="<?php echo esc_url(admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoice_id)); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php esc_html_e('Edit', 'easy-invoice'); ?></a></span> | |
| 790 | + <span class="publish"><a href="#" class="publish-invoice" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg><?php esc_html_e('Publish', 'easy-invoice'); ?></a></span> | |
| 791 | + <span class="trash"><a href="#" class="trash-invoice text-red-600" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg><?php esc_html_e('Trash', 'easy-invoice'); ?></a></span> | |
| 792 | + <span class="email"><a href="#" class="email-invoice" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg><?php esc_html_e('Send Email', 'easy-invoice'); ?></a></span> | |
| 793 | + <span class="pdf"><a href="<?php echo esc_url(get_permalink($invoice_id)); ?>?auto_download_pdf=1" target="_blank" class="download-pdf" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php esc_html_e('Download PDF', 'easy-invoice'); ?></a></span> | |
| 757 | 794 | <?php if (!easy_invoice_has_pro()): ?> |
| 758 | - <span class="export premium-feature"><a href="#" class="export-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg>Export</a></span> | |
| 795 | + <span class="export premium-feature"><a href="#" class="export-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg>Export</a></span> | |
| 759 | 796 | <?php endif; ?> |
| 760 | 797 | <?php if (!easy_invoice_has_pro()): ?> |
| 761 | - <span class="duplicate premium-feature"><a href="#" class="duplicate-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 7l2 4 4 .5-3 2.5.5 4-3.5-2-3.5 2 .5-4-3-2.5 4-.5 2-4z"/></svg>Duplicate</a></span> | |
| 798 | + <span class="duplicate premium-feature"><a href="#" class="duplicate-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 7l2 4 4 .5-3 2.5.5 4-3.5-2-3.5 2 .5-4-3-2.5 4-.5 2-4z"/></svg>Duplicate</a></span> | |
| 762 | 799 | <?php endif; ?> |
| 763 | 800 | |
| 764 | 801 | <?php |
| 765 | 802 | // Apply filter for Pro plugin to add secure link actions |
| @@ -764,20 +801,26 @@ | ||
| 764 | 801 | <?php |
| 765 | 802 | // Apply filter for Pro plugin to add secure link actions |
| 766 | 803 | $secure_actions = apply_filters('easy_invoice_invoice_row_actions', [], $invoice); |
| 767 | 804 | foreach ($secure_actions as $action_key => $action_html) { |
| 768 | - echo '<span class="' . esc_attr($action_key) . '">' . $action_html . '</span>'; | |
| 805 | + echo '<span class="' . esc_attr($action_key) . '">' . wp_kses_post($action_html) . '</span>'; | |
| 769 | 806 | } |
| 770 | 807 | ?> |
| 771 | 808 | </div> |
| 772 | 809 | <?php else: ?> |
| 773 | 810 | <div class="text-sm font-medium text-gray-900"> |
| 774 | - <a href="<?php echo admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoice_id); ?>" class="text-indigo-600 hover:text-indigo-900"> | |
| 775 | - <?php echo apply_filters('easy_invoice_invoice_title', esc_html($display_title), $invoice); ?> | |
| 811 | + <a href="<?php echo esc_url(admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoice_id)); ?>" class="text-indigo-600 hover:text-indigo-900"> | |
| 812 | + <?php echo wp_kses_post(apply_filters('easy_invoice_invoice_title', esc_html($display_title), $invoice)); ?> | |
| 776 | 813 | </a> |
| 777 | 814 | </div> |
| 778 | 815 | <div class="text-xs text-gray-500 mt-1"> |
| 779 | - <?php echo apply_filters('easy_invoice_invoice_number_display', esc_html($invoice_number), $invoice); ?> | |
| 816 | + <?php echo wp_kses_post(apply_filters('easy_invoice_invoice_number_display', esc_html($invoice_number), $invoice)); ?> | |
| 817 | + <?php if ('draft' !== get_post_meta($invoice_id, '_easy_invoice_status', true)) : ?> | |
| 818 | + <span class="ei-viewed ml-2 inline-flex items-center gap-1 <?php echo \EasyInvoice\Services\DocumentViews::summary($invoice_id)['count'] ? 'text-emerald-600' : 'text-gray-400'; ?>" title="<?php echo esc_attr(\EasyInvoice\Services\DocumentViews::summary($invoice_id)['from'] ? sprintf(/* translators: %s: anonymised IP. */ __('Last opened from %s', 'easy-invoice'), \EasyInvoice\Services\DocumentViews::summary($invoice_id)['from']) : ''); ?>"> | |
| 819 | + <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><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"/></svg> | |
| 820 | + <?php echo esc_html(\EasyInvoice\Services\DocumentViews::label($invoice_id)); ?> | |
| 821 | + </span> | |
| 822 | + <?php endif; ?> | |
| 780 | 823 | <?php |
| 781 | 824 | // Check if this invoice was converted from a quote |
| 782 | 825 | $quote_info = \EasyInvoice\Helpers\QuoteInvoiceHelper::getQuoteInfoFromInvoice($invoice_id); |
| 783 | 826 | if ($quote_info): ?> |
| @@ -792,19 +835,23 @@ | ||
| 792 | 835 | </span> |
| 793 | 836 | <?php endif; ?> |
| 794 | 837 | </div> |
| 795 | 838 | <div class="row-actions mt-1"> |
| 796 | - <span class="view"><a href="<?php echo apply_filters('easy_invoice_invoice_view_url', get_permalink($invoice_id), $invoice_id); ?>" target="_blank"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><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></svg><?php _e('View', 'easy-invoice'); ?></a></span> | |
| 797 | - <span class="edit"><a href="<?php echo admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoice_id); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php _e('Edit', 'easy-invoice'); ?></a></span> | |
| 798 | - <span class="draft"><a href="#" class="draft-invoice" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php _e('Draft', 'easy-invoice'); ?></a></span> | |
| 799 | - <span class="trash"><a href="#" class="trash-invoice text-red-600" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg><?php _e('Trash', 'easy-invoice'); ?></a></span> | |
| 800 | - <span class="email"><a href="#" class="email-invoice" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg><?php _e('Send Email', 'easy-invoice'); ?></a></span> | |
| 801 | - <span class="pdf"><a href="<?php echo get_permalink($invoice_id); ?>?auto_download_pdf=1" target="_blank" class="download-pdf" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php _e('Download PDF', 'easy-invoice'); ?></a></span> | |
| 839 | + <span class="view"><a href="<?php echo esc_url(apply_filters('easy_invoice_invoice_view_url', get_permalink($invoice_id), $invoice_id)); ?>" target="_blank"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><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></svg><?php esc_html_e('View', 'easy-invoice'); ?></a></span> | |
| 840 | + <span class="edit"><a href="<?php echo esc_url(admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoice_id)); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php esc_html_e('Edit', 'easy-invoice'); ?></a></span> | |
| 841 | + <?php if (in_array((string) $invoice->getStatus(), ['available', 'unpaid', 'overdue'], true)) : // paid, part-paid and cancelled invoices are not un-issued ?> | |
| 842 | + <?php if (is_object($invoice) && in_array(strtolower((string) $invoice->getStatus()), ['available', 'unpaid', 'overdue'], true)) : // paid, part-paid and cancelled invoices are not un-issued ?> | |
| 843 | + <span class="draft"><a href="#" class="draft-invoice" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php esc_html_e('Draft', 'easy-invoice'); ?></a></span> | |
| 844 | + <?php endif; ?> | |
| 845 | + <?php endif; ?> | |
| 846 | + <span class="trash"><a href="#" class="trash-invoice text-red-600" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg><?php esc_html_e('Trash', 'easy-invoice'); ?></a></span> | |
| 847 | + <span class="email"><a href="#" class="email-invoice" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg><?php esc_html_e('Send Email', 'easy-invoice'); ?></a></span> | |
| 848 | + <span class="pdf"><a href="<?php echo esc_url(get_permalink($invoice_id)); ?>?auto_download_pdf=1" target="_blank" class="download-pdf" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg><?php esc_html_e('Download PDF', 'easy-invoice'); ?></a></span> | |
| 802 | 849 | <?php if (!easy_invoice_has_pro()): ?> |
| 803 | - <span class="export premium-feature"><a href="#" class="export-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg>Export</a></span> | |
| 850 | + <span class="export premium-feature"><a href="#" class="export-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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></svg>Export</a></span> | |
| 804 | 851 | <?php endif; ?> |
| 805 | 852 | <?php if (!easy_invoice_has_pro()): ?> |
| 806 | - <span class="duplicate premium-feature"><a href="#" class="duplicate-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 7l2 4 4 .5-3 2.5.5 4-3.5-2-3.5 2 .5-4-3-2.5 4-.5 2-4z"/></svg>Duplicate</a></span> | |
| 853 | + <span class="duplicate premium-feature"><a href="#" class="duplicate-invoice-pro-placeholder text-yellow-600 font-semibold" data-invoice-id="<?php echo (int) $invoice_id; ?>" data-invoice-number="<?php echo esc_attr($invoice_number); ?>"><svg class="w-3.5 h-3.5 mr-1 inline-block text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 7l2 4 4 .5-3 2.5.5 4-3.5-2-3.5 2 .5-4-3-2.5 4-.5 2-4z"/></svg>Duplicate</a></span> | |
| 807 | 854 | <?php endif; ?> |
| 808 | 855 | |
| 809 | 856 | <?php |
| 810 | 857 | // Apply filter for Pro plugin to add secure link actions |
| @@ -809,9 +856,9 @@ | ||
| 809 | 856 | <?php |
| 810 | 857 | // Apply filter for Pro plugin to add secure link actions |
| 811 | 858 | $secure_actions = apply_filters('easy_invoice_invoice_row_actions', [], $invoice); |
| 812 | 859 | foreach ($secure_actions as $action_key => $action_html) { |
| 813 | - echo '<span class="' . esc_attr($action_key) . '">' . $action_html . '</span>'; | |
| 860 | + echo '<span class="' . esc_attr($action_key) . '">' . wp_kses_post($action_html) . '</span>'; | |
| 814 | 861 | } |
| 815 | 862 | ?> |
| 816 | 863 | </div> |
| 817 | 864 | <?php endif; ?> |
| @@ -820,10 +867,10 @@ | ||
| 820 | 867 | <div class="text-sm text-gray-900"><?php echo esc_html($client_name ?: 'No Client'); ?></div> |
| 821 | 868 | <div class="text-sm text-gray-500"><?php echo esc_html($client_email ?: ''); ?></div> |
| 822 | 869 | </td> |
| 823 | 870 | <td class="px-6 py-4 whitespace-nowrap"> |
| 824 | - <span class="px-3 py-1 inline-flex text-xs leading-5 font-medium rounded-full <?php echo $status_class; ?>"> | |
| 825 | - <?php echo ucfirst(esc_html($status)); ?> | |
| 871 | + <span class="px-3 py-1 inline-flex text-xs leading-5 font-medium rounded-full <?php echo esc_attr($status_class); ?>"> | |
| 872 | + <?php echo esc_html(\EasyInvoice\Helpers\InvoiceStatus::label($status)); ?> | |
| 826 | 873 | </span> |
| 827 | 874 | </td> |
| 828 | 875 | <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700 font-medium"> |
| 829 | 876 | <?php echo esc_html($amount); ?> |
| @@ -837,14 +884,28 @@ | ||
| 837 | 884 | |
| 838 | 885 | <?php if (empty($invoices)): ?> |
| 839 | 886 | <tr> |
| 840 | 887 | <td colspan="7" class="px-6 py-4 text-center text-sm text-gray-500"> |
| 888 | + <?php | |
| 889 | + // These three strings were hardcoded English with no | |
| 890 | + // __() wrapper, so they could never be translated even | |
| 891 | + // though the rest of the screen is fully localised. | |
| 892 | + $ei_create_link = '<a href="#" class="text-indigo-600 hover:text-indigo-900 create-first-invoice">' | |
| 893 | + . esc_html__('Create your first invoice', 'easy-invoice') | |
| 894 | + . '</a>'; | |
| 895 | + ?> | |
| 841 | 896 | <?php if ($current_view === 'trash'): ?> |
| 842 | - No invoices found in trash. | |
| 897 | + <?php esc_html_e('No invoices found in trash.', 'easy-invoice'); ?> | |
| 843 | 898 | <?php elseif ($current_view === 'draft'): ?> |
| 844 | - No invoices found in draft. <a href="#" class="text-indigo-600 hover:text-indigo-900 create-first-invoice">Create your first invoice</a>. | |
| 899 | + <?php | |
| 900 | + /* translators: %s: link reading "Create your first invoice". */ | |
| 901 | + printf(esc_html__('No invoices found in draft. %s.', 'easy-invoice'), wp_kses_post($ei_create_link)); | |
| 902 | + ?> | |
| 845 | 903 | <?php else: ?> |
| 846 | - No invoices found. <a href="#" class="text-indigo-600 hover:text-indigo-900 create-first-invoice">Create your first invoice</a>. | |
| 904 | + <?php | |
| 905 | + /* translators: %s: link reading "Create your first invoice". */ | |
| 906 | + printf(esc_html__('No invoices found. %s.', 'easy-invoice'), wp_kses_post($ei_create_link)); | |
| 907 | + ?> | |
| 847 | 908 | <?php endif; ?> |
| 848 | 909 | </td> |
| 849 | 910 | </tr> |
| 850 | 911 | <?php endif; ?> |
| @@ -910,9 +971,9 @@ | ||
| 910 | 971 | if ($link && strpos($link, 'bg-indigo-50') === false && strpos($link, 'bg-white') === false) { |
| 911 | 972 | $link = easy_invoice_str_replace('border-gray-300', 'border-gray-300 bg-white text-gray-500 hover:bg-gray-50', $link); |
| 912 | 973 | } |
| 913 | 974 | |
| 914 | - echo $link; | |
| 975 | + echo wp_kses_post($link); | |
| 915 | 976 | } |
| 916 | 977 | echo '</div>'; |
| 917 | 978 | } |
| 918 | 979 | ?> |
| @@ -927,9 +988,9 @@ | ||
| 927 | 988 | <div class="bg-white rounded-lg shadow-xl max-w-md w-full p-6 relative"> |
| 928 | 989 | <button class="close-modal absolute top-4 right-4 text-gray-400 hover:text-gray-500"> |
| 929 | 990 | <i class="fas fa-times"></i> |
| 930 | 991 | </button> |
| 931 | - <h2 class="text-xl font-medium text-gray-900 mb-4">Move to Trash</h2> | |
| 992 | + <h2 class="text-xl font-medium text-gray-900 mb-4"><?php esc_html_e('Move to Trash', 'easy-invoice'); ?></h2> | |
| 932 | 993 | <p class="text-sm text-gray-500 mb-4">Are you sure you want to move invoice <span id="trash-invoice-number" class="font-medium"></span> to trash?</p> |
| 933 | 994 | |
| 934 | 995 | <div class="mt-5 flex justify-end space-x-3"> |
| 935 | 996 | <button type="button" class="cancel-modal bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| @@ -946,9 +1007,9 @@ | ||
| 946 | 1007 | <div class="bg-white rounded-lg shadow-xl max-w-md w-full p-6 relative"> |
| 947 | 1008 | <button class="close-modal absolute top-4 right-4 text-gray-400 hover:text-gray-500"> |
| 948 | 1009 | <i class="fas fa-times"></i> |
| 949 | 1010 | </button> |
| 950 | - <h2 class="text-xl font-medium text-gray-900 mb-4">Restore Invoice</h2> | |
| 1011 | + <h2 class="text-xl font-medium text-gray-900 mb-4"><?php esc_html_e('Restore Invoice', 'easy-invoice'); ?></h2> | |
| 951 | 1012 | <p class="text-sm text-gray-500 mb-4">Are you sure you want to restore invoice <span id="restore-invoice-number" class="font-medium"></span>?</p> |
| 952 | 1013 | |
| 953 | 1014 | <div class="mt-5 flex justify-end space-x-3"> |
| 954 | 1015 | <button type="button" class="cancel-modal bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| @@ -965,9 +1026,9 @@ | ||
| 965 | 1026 | <div class="bg-white rounded-lg shadow-xl max-w-md w-full p-6 relative"> |
| 966 | 1027 | <button class="close-modal absolute top-4 right-4 text-gray-400 hover:text-gray-500"> |
| 967 | 1028 | <i class="fas fa-times"></i> |
| 968 | 1029 | </button> |
| 969 | - <h2 class="text-xl font-medium text-gray-900 mb-4">Delete Invoice Permanently</h2> | |
| 1030 | + <h2 class="text-xl font-medium text-gray-900 mb-4"><?php esc_html_e('Delete Invoice Permanently', 'easy-invoice'); ?></h2> | |
| 970 | 1031 | <p class="text-sm text-gray-500 mb-4">Are you sure you want to permanently delete invoice <span id="delete-permanently-number" class="font-medium"></span>? This action cannot be undone.</p> |
| 971 | 1032 | |
| 972 | 1033 | <div class="mt-5 flex justify-end space-x-3"> |
| 973 | 1034 | <button type="button" class="cancel-modal bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| @@ -984,9 +1045,9 @@ | ||
| 984 | 1045 | <div class="bg-white rounded-lg shadow-xl max-w-md w-full p-6 relative"> |
| 985 | 1046 | <button class="close-modal absolute top-4 right-4 text-gray-400 hover:text-gray-500"> |
| 986 | 1047 | <i class="fas fa-times"></i> |
| 987 | 1048 | </button> |
| 988 | - <h2 class="text-xl font-medium text-gray-900 mb-4">Publish Invoice</h2> | |
| 1049 | + <h2 class="text-xl font-medium text-gray-900 mb-4"><?php esc_html_e('Publish Invoice', 'easy-invoice'); ?></h2> | |
| 989 | 1050 | <p class="text-sm text-gray-500 mb-4">Are you sure you want to publish invoice <span id="publish-invoice-number" class="font-medium"></span>?</p> |
| 990 | 1051 | |
| 991 | 1052 | <div class="mt-5 flex justify-end space-x-3"> |
| 992 | 1053 | <button type="button" class="cancel-modal bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| @@ -1003,10 +1064,10 @@ | ||
| 1003 | 1064 | <div class="bg-white rounded-lg shadow-xl max-w-md w-full p-6 relative"> |
| 1004 | 1065 | <button class="close-modal absolute top-4 right-4 text-gray-400 hover:text-gray-500"> |
| 1005 | 1066 | <i class="fas fa-times"></i> |
| 1006 | 1067 | </button> |
| 1007 | - <h2 class="text-xl font-medium text-gray-900 mb-4">Set Invoice to Draft</h2> | |
| 1008 | - <p class="text-sm text-gray-500 mb-4">Are you sure you want to set invoice <span id="draft-invoice-number" class="font-medium"></span> to draft status?</p> | |
| 1068 | + <h2 class="text-xl font-medium text-gray-900 mb-4"><?php esc_html_e('Set Invoice to Draft', 'easy-invoice'); ?></h2> | |
| 1069 | + <p class="text-sm text-gray-500 mb-4"><?php esc_html_e('Set invoice', 'easy-invoice'); ?> <span id="draft-invoice-number" class="font-medium"></span> <?php esc_html_e('back to draft? It stays in your list and keeps its number, but reads as not yet issued until you send it again.', 'easy-invoice'); ?></p> | |
| 1009 | 1070 | |
| 1010 | 1071 | <div class="mt-5 flex justify-end space-x-3"> |
| 1011 | 1072 | <button type="button" class="cancel-modal bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| 1012 | 1073 | Cancel |
| @@ -1019,20 +1080,48 @@ | ||
| 1019 | 1080 | </div> |
| 1020 | 1081 | |
| 1021 | 1082 | <style> |
| 1022 | 1083 | /* Modern row actions styling */ |
| 1084 | +/* Team roles: controls a member may not use are not drawn (the endpoints check again). */ | |
| 1085 | +<?php if (!easy_invoice_user_can('ei_create_invoice')) : ?>.row-actions .edit, .row-actions .publish, .row-actions .draft { display: none; }<?php endif; ?> | |
| 1086 | +<?php if (!easy_invoice_user_can('ei_delete_invoice')) : ?>.row-actions .trash, .row-actions .delete, .row-actions .restore { display: none; }<?php endif; ?> | |
| 1087 | +<?php if (!easy_invoice_user_can('ei_send_invoice')) : ?>.row-actions .email { display: none; }<?php endif; ?> | |
| 1088 | +.ei-invoices-table td:nth-child(2) { white-space: normal; } | |
| 1089 | +.ei-invoices-table td:nth-child(2) .ei-viewed { white-space: nowrap; } | |
| 1023 | 1090 | .row-actions { |
| 1024 | 1091 | visibility: hidden; |
| 1025 | 1092 | font-size: 12px; |
| 1026 | 1093 | padding-top: 4px; |
| 1027 | 1094 | display: flex; |
| 1028 | - gap: 8px; | |
| 1095 | + flex-wrap: wrap; /* a long action list must not widen the column past the screen */ | |
| 1096 | + gap: 4px 8px; | |
| 1029 | 1097 | } |
| 1030 | 1098 | |
| 1031 | -tr:hover .row-actions { | |
| 1099 | +tr:hover .row-actions, | |
| 1100 | +tr:focus-within .row-actions { | |
| 1032 | 1101 | visibility: visible; |
| 1033 | 1102 | } |
| 1034 | 1103 | |
| 1104 | +/* | |
| 1105 | + * Row actions were revealed on `tr:hover` only, which made them unreachable for | |
| 1106 | + * two whole groups of users: | |
| 1107 | + * | |
| 1108 | + * - Keyboard users. `visibility: hidden` also removes elements from the tab | |
| 1109 | + * order, so View / Edit / Trash / Send Email / Download PDF / Duplicate could | |
| 1110 | + * never be focused at all. `:focus-within` above fixes that — tabbing into the | |
| 1111 | + * row now reveals them. | |
| 1112 | + * - Touch users. There is no hover on a phone or tablet, so every row action was | |
| 1113 | + * permanently invisible and there was no other way to reach them. | |
| 1114 | + * | |
| 1115 | + * On pointer-less devices, and on the narrow widths WordPress itself treats as | |
| 1116 | + * mobile admin, the actions are simply always visible. | |
| 1117 | + */ | |
| 1118 | +@media (hover: none), (max-width: 782px) { | |
| 1119 | + .row-actions { | |
| 1120 | + visibility: visible; | |
| 1121 | + } | |
| 1122 | +} | |
| 1123 | + | |
| 1035 | 1124 | .row-actions span a { |
| 1036 | 1125 | color: #6366f1; /* indigo-500 */ |
| 1037 | 1126 | text-decoration: none; |
| 1038 | 1127 | transition: all 0.2s; |
| @@ -1524,38 +1613,8 @@ | ||
| 1524 | 1613 | e.preventDefault(); |
| 1525 | 1614 | EasyInvoiceConfirmation.showFeatureUpgrade('Invoice Export', 'Export your invoices to CSV, Excel, or PDF format for backup, analysis, or sharing with your team.'); |
| 1526 | 1615 | }); |
| 1527 | 1616 | |
| 1528 | - // Handle "Create Sample Invoice" button click | |
| 1529 | - $('#easy-invoice-create-sample').on('click', function() { | |
| 1530 | - var $button = $(this); | |
| 1531 | - var original_text = $button.html(); | |
| 1532 | - $button.html('Creating...').prop('disabled', true); | |
| 1533 | - | |
| 1534 | - $.ajax({ | |
| 1535 | - url: ajaxurl, // WordPress AJAX URL | |
| 1536 | - type: 'POST', | |
| 1537 | - data: { | |
| 1538 | - action: 'easy_invoice_create_sample_invoice', | |
| 1539 | - nonce: '<?php echo wp_create_nonce("easy_invoice_admin_nonce"); ?>' // Make sure this nonce matches the one checked in PHP | |
| 1540 | - }, | |
| 1541 | - success: function(response) { | |
| 1542 | - if (response.success) { | |
| 1543 | - EasyInvoiceToast.success(response.data.message + ' You can edit it at: ' + response.data.edit_link); | |
| 1544 | - // Optionally, refresh the page or redirect | |
| 1545 | - window.location.reload(); | |
| 1546 | - } else { | |
| 1547 | - EasyInvoiceToast.error('Error: ' + response.data.message); | |
| 1548 | - } | |
| 1549 | - }, | |
| 1550 | - error: function(jqXHR, textStatus, errorThrown) { | |
| 1551 | - EasyInvoiceToast.error('AJAX Error: ' + textStatus + ' - ' + errorThrown); | |
| 1552 | - }, | |
| 1553 | - complete: function() { | |
| 1554 | - $button.html(original_text).prop('disabled', false); | |
| 1555 | - } | |
| 1556 | - }); | |
| 1557 | - }); | |
| 1558 | 1617 | }); |
| 1559 | 1618 | </script> |
| 1560 | 1619 | |
| 1561 | 1620 | <div id="new-invoice-modal" class="fixed inset-0 bg-gray-600 bg-opacity-75 overflow-y-auto h-full w-full z-50 hidden"> |
| @@ -1577,9 +1636,9 @@ | ||
| 1577 | 1636 | id="new_invoice_title" |
| 1578 | 1637 | required |
| 1579 | 1638 | placeholder="Enter invoice title..." |
| 1580 | 1639 | class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-3 px-4 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm transition-colors duration-200"> |
| 1581 | - <p class="mt-2 text-sm text-gray-500">This will be the title of your invoice</p> | |
| 1640 | + <p class="mt-2 text-sm text-gray-500"><?php esc_html_e('This will be the title of your invoice', 'easy-invoice'); ?></p> | |
| 1582 | 1641 | </div> |
| 1583 | 1642 | |
| 1584 | 1643 | <div class="flex justify-end space-x-3 pt-4"> |
| 1585 | 1644 | <button type="button" id="cancel-new-invoice" |
| @@ -1600,10 +1659,10 @@ | ||
| 1600 | 1659 | <script> |
| 1601 | 1660 | jQuery(document).ready(function($) { |
| 1602 | 1661 | // Initialize easyInvoice object for AJAX calls |
| 1603 | 1662 | window.easyInvoice = { |
| 1604 | - ajaxUrl: '<?php echo admin_url('admin-ajax.php'); ?>', | |
| 1605 | - nonce: '<?php echo wp_create_nonce('easy_invoice_nonce'); ?>', | |
| 1663 | + ajaxUrl: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>', | |
| 1664 | + nonce: '<?php echo esc_attr(wp_create_nonce('easy_invoice_nonce')); ?>', | |
| 1606 | 1665 | isPro: <?php echo easy_invoice_has_pro() ? 'true' : 'false'; ?> |
| 1607 | 1666 | }; |
| 1608 | 1667 | |
| 1609 | 1668 | // New Invoice Modal Functionality |
| @@ -1644,9 +1703,9 @@ | ||
| 1644 | 1703 | var $message = $('#new-invoice-message'); |
| 1645 | 1704 | var title = $('#new_invoice_title').val().trim(); |
| 1646 | 1705 | |
| 1647 | 1706 | if (!title) { |
| 1648 | - $message.removeClass('hidden').html('<div class="text-red-600 text-sm">Please enter an invoice title.</div>'); | |
| 1707 | + $message.removeClass('hidden').html('<div class="text-red-600 text-sm"><?php esc_html_e('Please enter an invoice title.', 'easy-invoice'); ?></div>'); | |
| 1649 | 1708 | return; |
| 1650 | 1709 | } |
| 1651 | 1710 | |
| 1652 | 1711 | // Show loading state |
| @@ -1663,9 +1722,9 @@ | ||
| 1663 | 1722 | }, |
| 1664 | 1723 | success: function(response) { |
| 1665 | 1724 | if (response.success) { |
| 1666 | 1725 | // Show success message |
| 1667 | - $message.removeClass('hidden').html('<div class="text-green-600 text-sm">Invoice created successfully! Redirecting...</div>'); | |
| 1726 | + $message.removeClass('hidden').html('<div class="text-green-600 text-sm"><?php esc_html_e('Invoice created successfully! Redirecting...', 'easy-invoice'); ?></div>'); | |
| 1668 | 1727 | |
| 1669 | 1728 | // Redirect to the builder page with the new invoice ID |
| 1670 | 1729 | setTimeout(function() { |
| 1671 | 1730 | window.location.href = response.data.redirect_url; |
| @@ -1675,9 +1734,9 @@ | ||
| 1675 | 1734 | $submitBtn.prop('disabled', false).html('Create Invoice'); |
| 1676 | 1735 | } |
| 1677 | 1736 | }, |
| 1678 | 1737 | error: function() { |
| 1679 | - $message.removeClass('hidden').html('<div class="text-red-600 text-sm">Error connecting to server. Please try again.</div>'); | |
| 1738 | + $message.removeClass('hidden').html('<div class="text-red-600 text-sm"><?php esc_html_e('Error connecting to server. Please try again.', 'easy-invoice'); ?></div>'); | |
| 1680 | 1739 | $submitBtn.prop('disabled', false).html('Create Invoice'); |
| 1681 | 1740 | } |
| 1682 | 1741 | }); |
| 1683 | 1742 | }); |