| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | exit; |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | 7 | // Enqueue CSS and JS files for the builder page |
| 8 | -wp_enqueue_style('easy-invoice-form', plugin_dir_url(__FILE__) . '../../assets/css/invoice-form.css', array(), '1.0.0'); | |
| 9 | -wp_enqueue_script('easy-invoice-form', plugin_dir_url(__FILE__) . '../../assets/js/invoice-form.js', array('jquery'), '1.0.0', true); | |
| 10 | -wp_enqueue_script('easy-client-manager', plugin_dir_url(__FILE__) . '../../assets/js/client-manager.js', array('jquery'), '1.0.0', true); | |
| 8 | +wp_enqueue_style('easy-invoice-form', plugin_dir_url(__FILE__) . '../../assets/css/invoice-form.css', array(), EASY_INVOICE_VERSION); | |
| 9 | +wp_enqueue_script('easy-invoice-form', plugin_dir_url(__FILE__) . '../../assets/js/invoice-form.js', array('jquery'), EASY_INVOICE_VERSION, true); | |
| 10 | +wp_enqueue_script('easy-client-manager', plugin_dir_url(__FILE__) . '../../assets/js/client-manager.js', array('jquery'), EASY_INVOICE_VERSION, true); | |
| 11 | 11 | |
| 12 | 12 | use EasyInvoice\Providers\ClientServiceProvider; |
| 13 | 13 | use EasyInvoice\Providers\InvoiceServiceProvider; |
| 14 | 14 | |
| @@ -14,8 +14,20 @@ | ||
| 14 | 14 | |
| 15 | 15 | |
| 16 | 16 | // Get invoice ID if present in URL |
| 17 | 17 | $invoice_id = isset($_GET['invoice_id']) ? intval($_GET['invoice_id']) : 0; |
| 18 | +// A stale link (an invoice deleted since, or a quote id pasted here) must not fall | |
| 19 | +// through to the editor and preview as if it were a new invoice. | |
| 20 | +if ( $invoice_id > 0 ) { | |
| 21 | + $ei_builder_post = get_post( $invoice_id ); | |
| 22 | + if ( ! $ei_builder_post || \EasyInvoice\Constants\PostTypes::EASY_INVOICE_POST_TYPE !== $ei_builder_post->post_type ) { | |
| 23 | + wp_die( | |
| 24 | + esc_html__( 'That invoice does not exist or has been deleted.', 'easy-invoice' ), | |
| 25 | + esc_html__( 'Invoice not found', 'easy-invoice' ), | |
| 26 | + array( 'back_link' => true, 'response' => 404 ) | |
| 27 | + ); | |
| 28 | + } | |
| 29 | +} | |
| 18 | 30 | $invoice = null; |
| 19 | 31 | |
| 20 | 32 | // Check if this is a new invoice (no ID) |
| 21 | 33 | $is_new_invoice = ($invoice_id === 0); |
| @@ -23,10 +35,10 @@ | ||
| 23 | 35 | // Default values for new invoice |
| 24 | 36 | $invoice_number_service = easy_invoice_get_invoice_number_service(); |
| 25 | 37 | $invoice_data = array( |
| 26 | 38 | 'number' => $invoice_number_service->getNextNumber(), |
| 27 | - 'date' => date('Y-m-d'), | |
| 28 | - 'due_date' => date('Y-m-d', strtotime('+30 days')), | |
| 39 | + 'date' => current_time('Y-m-d'), | |
| 40 | + 'due_date' => wp_date('Y-m-d', strtotime('+30 days')), | |
| 29 | 41 | 'client_id' => '', |
| 30 | 42 | 'client_name' => '', |
| 31 | 43 | 'client_email' => '', |
| 32 | 44 | 'client_phone' => '', |
| @@ -51,9 +63,11 @@ | ||
| 51 | 63 | ); |
| 52 | 64 | |
| 53 | 65 | // Load clients for the dropdown |
| 54 | 66 | $client_repository = ClientServiceProvider::getClientRepository(); |
| 55 | -$clients = $client_repository->all(); | |
| 67 | +// The hidden #select-client mirror only needs the document's own client; the picker | |
| 68 | +// searches over AJAX. Loading every client here built a model per user on each open. | |
| 69 | +$clients = []; | |
| 56 | 70 | |
| 57 | 71 | // If editing an existing invoice, load its data |
| 58 | 72 | if ($invoice_id > 0) { |
| 59 | 73 | // Get the invoice from repository |
| @@ -122,72 +136,94 @@ | ||
| 122 | 136 | // Prepare client data for JavaScript |
| 123 | 137 | $client_data_json = json_encode($client_data ?? null); |
| 124 | 138 | |
| 125 | 139 | // Start output buffering to capture content |
| 140 | + | |
| 141 | +if ( $invoice_id && $invoice ) { | |
| 142 | + $ei_header_display_title = $invoice->title ?: $invoice->number ?: __( 'Untitled invoice', 'easy-invoice' ); | |
| 143 | +} else { | |
| 144 | + $ei_header_display_title = __( 'Create new invoice', 'easy-invoice' ); | |
| 145 | +} | |
| 126 | 146 | ?> |
| 127 | 147 | |
| 128 | -<div id="easy-invoice-content" class="h-screen flex flex-col"> | |
| 129 | - <!-- Header --> | |
| 130 | - <div class="bg-white shadow-sm w-full z-10"> | |
| 131 | - <div class="max-w-full mx-auto px-5"> | |
| 132 | - <div class="py-3 flex items-center justify-between"> | |
| 133 | - <div class="flex items-center"> | |
| 134 | - <a href="<?php echo admin_url('admin.php?page=easy-invoice-all'); ?>" | |
| 135 | - class="inline-flex items-center text-gray-600 hover:text-gray-900"> | |
| 136 | - <i class="fas fa-arrow-left mr-2"></i> | |
| 137 | - <span>Back to Invoices</span> | |
| 148 | +<div id="easy-invoice-content" class="h-screen flex flex-col bg-gray-50"> | |
| 149 | + <header class="ei-invoice-builder-header ei-app-header-sync bg-white border-b border-gray-200 shadow-sm w-full z-10 box-border"> | |
| 150 | + <div class="max-w-full mx-auto h-full px-4 sm:px-5"> | |
| 151 | + <div class="ei-app-header-inner flex flex-col gap-3 py-3 sm:gap-4 lg:flex-row lg:items-center lg:justify-between lg:gap-6 lg:py-0 lg:h-full"> | |
| 152 | + <div class="ei-app-header-leading flex min-w-0 flex-1 flex-col gap-3 sm:flex-row sm:items-center sm:gap-4"> | |
| 153 | + <a href="<?php echo esc_url( admin_url( 'admin.php?page=easy-invoice-all' ) ); ?>" | |
| 154 | + class="inline-flex shrink-0 items-center gap-2 self-start rounded-md text-sm font-medium text-gray-600 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"> | |
| 155 | + <svg class="h-4 w-4 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> | |
| 156 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path> | |
| 157 | + </svg> | |
| 158 | + <span><?php esc_html_e( 'Back to invoices', 'easy-invoice' ); ?></span> | |
| 138 | 159 | </a> |
| 160 | + <div class="min-w-0 flex-1 border-l-0 sm:border-l sm:border-gray-200 sm:pl-4"> | |
| 161 | + <p class="text-xs font-medium uppercase tracking-wide text-gray-500"><?php esc_html_e( 'Invoice', 'easy-invoice' ); ?></p> | |
| 162 | + <h1 id="ei-builder-header-title" class="mt-0.5 truncate text-lg font-semibold leading-tight text-gray-900 sm:text-xl" data-ei-default="<?php echo esc_attr( $ei_header_display_title ); ?>"> | |
| 163 | + <?php echo esc_html( $ei_header_display_title ); ?> | |
| 164 | + </h1> | |
| 165 | + <p class="sr-only"><?php esc_html_e( 'The title above matches the document title field in the editor.', 'easy-invoice' ); ?></p> | |
| 166 | + </div> | |
| 139 | 167 | </div> |
| 140 | - <h1 class="text-lg font-semibold text-gray-800"> | |
| 141 | - <?php | |
| 142 | - if ($invoice_id && $invoice) { | |
| 143 | - $title = $invoice->title ?: $invoice->number ?: 'Untitled Invoice'; | |
| 144 | - echo esc_html($title); | |
| 145 | - } else { | |
| 146 | - echo esc_html__('Create New Invoice', 'easy-invoice'); | |
| 168 | + <div class="ei-builder-header-actions flex w-full min-w-0 flex-wrap items-center justify-end gap-2 lg:w-auto lg:max-w-3xl lg:shrink-0"> | |
| 169 | + <?php | |
| 170 | + if ( $invoice && $invoice_id > 0 ) { | |
| 171 | + do_action( 'easy_invoice_builder_before_invoice_actions', $invoice ); | |
| 147 | 172 | } |
| 148 | 173 | ?> |
| 149 | - </h1> | |
| 150 | - <div class="flex items-center space-x-4"> | |
| 151 | - <?php if ($invoice && $invoice_id > 0): ?> | |
| 152 | - <div class="flex items-center space-x-2"> | |
| 153 | - <?php do_action('easy_invoice_builder_before_invoice_actions', $invoice); // Deposit info button appears here ?> | |
| 154 | - </div> | |
| 155 | - <?php endif; ?> | |
| 156 | - <button type="button" id="save-invoice-btn" class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm 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"> | |
| 157 | - <i class="fas fa-save mr-2"></i> | |
| 158 | - <span><?php echo (isset($_GET['invoice_id']) ? __('Update Invoice', 'easy-invoice') : __('Save Invoice', 'easy-invoice')); ?></span> | |
| 174 | + <button type="button" id="save-invoice-btn" class="inline-flex items-center gap-2 px-3 sm:px-4 py-2 border border-gray-300 shadow-sm 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" aria-busy="false"> | |
| 175 | + <svg class="h-4 w-4 text-gray-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> | |
| 176 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"></path> | |
| 177 | + </svg> | |
| 178 | + <span><?php echo isset( $_GET['invoice_id'] ) ? esc_html__( 'Update invoice', 'easy-invoice' ) : esc_html__( 'Save invoice', 'easy-invoice' ); ?></span> | |
| 159 | 179 | </button> |
| 160 | - <button type="button" id="send-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"> | |
| 161 | - <i class="fas fa-paper-plane mr-2"></i> | |
| 162 | - <span>Send Invoice</span> | |
| 180 | + <button type="button" id="send-invoice-btn" class="inline-flex items-center gap-2 px-3 sm: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" data-send-nonce="<?php echo esc_attr( wp_create_nonce( 'easy_invoice_send_invoice_email' ) ); ?>"> | |
| 181 | + <svg class="h-4 w-4 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true"> | |
| 182 | + <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"></path> | |
| 183 | + </svg> | |
| 184 | + <span><?php esc_html_e( 'Send invoice', 'easy-invoice' ); ?></span> | |
| 163 | 185 | </button> |
| 164 | 186 | </div> |
| 165 | 187 | </div> |
| 166 | 188 | </div> |
| 167 | - </div> | |
| 189 | + </header> | |
| 168 | 190 | |
| 169 | - <!-- Main Content --> | |
| 170 | - <div class="flex-grow overflow-y-auto"> | |
| 171 | - <div class="max-w-full mx-auto px-5 py-5"> | |
| 172 | - <div id="ei-invoice-builder-grid" class="grid grid-cols-1 lg:grid-cols-2 gap-8"> | |
| 173 | - <!-- Left Panel - Editable Fields --> | |
| 174 | - | |
| 175 | - <?php | |
| 176 | - include_once EASY_INVOICE_PLUGIN_DIR . 'templates/invoices/form.php'; | |
| 177 | - | |
| 178 | - include_once EASY_INVOICE_PLUGIN_DIR . 'templates/invoices/live-preview.php'; | |
| 179 | - ?> | |
| 191 | + <div class="flex-grow overflow-y-auto min-h-0"> | |
| 192 | + <div class="max-w-full mx-auto px-4 sm:px-5 py-4 sm:py-5"> | |
| 193 | + <div class="ei-builder-tabs lg:hidden flex rounded-lg bg-gray-100 p-1 gap-1 mb-4" role="tablist" aria-label="<?php echo esc_attr__( 'Editor panels', 'easy-invoice' ); ?>"> | |
| 194 | + <button type="button" role="tab" class="ei-builder-tab flex-1 rounded-md py-2 text-sm font-medium transition bg-white shadow-sm text-indigo-700" data-tab="editor" aria-selected="true"><?php esc_html_e( 'Editor', 'easy-invoice' ); ?></button> | |
| 195 | + <button type="button" role="tab" class="ei-builder-tab flex-1 rounded-md py-2 text-sm font-medium transition text-gray-600 hover:text-gray-800" data-tab="preview" aria-selected="false"><?php esc_html_e( 'Preview', 'easy-invoice' ); ?></button> | |
| 180 | 196 | </div> |
| 197 | + <div id="ei-builder-shell-hint" class="ei-builder-shell-hint mb-4 hidden rounded-md border border-indigo-100 bg-indigo-50/90 p-3 text-sm text-gray-700 shadow-sm lg:hidden" role="status" hidden> | |
| 198 | + <div class="flex items-start gap-3"> | |
| 199 | + <span class="mt-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-indigo-100 text-indigo-700" aria-hidden="true"> | |
| 200 | + <svg class="h-3.5 w-3.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg> | |
| 201 | + </span> | |
| 202 | + <p class="min-w-0 flex-1 leading-snug"><?php esc_html_e( 'On smaller screens, use the tabs to switch between the editor and the live preview.', 'easy-invoice' ); ?></p> | |
| 203 | + <button type="button" id="ei-builder-shell-hint-dismiss" class="shrink-0 rounded-md px-2 py-1 text-xs font-medium text-indigo-700 hover:bg-indigo-100 focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
| 204 | + <?php esc_html_e( 'Got it', 'easy-invoice' ); ?> | |
| 205 | + </button> | |
| 206 | + </div> | |
| 207 | + </div> | |
| 208 | + <div id="ei-invoice-builder-grid" class="grid grid-cols-1 lg:grid-cols-2 gap-6 lg:gap-8"> | |
| 209 | + <div id="ei-builder-editor" class="min-w-0 ei-builder-panel-editor"> | |
| 210 | + <?php include_once EASY_INVOICE_PLUGIN_DIR . 'templates/invoices/form.php'; ?> | |
| 211 | + </div> | |
| 212 | + <div id="ei-builder-preview" class="min-w-0 ei-builder-panel-preview hidden lg:block"> | |
| 213 | + <?php include_once EASY_INVOICE_PLUGIN_DIR . 'templates/invoices/live-preview.php'; ?> | |
| 214 | + </div> | |
| 215 | + </div> | |
| 181 | 216 | |
| 182 | - <!-- Add Client Modal --> | |
| 183 | - <div id="add_client_modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-75 overflow-y-auto h-full w-full z-50"> | |
| 217 | + <div id="add_client_modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-75 overflow-y-auto h-full w-full z-50" role="dialog" aria-modal="true" aria-labelledby="ei-add-client-title"> | |
| 184 | 218 | <div class="relative top-20 mx-auto p-5 border w-11/12 md:w-2/3 lg:w-1/2 shadow-lg rounded-md bg-white"> |
| 185 | 219 | <div class="flex justify-between items-center mb-4"> |
| 186 | - <h3 class="text-lg font-medium text-gray-900">Add New Client</h3> | |
| 187 | - <button type="button" class="close-modal text-gray-400 hover:text-gray-500"> | |
| 188 | - <span class="sr-only">Close</span> | |
| 189 | - <i class="fas fa-times"></i> | |
| 220 | + <h3 id="ei-add-client-title" class="text-lg font-medium text-gray-900"><?php esc_html_e( 'Add new client', 'easy-invoice' ); ?></h3> | |
| 221 | + <button type="button" class="close-modal rounded-md p-1 text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
| 222 | + <span class="sr-only"><?php esc_html_e( 'Close', 'easy-invoice' ); ?></span> | |
| 223 | + <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> | |
| 224 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> | |
| 225 | + </svg> | |
| 190 | 226 | </button> |
| 191 | 227 | </div> |
| 192 | 228 | |
| 193 | 229 | <?php |
| @@ -204,133 +240,95 @@ | ||
| 204 | 240 | </div> |
| 205 | 241 | |
| 206 | 242 | <script type="text/javascript"> |
| 207 | 243 | jQuery(document).ready(function($) { |
| 208 | - // Initialize easyInvoice object for client manager | |
| 209 | - window.easyInvoice = { | |
| 210 | - ajaxUrl: '<?php echo admin_url('admin-ajax.php'); ?>', | |
| 211 | - nonce: '<?php echo wp_create_nonce('easy_invoice_nonce'); ?>', | |
| 212 | - clientData: <?php echo $client_data_json; ?>, | |
| 244 | + var base = { | |
| 245 | + ajaxUrl: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>', | |
| 246 | + nonce: '<?php echo esc_js( wp_create_nonce( 'easy_invoice_nonce' ) ); ?>', | |
| 247 | + clientData: <?php echo $client_data_json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>, | |
| 213 | 248 | isPro: <?php echo easy_invoice_has_pro() ? 'true' : 'false'; ?> |
| 214 | 249 | }; |
| 215 | - | |
| 216 | - // Handle Send Invoice button | |
| 217 | - $('#send-invoice-btn').on('click', function(e) { | |
| 250 | + window.easyInvoice = $.extend(true, {}, typeof window.easyInvoice === 'object' ? window.easyInvoice : {}, base); | |
| 251 | + | |
| 252 | + function t(key, fb) { | |
| 253 | + return (window.easyInvoice && easyInvoice.i18n && easyInvoice.i18n[key]) ? easyInvoice.i18n[key] : fb; | |
| 254 | + } | |
| 255 | + | |
| 256 | + var spin = '<svg class="ei-btn-spinner h-4 w-4 animate-spin inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>'; | |
| 257 | + var pendingSend = false; | |
| 258 | + | |
| 259 | + $(document).on('easy-invoice-saved', function (e, response) { | |
| 260 | + if (!pendingSend || !response || !response.success) { | |
| 261 | + return; | |
| 262 | + } | |
| 263 | + pendingSend = false; | |
| 264 | + if ($('#invoice-id').val() !== '0') { | |
| 265 | + sendInvoiceEmail(); | |
| 266 | + } | |
| 267 | + }); | |
| 268 | + $(document).on('easy-invoice-save-failed', function () { | |
| 269 | + pendingSend = false; | |
| 270 | + }); | |
| 271 | + | |
| 272 | + $('#send-invoice-btn').on('click', function (e) { | |
| 218 | 273 | e.preventDefault(); |
| 219 | - | |
| 220 | - // First save the invoice if it's not saved yet | |
| 221 | - if ($('#invoice-id').val() == '0') { | |
| 222 | - // Invoice not saved yet, save it first | |
| 223 | - $('#save-invoice-btn').click(); | |
| 224 | - | |
| 225 | - // Wait for save to complete, then send | |
| 226 | - setTimeout(function() { | |
| 227 | - if ($('#invoice-id').val() != '0') { | |
| 228 | - sendInvoiceEmail(); | |
| 229 | - } else { | |
| 230 | - if (typeof EasyInvoiceToast !== 'undefined') { | |
| 231 | - EasyInvoiceToast.warning('Please save the invoice first before sending.'); | |
| 232 | - } else { | |
| 233 | - console.log('Please save the invoice first before sending.'); | |
| 234 | - } | |
| 235 | - } | |
| 236 | - }, 2000); | |
| 237 | - } else { | |
| 238 | - // Invoice already saved, send directly | |
| 239 | - sendInvoiceEmail(); | |
| 274 | + if ($('#invoice-id').val() === '0') { | |
| 275 | + pendingSend = true; | |
| 276 | + $('#save-invoice-btn').trigger('click'); | |
| 277 | + return; | |
| 240 | 278 | } |
| 279 | + sendInvoiceEmail(); | |
| 241 | 280 | }); |
| 242 | - | |
| 281 | + | |
| 243 | 282 | function sendInvoiceEmail() { |
| 244 | - const invoiceId = $('#invoice-id').val(); | |
| 245 | - | |
| 246 | - if (invoiceId == '0') { | |
| 283 | + var invoiceId = $('#invoice-id').val(); | |
| 284 | + if (invoiceId === '0') { | |
| 247 | 285 | if (typeof EasyInvoiceToast !== 'undefined') { |
| 248 | - EasyInvoiceToast.warning('Please save the invoice first before sending.'); | |
| 249 | - } else { | |
| 250 | - console.log('Please save the invoice first before sending.'); | |
| 286 | + EasyInvoiceToast.warning(t('save_first_invoice', 'Please save the invoice before sending.')); | |
| 251 | 287 | } |
| 252 | 288 | return; |
| 253 | 289 | } |
| 254 | - | |
| 255 | - // Use the confirmation system instead of alert | |
| 256 | - if (typeof EasyInvoiceConfirmation !== 'undefined') { | |
| 257 | - EasyInvoiceConfirmation.confirmAction('send email', 'this invoice', function() { | |
| 258 | - // Show loading state | |
| 259 | - const $btn = $('#send-invoice-btn'); | |
| 260 | - const originalText = $btn.html(); | |
| 261 | - $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-2"></i>Sending...'); | |
| 262 | - | |
| 263 | - // Send AJAX request | |
| 264 | - $.ajax({ | |
| 265 | - url: window.easyInvoice.ajaxUrl, | |
| 266 | - type: 'POST', | |
| 267 | - data: { | |
| 268 | - action: 'easy_invoice_send_invoice_email', | |
| 269 | - invoice_id: invoiceId, | |
| 270 | - nonce: '<?php echo wp_create_nonce('easy_invoice_send_invoice_email'); ?>' | |
| 271 | - }, | |
| 272 | - success: function(response) { | |
| 273 | - if (response.success) { | |
| 274 | - if (typeof EasyInvoiceToast !== 'undefined') { | |
| 275 | - EasyInvoiceToast.success('Invoice email sent successfully!'); | |
| 276 | - } else { | |
| 277 | - console.log('Invoice email sent successfully!'); | |
| 278 | - } | |
| 279 | - } else { | |
| 280 | - if (typeof EasyInvoiceToast !== 'undefined') { | |
| 281 | - EasyInvoiceToast.error(response.data.message || 'Error sending email'); | |
| 282 | - } else { | |
| 283 | - console.log('Error sending email: ' + (response.data.message || 'Unknown error')); | |
| 284 | - } | |
| 290 | + var nonce = $('#send-invoice-btn').data('send-nonce') || '<?php echo esc_js( wp_create_nonce( 'easy_invoice_send_invoice_email' ) ); ?>'; | |
| 291 | + | |
| 292 | + var runAjax = function () { | |
| 293 | + var $btn = $('#send-invoice-btn'); | |
| 294 | + var original = $btn.html(); | |
| 295 | + $btn.prop('disabled', true).attr('aria-busy', 'true').html('<span class="inline-flex items-center gap-2">' + spin + '<span>' + t('sending', 'Sending…') + '</span></span>'); | |
| 296 | + $.ajax({ | |
| 297 | + url: window.easyInvoice.ajaxUrl, | |
| 298 | + type: 'POST', | |
| 299 | + data: { | |
| 300 | + action: 'easy_invoice_send_invoice_email', | |
| 301 | + invoice_id: invoiceId, | |
| 302 | + nonce: nonce | |
| 303 | + }, | |
| 304 | + success: function (response) { | |
| 305 | + if (response.success) { | |
| 306 | + if (typeof EasyInvoiceToast !== 'undefined') { | |
| 307 | + EasyInvoiceToast.success(t('email_sent_invoice', 'Invoice email sent successfully.')); | |
| 285 | 308 | } |
| 286 | - }, | |
| 287 | - error: function() { | |
| 309 | + } else { | |
| 310 | + var msg = (response.data && response.data.message) ? response.data.message : t('email_error', 'Error sending email.'); | |
| 288 | 311 | if (typeof EasyInvoiceToast !== 'undefined') { |
| 289 | - EasyInvoiceToast.error('Error connecting to server'); | |
| 290 | - } else { | |
| 291 | - console.log('Error connecting to server'); | |
| 312 | + EasyInvoiceToast.error(msg); | |
| 292 | 313 | } |
| 293 | - }, | |
| 294 | - complete: function() { | |
| 295 | - // Reset button | |
| 296 | - $btn.prop('disabled', false).html(originalText); | |
| 297 | 314 | } |
| 298 | - }); | |
| 315 | + }, | |
| 316 | + error: function () { | |
| 317 | + if (typeof EasyInvoiceToast !== 'undefined') { | |
| 318 | + EasyInvoiceToast.error(t('network_error', 'Error connecting to server.')); | |
| 319 | + } | |
| 320 | + }, | |
| 321 | + complete: function () { | |
| 322 | + $btn.prop('disabled', false).removeAttr('aria-busy').html(original); | |
| 323 | + } | |
| 299 | 324 | }); |
| 300 | - } else { | |
| 301 | - // Fallback to browser confirm if confirmation system not available | |
| 302 | - if (confirm('Send this invoice via email?')) { | |
| 303 | - // Show loading state | |
| 304 | - const $btn = $('#send-invoice-btn'); | |
| 305 | - const originalText = $btn.html(); | |
| 306 | - $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-2"></i>Sending...'); | |
| 307 | - | |
| 308 | - // Send AJAX request | |
| 309 | - $.ajax({ | |
| 310 | - url: window.easyInvoice.ajaxUrl, | |
| 311 | - type: 'POST', | |
| 312 | - data: { | |
| 313 | - action: 'easy_invoice_send_invoice_email', | |
| 314 | - invoice_id: invoiceId, | |
| 315 | - nonce: '<?php echo wp_create_nonce('easy_invoice_send_invoice_email'); ?>' | |
| 316 | - }, | |
| 317 | - success: function(response) { | |
| 318 | - if (response.success) { | |
| 319 | - alert('Invoice email sent successfully!'); | |
| 320 | - } else { | |
| 321 | - alert(response.data.message || 'Error sending email'); | |
| 322 | - } | |
| 323 | - }, | |
| 324 | - error: function() { | |
| 325 | - alert('Error connecting to server'); | |
| 326 | - }, | |
| 327 | - complete: function() { | |
| 328 | - // Reset button | |
| 329 | - $btn.prop('disabled', false).html(originalText); | |
| 330 | - } | |
| 331 | - }); | |
| 332 | - } | |
| 325 | + }; | |
| 326 | + | |
| 327 | + if (typeof EasyInvoiceConfirmation !== 'undefined') { | |
| 328 | + EasyInvoiceConfirmation.confirmSendDocument('invoice', runAjax); | |
| 329 | + } else if (window.confirm(t('send_invoice_confirm_browser', 'Send this invoice by email?'))) { | |
| 330 | + runAjax(); | |
| 333 | 331 | } |
| 334 | 332 | } |
| 335 | 333 | }); |
| 336 | 334 | </script> |