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
easy-invoice / includes / Admin / AdminAssets.php

AdminAssets.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.0, at includes/Admin/AdminAssets.php

525 lines 25.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Assets Class
4 *
5 * @package Easy_Invoice
6 * @subpackage Admin
7 */
8
9 namespace EasyInvoice\Admin;
10
11 use EasyInvoice\Constants\PagesSlugs;
12
13 /**
14 * AdminAssets Class
15 *
16 * Handles registration and enqueuing of admin CSS and JS assets.
17 */
18 class AdminAssets {
19 /**
20 * Register hooks
21 */
22 public function register() {
23 add_action('admin_enqueue_scripts', array($this, 'enqueueAdminAssets'));
24 }
25
26 /**
27 * Enqueue admin assets
28 *
29 * @param string $hook The current admin page
30 */
31 public function enqueueAdminAssets($hook) {
32 // Only load on our plugin pages
33 if (empty($hook) || strpos($hook, 'easy-invoice') === false) {
34 return;
35 }
36
37 // Enqueue styles
38 $this->enqueueStyles();
39
40 // Enqueue scripts
41 $this->enqueueScripts($hook);
42
43 // Localize script data
44 $this->localizeScripts($hook);
45 }
46
47 /**
48 * Enqueue stylesheets
49 */
50 private function enqueueStyles() {
51
52 // Tailwind: the purged ~47 KB build is the default; the full 2.8 MB
53 // dump stays on disk as the fallback.
54 //
55 // The purged file is the shipped v2 bundle with unused rules removed --
56 // NOT a v3 rebuild, which would rename utilities and change the palette.
57 // Every rule it keeps is byte-identical to the full file, so anything
58 // still on a page renders exactly as before. It was verified by
59 // pixel-diffing 41 admin screens (every core page, every addon page,
60 // three breakpoints, the drawer, a modal and toasts) against the full
61 // file: zero differing pixels. See tools/tailwind-build/README.md.
62 //
63 // A site that adds markup using utilities the plugin never uses --
64 // a custom template, a child theme -- can go back to the full file:
65 // update_option('easy_invoice_tailwind_purged', '0');
66 // or
67 // add_filter('easy_invoice_use_purged_tailwind', '__return_false');
68 //
69 // The option was previously opt-IN ('1' enabled the purged file). It is
70 // now opt-OUT: only an explicit '0' disables it. A site that had set
71 // '1' keeps working; a site that never set it gets the win.
72 //
73 // The file_exists check below means a deployment that lost the purged
74 // file falls back to the full one rather than 404-ing the stylesheet.
75 $purged_option = get_option('easy_invoice_tailwind_purged', '1');
76 $use_purged = apply_filters(
77 'easy_invoice_use_purged_tailwind',
78 '0' !== (string) $purged_option && false !== $purged_option
79 );
80 $purged_rel = 'assets/lib/tailwind/tailwind.purged.min.css';
81 $shipped_rel = 'assets/lib/tailwind/tailwind.min.css';
82 $tailwind_rel = ($use_purged && file_exists(EASY_INVOICE_PLUGIN_DIR . $purged_rel))
83 ? $purged_rel
84 : $shipped_rel;
85
86 wp_enqueue_style(
87 'easy-invoice-tailwind',
88 EASY_INVOICE_PLUGIN_URL . $tailwind_rel,
89 array(),
90 EASY_INVOICE_VERSION
91 );
92
93 // Colour names the views use that Tailwind v2 never had (amber, emerald,
94 // teal …) — without these every amber notice and emerald badge was unstyled.
95 wp_enqueue_style(
96 'easy-invoice-palette-ext',
97 EASY_INVOICE_PLUGIN_URL . 'assets/css/palette-ext.css',
98 array( 'easy-invoice-tailwind' ),
99 EASY_INVOICE_VERSION
100 );
101
102 $page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
103
104 // Main plugin layout + header strip alignment (always on Easy Invoice admin screens).
105 wp_enqueue_style(
106 'easy-invoice-main',
107 EASY_INVOICE_PLUGIN_URL . 'assets/css/easy-invoice.css',
108 array(),
109 EASY_INVOICE_VERSION
110 );
111
112 if($page === 'easy-invoice-builder') {
113 // Main admin styles
114
115 wp_enqueue_style(
116 'easy-invoice-preview',
117 EASY_INVOICE_PLUGIN_URL . 'assets/css/invoice-preview.css',
118 array(),
119 EASY_INVOICE_VERSION
120 );
121 }
122
123 // Font Awesome (~87 KB) is used by the heavyweight templates
124 // (clients, settings, reports, invoices, quotes, payments) but
125 // NOT by the lightweight admin pages — Dashboard, Addons grid,
126 // License, Free-vs-Pro, Join Community, and every addon-settings
127 // sub-page (those use dashicons). Skip enqueueing FA on the
128 // deny-listed pages to save the bandwidth and the parse cost.
129 // Filterable so site-specific custom templates can opt back in.
130 $fa_deny = (array) apply_filters('easy_invoice_font_awesome_skip_pages', [
131 'easy-invoice-dashboard',
132 'easy-invoice-addons',
133 'easy-invoice-license',
134 'easy-invoice-free-vs-pro',
135 'easy-invoice-join-community',
136 ]);
137 $is_addon_subpage = ($page !== '' && strpos($page, 'easy-invoice-addon-') === 0);
138 if (!in_array($page, $fa_deny, true) && !$is_addon_subpage) {
139 wp_enqueue_style(
140 'font-awesome',
141 EASY_INVOICE_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css',
142 array(),
143 EASY_INVOICE_VERSION
144 );
145 }
146
147
148 // RTL support.
149 //
150 // Strategy: 'append' (not 'replace') because Tailwind utility
151 // classes generated into easy-invoice.css remain valid LTR — only
152 // the small set of custom directional rules (sidebar borders,
153 // page-header negative margins, drawer offsets) need mirroring.
154 // WordPress loads assets/css/easy-invoice-rtl.css AFTER
155 // easy-invoice.css when is_rtl() is true; that file holds only the
156 // directional overrides.
157 //
158 // 'easy-invoice-main' is the handle of the file we want to extend
159 // (line 87 above). The previous handle 'easy-invoice-admin' did
160 // not exist and so the call was a no-op.
161 wp_style_add_data('easy-invoice-main', 'rtl', 'append');
162 }
163
164 /**
165 * Enqueue scripts
166 *
167 * @param string $hook The current admin page
168 */
169 private function enqueueScripts($hook) {
170 // Only load on Easy Invoice pages
171 if (empty($hook) || strpos($hook, 'easy-invoice') === false) {
172 return;
173 }
174
175 // Common admin scripts
176 wp_enqueue_script('jquery');
177 wp_enqueue_script('jquery-ui-core');
178 wp_enqueue_script('jquery-ui-datepicker');
179 wp_enqueue_script('wp-util');
180
181 // Add WordPress core dependencies that provide the 'wp' object
182 wp_enqueue_script('wp-api-fetch');
183 wp_enqueue_script('wp-i18n');
184 wp_enqueue_script('wp-a11y');
185 wp_enqueue_script('wp-hooks');
186
187 // Settings page script
188 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-settings') {
189 // settings.js calls .sortable() and .disableSelection() on the
190 // payment-gateway list, so jQuery UI Sortable must be present and
191 // printed first. SettingsController::enqueueAdminScripts() also
192 // registers this same handle; WordPress keeps whichever call runs
193 // first and silently drops the other's dependency array, and this
194 // one runs first (AdminAssets is wired up during EasyInvoice::init,
195 // before SettingsController::init). Declaring the jQuery UI handles
196 // here lets wp_scripts resolve the order rather than leaving it to
197 // the sequence the two enqueue callbacks happen to fire in.
198 //
199 // Only core handles are listed. select2 / easy-invoice-toast are
200 // also used by settings.js but are registered by SettingsController
201 // later in the request; naming them here would mean settings.js is
202 // dropped entirely if that callback ever stops running, so they are
203 // deliberately left out.
204 wp_enqueue_script(
205 'easy-invoice-settings',
206 EASY_INVOICE_PLUGIN_URL . 'assets/js/settings.js',
207 array('jquery', 'jquery-ui-core', 'jquery-ui-sortable', 'wp-util', 'wp-api-fetch', 'wp-i18n'),
208 EASY_INVOICE_VERSION,
209 true
210 );
211
212 // Localize the script with necessary data
213 wp_localize_script('easy-invoice-settings', 'easyInvoiceSettings', array(
214 'nonce' => wp_create_nonce('easy_invoice_settings'),
215 'ajaxurl' => admin_url('admin-ajax.php')
216 ));
217 return; // Don't load other scripts on settings page
218 }
219
220 // Load dependencies
221 wp_enqueue_script('jquery-ui-sortable');
222
223 // Main admin script
224 wp_enqueue_script('jquery');
225
226 // Register and enqueue our scripts
227 wp_register_script('easy-invoice-scripts', EASY_INVOICE_PLUGIN_URL . 'assets/js/easy-invoice.js', array('jquery', 'wp-api-fetch', 'wp-i18n', 'wp-a11y'), EASY_INVOICE_VERSION, true);
228 wp_enqueue_script('easy-invoice-scripts');
229
230 // Conditionally load client manager only on invoice pages (not quote pages or invoice builder)
231 if (!(isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-quote-builder' || $_GET['page'] === 'easy-invoice-builder'))) {
232 wp_register_script('easy-invoice-client-manager', EASY_INVOICE_PLUGIN_URL . 'assets/js/client-manager.js', array('jquery', 'easy-invoice-scripts', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
233 wp_enqueue_script('easy-invoice-client-manager');
234 }
235
236 // Load clients.js on the clients page
237 if (isset($_GET['page']) && $_GET['page'] === PagesSlugs::CLIENTS) {
238 wp_register_script('easy-invoice-clients', EASY_INVOICE_PLUGIN_URL . 'assets/js/clients.js', array('jquery', 'easy-invoice-scripts', 'easy-invoice-confirmation-modal', 'easy-invoice-toast', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
239 wp_enqueue_script('easy-invoice-clients');
240 }
241
242 wp_register_script('easy-invoice-payment-manager', EASY_INVOICE_PLUGIN_URL . 'assets/js/payment-manager.js', array('jquery', 'easy-invoice-scripts', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
243 wp_enqueue_script('easy-invoice-payment-manager');
244
245 // Tooltip manager - reusable across the plugin
246 wp_register_script('easy-invoice-tooltip', EASY_INVOICE_PLUGIN_URL . 'assets/js/tooltip-manager.js', array('jquery', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
247 wp_enqueue_script('easy-invoice-tooltip');
248
249 // Confirmation modal - reusable across the plugin
250 wp_register_script('easy-invoice-confirmation-modal', EASY_INVOICE_PLUGIN_URL . 'assets/js/confirmation-modal.js', array('jquery', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
251 wp_enqueue_script('easy-invoice-confirmation-modal');
252
253 // Toast notification system - global across the plugin
254 wp_register_script('easy-invoice-toast', EASY_INVOICE_PLUGIN_URL . 'assets/js/easy-invoice-toast.js', array('jquery', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
255 wp_enqueue_script('easy-invoice-toast');
256
257 // Bulk "Send Email" teaser — only on the invoice / quote listings.
258 // Always injects the option (even without Pro) so users discover the
259 // feature; when Pro is inactive, clicking Apply opens the upgrade
260 // dialog instead of doing the work.
261 $current_page = isset($_GET['page']) ? sanitize_key($_GET['page']) : '';
262 if (in_array($current_page, ['easy-invoice-all', 'easy-quote-all'], true)) {
263 wp_register_script(
264 'easy-invoice-bulk-send-email-teaser',
265 EASY_INVOICE_PLUGIN_URL . 'assets/js/bulk-send-email-teaser.js',
266 array('jquery', 'easy-invoice-confirmation-modal', 'easy-invoice-toast'),
267 EASY_INVOICE_VERSION,
268 true
269 );
270 wp_localize_script('easy-invoice-bulk-send-email-teaser', 'easyInvoiceBulkSendTeaser', array(
271 'hasPro' => function_exists('easy_invoice_has_pro') && easy_invoice_has_pro(),
272 'upgradeUrl' => 'https://matrixaddons.com/plugins/easy-invoice/#pricing',
273 'i18n' => array(
274 // Send Email
275 'send_email_label' => __('Send Email (Pro)', 'easy-invoice'),
276 'send_email_feature_name' => __('Bulk Send Email', 'easy-invoice'),
277 'send_email_feature_description'=> __('Select multiple invoices or quotes and send the configured "Available" email to every selected document\'s client in a single click. Includes a per-row success / failure report so you can spot deliverability problems immediately.', 'easy-invoice'),
278 // Export
279 'export_feature_name' => __('Bulk Export Selected', 'easy-invoice'),
280 'export_feature_description' => __('Export your selected invoices or quotes to a clean, accounting-ready CSV — perfect for QuickBooks, Xero, audit trails, or migrating to a new system.', 'easy-invoice'),
281 // Generic
282 'upgrade_required' => __('This action requires Easy Invoice Pro.', 'easy-invoice'),
283 ),
284 ));
285 wp_enqueue_script('easy-invoice-bulk-send-email-teaser');
286 }
287
288 // jsPDF + html2canvas for PDF generation - available on all Easy Invoice pages.
289 // Both are bundled in assets/js/vendors/ rather than loaded from a CDN:
290 // WordPress.org requires every asset to ship inside the plugin, and a remote
291 // CDN is a hard runtime dependency for a core feature.
292 wp_register_script('html2canvas', EASY_INVOICE_PLUGIN_URL . 'assets/js/vendors/html2canvas.min.js', array(), '1.4.1', true);
293 wp_register_script('jspdf', EASY_INVOICE_PLUGIN_URL . 'assets/js/vendors/jspdf.umd.min.js', array(), '2.5.1', true);
294 wp_enqueue_script('html2canvas');
295 wp_enqueue_script('jspdf');
296
297
298 // Conditionally load invoice-specific scripts only on invoice pages
299 if (isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-new' || $_GET['page'] === 'easy-invoice-builder')) {
300 // Invoice builder scripts
301 wp_register_script('easy-invoice-builder', EASY_INVOICE_PLUGIN_URL . 'assets/js/invoice-builder.js', array('jquery', 'easy-invoice-scripts', 'easy-invoice-payment-manager', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
302 wp_enqueue_script('easy-invoice-builder');
303
304 // Use invoice-save.js for comprehensive save functionality
305 wp_register_script('easy-invoice-save', EASY_INVOICE_PLUGIN_URL . 'assets/js/invoice-save.js', array('jquery', 'easy-invoice-scripts', 'easy-invoice-payment-manager', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
306 wp_enqueue_script('easy-invoice-save');
307 }
308
309 // Quote builder (full-screen editor)
310 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-quote-builder') {
311 wp_register_script(
312 'easy-quote-save',
313 EASY_INVOICE_PLUGIN_URL . 'assets/js/quote-save.js',
314 array('jquery', 'easy-invoice-scripts', 'easy-invoice-payment-manager', 'wp-api-fetch', 'wp-i18n'),
315 EASY_INVOICE_VERSION,
316 true
317 );
318 wp_enqueue_script('easy-quote-save');
319 }
320
321 if (isset($_GET['page']) && in_array($_GET['page'], array('easy-invoice-builder', 'easy-invoice-quote-builder'), true)) {
322 wp_enqueue_script(
323 'easy-invoice-builder-mobile-tabs',
324 EASY_INVOICE_PLUGIN_URL . 'assets/js/builder-mobile-tabs.js',
325 array('jquery'),
326 EASY_INVOICE_VERSION,
327 true
328 );
329 wp_enqueue_script(
330 'easy-invoice-builder-ux',
331 EASY_INVOICE_PLUGIN_URL . 'assets/js/builder-ux.js',
332 array('jquery', 'easy-invoice-scripts'),
333 EASY_INVOICE_VERSION,
334 true
335 );
336 }
337 }
338
339 /**
340 * Localize script data
341 *
342 * @param string $hook The current admin page
343 */
344 private function localizeScripts($hook) {
345 global $pagenow, $post;
346
347 // Get currency settings
348 $settings_controller = new \EasyInvoice\Controllers\SettingsController();
349 $settings = $settings_controller->getSettings();
350 $currency_code = $settings['easy_invoice_currency_code'] ?? 'USD';
351 $currency_position = $settings['easy_invoice_currency_position'] ?? 'left';
352 $currency_symbol = easy_invoice_get_currency_symbol();
353
354 $current_admin_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
355
356 // Default data
357 $script_data = array(
358 'ajaxUrl' => admin_url('admin-ajax.php'),
359 'nonce' => wp_create_nonce('easy_invoice_nonce'),
360 'i18n' => array(
361 'confirm_delete' => __('Are you sure you want to delete this invoice?', 'easy-invoice'),
362 'invoice_deleted' => __('Invoice deleted successfully', 'easy-invoice'),
363 'client_deleted' => __('Client deleted successfully', 'easy-invoice'),
364 'confirm_delete_client' => __('Are you sure you want to delete this client?', 'easy-invoice'),
365 'edit_invoice' => __('Edit Invoice', 'easy-invoice'),
366 'create_invoice' => __('Create Invoice', 'easy-invoice'),
367 'save' => __('Save', 'easy-invoice'),
368 'cancel' => __('Cancel', 'easy-invoice'),
369 'add_item' => __('Add Item', 'easy-invoice'),
370 'delete_item' => __('Delete Item', 'easy-invoice'),
371 'error' => __('An error occurred', 'easy-invoice'),
372 ),
373 );
374
375 if (in_array($current_admin_page, array('easy-invoice-builder', 'easy-invoice-quote-builder'), true)) {
376 $script_data['i18n'] = array_merge(
377 $script_data['i18n'],
378 array(
379 'saving' => __('Saving…', 'easy-invoice'),
380 'sending' => __('Sending…', 'easy-invoice'),
381 'save_invoice' => __('Save Invoice', 'easy-invoice'),
382 'update_invoice' => __('Update Invoice', 'easy-invoice'),
383 'save_quote' => __('Save Quote', 'easy-invoice'),
384 'update_quote' => __('Update Quote', 'easy-invoice'),
385 'send_invoice' => __('Send Invoice', 'easy-invoice'),
386 'send_quote' => __('Send Quote', 'easy-invoice'),
387 'save_first_invoice' => __('Please save the invoice before sending.', 'easy-invoice'),
388 'save_first_quote' => __('Please save the quote before sending.', 'easy-invoice'),
389 'email_sent_invoice' => __('Invoice email sent successfully.', 'easy-invoice'),
390 'email_sent_quote' => __('Quote email sent successfully.', 'easy-invoice'),
391 'email_error' => __('Error sending email.', 'easy-invoice'),
392 'network_error' => __('Error connecting to server.', 'easy-invoice'),
393 'tab_editor' => __('Editor', 'easy-invoice'),
394 'tab_preview' => __('Preview', 'easy-invoice'),
395 'confirm_send_invoice_title' => __('Send invoice by email?', 'easy-invoice'),
396 'confirm_send_invoice_message' => __('This will email the invoice to the client using your configured template.', 'easy-invoice'),
397 'confirm_send_quote_title' => __('Send quote by email?', 'easy-invoice'),
398 'confirm_send_quote_message' => __('This will email the quote to the client using your configured template.', 'easy-invoice'),
399 'confirm_send_confirm' => __('Send', 'easy-invoice'),
400 'confirm_cancel' => __('Cancel', 'easy-invoice'),
401 'builder_unsaved_warning' => __('You have unsaved changes. If you leave this page, your changes may be lost.', 'easy-invoice'),
402 'builder_title_hint' => __('The title above matches the document title field in the editor.', 'easy-invoice'),
403 'builder_shell_hint' => __('On smaller screens, use the tabs to switch between the editor and the live preview.', 'easy-invoice'),
404 'builder_shell_hint_dismiss' => __('Got it', 'easy-invoice'),
405 'send_invoice_confirm_browser' => __('Send this invoice by email?', 'easy-invoice'),
406 'send_quote_confirm_browser' => __('Send this quote by email?', 'easy-invoice'),
407 )
408 );
409 }
410
411 $script_data = array_merge(
412 $script_data,
413 array(
414 'urls' => array(
415 'preview' => admin_url('admin.php?action=easy_invoice_preview&invoice_id='),
416 'edit' => admin_url('admin.php?page=easy-invoice-new&id='),
417 ),
418 'settings' => array(
419 'currency_symbol' => $currency_symbol,
420 'currency_position' => $currency_position,
421 'currency_code' => $currency_code,
422 'decimal_separator' => $settings['easy_invoice_decimal_separator'] ?? '.',
423 'thousand_separator' => $settings['easy_invoice_thousands_separator'] ?? ',',
424 'decimal_places' => $settings['easy_invoice_decimal_precision'] ?? 2,
425 'date_format' => get_option('date_format', 'F j, Y'),
426 ),
427 'showAdjustField' => \EasyInvoice\Controllers\SettingsController::shouldShowInvoiceAdjustField(),
428 )
429 );
430
431 // Localize common scripts
432 wp_localize_script('easy-invoice-scripts', 'easyInvoice', $script_data);
433
434 // Conditionally localize client manager only when it's loaded
435 if (!(isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-quote-builder' || $_GET['page'] === 'easy-invoice-builder'))) {
436 wp_localize_script('easy-invoice-client-manager', 'easyInvoice', $script_data);
437 }
438
439 wp_localize_script('easy-invoice-payment-manager', 'easyInvoice', $script_data);
440 wp_localize_script('easy-invoice-tooltip', 'easyInvoice', $script_data);
441
442 // Conditionally localize invoice-specific scripts
443 if (isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-new' || $_GET['page'] === 'easy-invoice-builder')) {
444 // Add invoice-specific field configuration
445 $form_manager = new \EasyInvoice\Forms\Invoice\InvoiceFormManager();
446 $script_data['fieldConfig'] = $form_manager->getFieldConfigForJavaScript();
447
448 // Add additional data for the invoice edit page
449 $invoice_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
450 $invoice_items_json = '';
451
452 if ($invoice_id > 0) {
453 // Existing invoice - get its data
454 $repository = \EasyInvoice\Providers\InvoiceServiceProvider::getInvoiceRepository();
455 $invoice = $repository->find($invoice_id);
456
457 if ($invoice) {
458 $script_data['invoice_id'] = $invoice_id;
459 $script_data['editMode'] = true;
460
461 // Get invoice data for JavaScript
462 $invoice_data = $invoice->toArray();
463 $script_data['invoiceData'] = $invoice_data;
464
465 // Get invoice items
466 $items = $invoice->getItems();
467 $items_data = [];
468 foreach ($items as $item) {
469 $items_data[] = [
470 'id' => $item->getId(),
471 'name' => $item->getName(),
472 'description' => $item->getDescription(),
473 'quantity' => $item->getQuantity(),
474 'price' => $item->getPrice(),
475 'taxable' => $item->isTaxable(),
476 'total' => $item->getAmount()
477 ];
478 }
479 $script_data['invoiceItems'] = $items_data;
480
481 // Get client data if available
482 if ($invoice->getClientId()) {
483 $client_repository = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository();
484 $client = $client_repository->find($invoice->getClientId());
485 if ($client) {
486 $script_data['clientData'] = [
487 'id' => $client->getId(),
488 'name' => $client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName()),
489 'email' => $client->getEmail(),
490 'phone' => $client->getExtraInfo(),
491 'address' => $client->getAddress(),
492 'company' => $client->getBusinessClientName()
493 ];
494 }
495 }
496 }
497 } else {
498 // New invoice - set default items
499 $script_data['editMode'] = false;
500 $script_data['invoice_id'] = 0;
501 $default_items = [
502 [
503 'name' => '',
504 'description' => '',
505 'quantity' => 0,
506 'price' => 0,
507 'taxable' => true
508 ]
509 ];
510 $script_data['default_items'] = $default_items;
511 }
512
513 // Localize invoice-specific scripts
514 wp_localize_script('easy-invoice-builder', 'easyInvoice', $script_data);
515 wp_localize_script('easy-invoice-save', 'easyInvoice', $script_data);
516 }
517
518 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-quote-builder') {
519 // Override showAdjustField for quote pages
520 $script_data['showAdjustField'] = \EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField();
521 wp_localize_script('easy-quote-save', 'easyInvoice', $script_data);
522 }
523 }
524 }
525