/**
* Invoice Preview JavaScript
*
* Handles all functionality for the invoice preview page.
*/
(function($) {
'use strict';
// Invoice Preview Object
const InvoicePreview = {
// Store data
data: {},
// Initialize
init: function() {
// Set up variables
this.invoiceContainer = $('.invoice-preview-container');
this.loadingSection = $('.invoice-preview-loading');
this.errorSection = $('.invoice-preview-error');
this.contentSection = $('.invoice-preview-content');
// Get invoice ID from localized variables
this.invoiceId = easy_invoice_vars.invoice_id;
// Set up event listeners
this.bindEvents();
// Load invoice data
this.loadInvoiceData();
},
// Bind events
bindEvents: function() {
// Print button
$(document).on('click', '#print-invoice', this.printInvoice);
// Download PDF button
$(document).on('click', '#download-pdf', this.downloadPdf);
// Send Email button
$(document).on('click', '#email-invoice', this.sendEmail);
},
// Load invoice data via AJAX
loadInvoiceData: function() {
const self = this;
// Show loading, hide content and error
this.loadingSection.show();
this.contentSection.hide();
this.errorSection.hide();
},
// Render invoice data
renderInvoice: function() {
const data = this.data;
// Set invoice status class
this.invoiceContainer.removeClass('status-draft status-pending status-paid status-overdue status-cancelled');
this.invoiceContainer.addClass('status-' + data.invoice.status);
// Render invoice info
this.renderInvoiceInfo();
// Render customer info
this.renderCustomerInfo();
// Render items
this.renderItems();
// Render totals
this.renderTotals();
// Render notes and payment instructions
this.renderNotesAndPayment();
},
// Render invoice info
renderInvoiceInfo: function() {
const invoice = this.data.invoice;
// Invoice number
$('#invoice-number').text(invoice.number);
// Invoice date
$('#invoice-date').text(invoice.date);
// Invoice due date
$('#invoice-due-date').text(invoice.due_date);
// Invoice status
$('#invoice-status').text(invoice.status_label)
.removeClass('status-draft status-pending status-paid status-overdue status-cancelled')
.addClass('status-' + invoice.status);
},
// Render customer info
renderCustomerInfo: function() {
const customer = this.data.customer;
// Customer name
$('#customer-name').text(customer.name);
// Customer contact
$('#customer-email').text(customer.email);
$('#customer-phone').text(customer.phone);
// Customer address
$('#customer-address').html(this.formatAddress(customer.address));
},
// Render items
renderItems: function() {
const items = this.data.items;
const itemsContainer = $('#invoice-items tbody');
// Clear existing items
itemsContainer.empty();
// Add items
$.each(items, function(index, item) {
const row = $('
');
// Item description
row.append($('| ').addClass('item-description').html(
' ' + item.name + ' ' +
(item.description ? '' + item.description + ' ' : '')
));
// Item quantity
row.append($(' | ').addClass('item-quantity').text(item.quantity));
// Item price
row.append($(' | ').addClass('item-price').text(
InvoicePreview.formatMoney(item.price)
));
// Item amount
row.append($(' | ').addClass('item-amount').text(
InvoicePreview.formatMoney(item.amount)
));
// Add row to container
itemsContainer.append(row);
});
},
// Render totals
renderTotals: function() {
const totals = this.data.totals;
// Subtotal
$('#invoice-subtotal').text(this.formatMoney(totals.subtotal));
// Discount row
const discountRow = $('#invoice-discount-row');
if (totals.discount > 0) {
$('#invoice-discount').text(this.formatMoney(totals.discount));
if (totals.discount_type === 'percentage') {
$('#invoice-discount-label').text(
easy_invoice_vars.i18n.discount + ' (' + totals.discount_rate + '%)'
);
}
discountRow.show();
} else {
discountRow.hide();
}
// Tax row
const taxRow = $('#invoice-tax-row');
if (totals.tax_rate > 0) {
$('#invoice-tax').text(this.formatMoney(totals.tax));
$('#invoice-tax-label').text(
easy_invoice_vars.i18n.tax + ' (' + totals.tax_rate + '%)'
);
taxRow.show();
} else {
taxRow.hide();
}
// Total
$('#invoice-total').text(this.formatMoney(totals.total));
},
// Render notes and payment
renderNotesAndPayment: function() {
const payment = this.data.payment;
const notes = this.data.notes;
// Notes
if (notes) {
$('#invoice-notes').html(notes);
$('#notes-section').show();
} else {
$('#notes-section').hide();
}
// Payment method
if (payment.method) {
$('#invoice-payment-method').text(payment.method);
$('#payment-method-row').show();
} else {
$('#payment-method-row').hide();
}
// Payment instructions
if (payment.instructions) {
$('#invoice-payment-instructions').html(payment.instructions);
$('#payment-instructions-section').show();
} else {
$('#payment-instructions-section').hide();
}
},
// Format address
formatAddress: function(address) {
if (!address) return '';
return address.replace(/\n/g, ' ');
},
// Format money
formatMoney: function(amount) {
return easy_invoice_vars.currency_symbol + parseFloat(amount).toFixed(2);
},
// Show error message
showError: function(message) {
// Set error message
$('.invoice-preview-error-message').text(message);
// Hide loading and content, show error
this.loadingSection.hide();
this.contentSection.hide();
this.errorSection.show();
},
// Print invoice
printInvoice: function(e) {
e.preventDefault();
window.print();
},
// Download PDF
downloadPdf: function(e) {
e.preventDefault();
// Get button element
const button = $(e.currentTarget);
const originalText = button.html();
// Disable button and show loading state
button.prop('disabled', true)
.html('' + easy_invoice_vars.i18n.generating);
// Use the new PDF generator that captures HTML directly
if (typeof InvoicePdfGenerator !== 'undefined') {
const pdfGenerator = new InvoicePdfGenerator();
pdfGenerator.generatePDF();
// Show success message after a short delay
setTimeout(function() {
EasyInvoiceToast.success("PDF generated successfully");
}, 2000);
} else {
EasyInvoiceToast.error("PDF generator not available");
}
// Restore button to original state with delay
setTimeout(function() {
button.prop('disabled', false).html(originalText);
}, 1000);
},
// Send email
sendEmail: function(e) {
e.preventDefault();
const button = $(this);
const originalText = button.html();
// Disable button and show loading
button.prop('disabled', true)
.html('' + easy_invoice_vars.i18n.sending);
// Make AJAX request
$.ajax({
url: easy_invoice_vars.ajax_url,
type: 'POST',
data: {
action: 'easy_invoice_send_email',
nonce: easy_invoice_vars.nonce,
invoice_id: InvoicePreview.invoiceId
},
success: function(response) {
if (response.success) {
// Show success message
if (typeof EasyInvoiceToast !== 'undefined') {
EasyInvoiceToast.show('success', response.data.message || easy_invoice_vars.i18n.email_sent);
}
} else {
// Show error
if (typeof EasyInvoiceToast !== 'undefined') {
EasyInvoiceToast.show('error', response.data.message || easy_invoice_vars.i18n.email_error);
}
}
// Restore button
button.prop('disabled', false).html(originalText);
},
error: function() {
// Show error
if (typeof EasyInvoiceToast !== 'undefined') {
EasyInvoiceToast.show('error', easy_invoice_vars.i18n.error_connection);
}
// Restore button
button.prop('disabled', false).html(originalText);
}
});
},
// Get parameter by name from URL
getParameterByName: function(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
const regex = new RegExp('[?&]' + name + '(=([^]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
};
// Initialize on document ready
$(document).ready(function() {
InvoicePreview.init();
});
})(jQuery); |