PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.3.3
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.3.3
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 / assets / js / invoice-preview.js

invoice-preview.js in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.3.3, at assets/js/invoice-preview.js

341 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Invoice Preview JavaScript
3 *
4 * Handles all functionality for the invoice preview page.
5 */
6 (function($) {
7 'use strict';
8
9 // Invoice Preview Object
10 const InvoicePreview = {
11 // Store data
12 data: {},
13
14 // Initialize
15 init: function() {
16 // Set up variables
17 this.invoiceContainer = $('.invoice-preview-container');
18 this.loadingSection = $('.invoice-preview-loading');
19 this.errorSection = $('.invoice-preview-error');
20 this.contentSection = $('.invoice-preview-content');
21
22 // Get invoice ID from localized variables
23 this.invoiceId = easy_invoice_vars.invoice_id;
24
25 // Set up event listeners
26 this.bindEvents();
27
28 // Load invoice data
29 this.loadInvoiceData();
30 },
31
32 // Bind events
33 bindEvents: function() {
34 // Print button
35 $(document).on('click', '#print-invoice', this.printInvoice);
36
37 // Download PDF button
38 $(document).on('click', '#download-pdf', this.downloadPdf);
39
40 // Send Email button
41 $(document).on('click', '#email-invoice', this.sendEmail);
42 },
43
44 // Load invoice data via AJAX
45 loadInvoiceData: function() {
46 const self = this;
47
48 // Show loading, hide content and error
49 this.loadingSection.show();
50 this.contentSection.hide();
51 this.errorSection.hide();
52
53 },
54
55 // Render invoice data
56 renderInvoice: function() {
57 const data = this.data;
58
59 // Set invoice status class
60 this.invoiceContainer.removeClass('status-draft status-pending status-paid status-overdue status-cancelled');
61 this.invoiceContainer.addClass('status-' + data.invoice.status);
62
63 // Render invoice info
64 this.renderInvoiceInfo();
65
66 // Render customer info
67 this.renderCustomerInfo();
68
69 // Render items
70 this.renderItems();
71
72 // Render totals
73 this.renderTotals();
74
75 // Render notes and payment instructions
76 this.renderNotesAndPayment();
77 },
78
79 // Render invoice info
80 renderInvoiceInfo: function() {
81 const invoice = this.data.invoice;
82
83 // Invoice number
84 $('#invoice-number').text(invoice.number);
85
86 // Invoice date
87 $('#invoice-date').text(invoice.date);
88
89 // Invoice due date
90 $('#invoice-due-date').text(invoice.due_date);
91
92 // Invoice status
93 $('#invoice-status').text(invoice.status_label)
94 .removeClass('status-draft status-pending status-paid status-overdue status-cancelled')
95 .addClass('status-' + invoice.status);
96 },
97
98 // Render customer info
99 renderCustomerInfo: function() {
100 const customer = this.data.customer;
101
102 // Customer name
103 $('#customer-name').text(customer.name);
104
105 // Customer contact
106 $('#customer-email').text(customer.email);
107 $('#customer-phone').text(customer.phone);
108
109 // Customer address
110 $('#customer-address').html(this.formatAddress(customer.address));
111 },
112
113 // Render items
114 renderItems: function() {
115 const items = this.data.items;
116 const itemsContainer = $('#invoice-items tbody');
117
118 // Clear existing items
119 itemsContainer.empty();
120
121 // Add items
122 $.each(items, function(index, item) {
123 const row = $('<tr>');
124
125 // Item description
126 row.append($('<td>').addClass('item-description').html(
127 '<div class="item-name">' + item.name + '</div>' +
128 (item.description ? '<div class="item-description-text">' + item.description + '</div>' : '')
129 ));
130
131 // Item quantity
132 row.append($('<td>').addClass('item-quantity').text(item.quantity));
133
134 // Item price
135 row.append($('<td>').addClass('item-price').text(
136 InvoicePreview.formatMoney(item.price)
137 ));
138
139 // Item amount
140 row.append($('<td>').addClass('item-amount').text(
141 InvoicePreview.formatMoney(item.amount)
142 ));
143
144 // Add row to container
145 itemsContainer.append(row);
146 });
147 },
148
149 // Render totals
150 renderTotals: function() {
151 const totals = this.data.totals;
152
153 // Subtotal
154 $('#invoice-subtotal').text(this.formatMoney(totals.subtotal));
155
156 // Discount row
157 const discountRow = $('#invoice-discount-row');
158 if (totals.discount > 0) {
159 $('#invoice-discount').text(this.formatMoney(totals.discount));
160 if (totals.discount_type === 'percentage') {
161 $('#invoice-discount-label').text(
162 easy_invoice_vars.i18n.discount + ' (' + totals.discount_rate + '%)'
163 );
164 }
165 discountRow.show();
166 } else {
167 discountRow.hide();
168 }
169
170 // Tax row
171 const taxRow = $('#invoice-tax-row');
172 if (totals.tax_rate > 0) {
173 $('#invoice-tax').text(this.formatMoney(totals.tax));
174 $('#invoice-tax-label').text(
175 easy_invoice_vars.i18n.tax + ' (' + totals.tax_rate + '%)'
176 );
177 taxRow.show();
178 } else {
179 taxRow.hide();
180 }
181
182 // Total
183 $('#invoice-total').text(this.formatMoney(totals.total));
184 },
185
186 // Render notes and payment
187 renderNotesAndPayment: function() {
188 const payment = this.data.payment;
189 const notes = this.data.notes;
190
191 // Notes
192 if (notes) {
193 $('#invoice-notes').html(notes);
194 $('#notes-section').show();
195 } else {
196 $('#notes-section').hide();
197 }
198
199 // Payment method
200 if (payment.method) {
201 $('#invoice-payment-method').text(payment.method);
202 $('#payment-method-row').show();
203 } else {
204 $('#payment-method-row').hide();
205 }
206
207 // Payment instructions
208 if (payment.instructions) {
209 $('#invoice-payment-instructions').html(payment.instructions);
210 $('#payment-instructions-section').show();
211 } else {
212 $('#payment-instructions-section').hide();
213 }
214 },
215
216 // Format address
217 formatAddress: function(address) {
218 if (!address) return '';
219
220 return address.replace(/\n/g, '<br>');
221 },
222
223 // Format money
224 formatMoney: function(amount) {
225 return easy_invoice_vars.currency_symbol + parseFloat(amount).toFixed(2);
226 },
227
228 // Show error message
229 showError: function(message) {
230 // Set error message
231 $('.invoice-preview-error-message').text(message);
232
233 // Hide loading and content, show error
234 this.loadingSection.hide();
235 this.contentSection.hide();
236 this.errorSection.show();
237 },
238
239 // Print invoice
240 printInvoice: function(e) {
241 e.preventDefault();
242 window.print();
243 },
244
245 // Download PDF
246 downloadPdf: function(e) {
247 e.preventDefault();
248
249 // Get button element
250 const button = $(e.currentTarget);
251 const originalText = button.html();
252
253 // Disable button and show loading state
254 button.prop('disabled', true)
255 .html('<i class="fas fa-spinner fa-spin mr-2"></i>' + easy_invoice_vars.i18n.generating);
256
257 // Use the new PDF generator that captures HTML directly
258 if (typeof InvoicePdfGenerator !== 'undefined') {
259 const pdfGenerator = new InvoicePdfGenerator();
260 pdfGenerator.generatePDF();
261
262 // Show success message after a short delay
263 setTimeout(function() {
264 EasyInvoiceToast.success("PDF generated successfully");
265 }, 2000);
266 } else {
267 EasyInvoiceToast.error("PDF generator not available");
268 }
269
270 // Restore button to original state with delay
271 setTimeout(function() {
272 button.prop('disabled', false).html(originalText);
273 }, 1000);
274 },
275
276 // Send email
277 sendEmail: function(e) {
278 e.preventDefault();
279
280 const button = $(this);
281 const originalText = button.html();
282
283 // Disable button and show loading
284 button.prop('disabled', true)
285 .html('<i class="fas fa-spinner fa-spin mr-2"></i>' + easy_invoice_vars.i18n.sending);
286
287 // Make AJAX request
288 $.ajax({
289 url: easy_invoice_vars.ajax_url,
290 type: 'POST',
291 data: {
292 action: 'easy_invoice_send_email',
293 nonce: easy_invoice_vars.nonce,
294 invoice_id: InvoicePreview.invoiceId
295 },
296 success: function(response) {
297 if (response.success) {
298 // Show success message
299 if (typeof EasyInvoiceToast !== 'undefined') {
300 EasyInvoiceToast.show('success', response.data.message || easy_invoice_vars.i18n.email_sent);
301 }
302 } else {
303 // Show error
304 if (typeof EasyInvoiceToast !== 'undefined') {
305 EasyInvoiceToast.show('error', response.data.message || easy_invoice_vars.i18n.email_error);
306 }
307 }
308
309 // Restore button
310 button.prop('disabled', false).html(originalText);
311 },
312 error: function() {
313 // Show error
314 if (typeof EasyInvoiceToast !== 'undefined') {
315 EasyInvoiceToast.show('error', easy_invoice_vars.i18n.error_connection);
316 }
317
318 // Restore button
319 button.prop('disabled', false).html(originalText);
320 }
321 });
322 },
323
324 // Get parameter by name from URL
325 getParameterByName: function(name, url) {
326 if (!url) url = window.location.href;
327 name = name.replace(/[\[\]]/g, '\\$&');
328 const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
329 results = regex.exec(url);
330 if (!results) return null;
331 if (!results[2]) return '';
332 return decodeURIComponent(results[2].replace(/\+/g, ' '));
333 }
334 };
335
336 // Initialize on document ready
337 $(document).ready(function() {
338 InvoicePreview.init();
339 });
340
341 })(jQuery);