PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
← All changes | templates/invoices/builder.php +162 -164 2.1.132.4.0 View file →
@@ -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>