# easy-invoice/2.1.0/templates/invoices/single.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.1.0. 1,102 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.1.0/code/templates/invoices/single.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.1.0/raw/templates/invoices/single.php
- Modified: 2025-08-24T10:24:48+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.1.0/code/templates/invoices/single.php#L10-L20`.

```php
<?php
/**
 * Single Invoice Template (Bare)
 *
 * @package Easy_Invoice
 * @subpackage Templates
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// Get text settings for invoice actions
$text_settings = \EasyInvoice\Helpers\TemplateTextHelper::getInvoiceTextSettings();


// Hide the admin bar for this view
add_filter('show_admin_bar', '__return_false');

// Get invoice from WordPress query
global $post;
$invoice = null;

if ($post && $post->post_type === \EasyInvoice\Constants\PostTypes::EASY_INVOICE_POST_TYPE) {
    // Load invoice from post using the correct service provider
    $invoice = \EasyInvoice\Providers\InvoiceServiceProvider::getInvoiceRepository()->find($post->ID);
}

if (!$invoice) {
    wp_die(__('Invoice not found.', 'easy-invoice'));
}

// Initialize formatter for currency formatting
$formatter = new \EasyInvoice\Helpers\InvoiceFormatter($invoice);

// Stripe is handled by the Pro plugin

// Get the selected template for this invoice
$current_template = $invoice->getTemplate();
if (empty($current_template)) {
    $current_template = 'standard';
}

// Check if the template file exists
$template_file = EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/' . $current_template . '.php';

?><!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
    <meta charset="<?php bloginfo('charset'); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo esc_html($invoice->getTitle() ?: __('Invoice', 'easy-invoice')); ?></title>    
    <!-- Load jQuery and toast system for better user experience -->
    <script src="<?php echo esc_url(includes_url('js/jquery/jquery.min.js')); ?>"></script>
    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/easy-invoice-toast.js'); ?>"></script>
    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/confirmation-modal.js'); ?>"></script>
    
    <!-- Load jsPDF for PDF generation -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/document-pdf.js'); ?>"></script>
    
    <!-- Stripe.js is loaded by the Pro plugin when needed -->
    
    <!-- Add Font Awesome for payment icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    
    <!-- Payment panel JavaScript functions -->
    <?php do_action('easy_invoice_head'); ?>
    
    <script>
    // Simple payment panel toggle functionality
    function togglePaymentPanel() {
        const paymentPanel = document.getElementById('payment-panel');
        const toggleButton = document.getElementById('toggle-payment-panel');
        
        if (paymentPanel && toggleButton) {
            if (paymentPanel.style.display === 'none' || !paymentPanel.style.display) {
                // Show panel
                paymentPanel.style.display = 'block';
                setTimeout(() => {
                    paymentPanel.style.transform = 'translateX(0)';
                }, 10);
                toggleButton.textContent = '<?php _e('Hide Payment', 'easy-invoice'); ?>';
                toggleButton.style.background = '#6c757d';
            } else {
                // Hide panel
                paymentPanel.style.transform = 'translateX(100%)';
                setTimeout(() => {
                    paymentPanel.style.display = 'none';
                }, 300);
                toggleButton.textContent = '<?php echo esc_js($text_settings['pay_now']); ?>';
                toggleButton.style.background = '#27ae60';
            }
        }
    }
    
    function closePaymentPanel() {
        const paymentPanel = document.getElementById('payment-panel');
        const toggleButton = document.getElementById('toggle-payment-panel');
        
        if (paymentPanel && toggleButton) {
            paymentPanel.style.transform = 'translateX(100%)';
            setTimeout(() => {
                paymentPanel.style.display = 'none';
            }, 300);
            toggleButton.textContent = '<?php _e('Pay Now', 'easy-invoice'); ?>';
            toggleButton.style.background = '#27ae60';
        }
    }
    
    // Initialize payment panel on page load
    document.addEventListener('DOMContentLoaded', function() {
        const paymentPanel = document.getElementById('payment-panel');
        if (paymentPanel) {
            paymentPanel.style.transform = 'translateX(100%)';
        }
    });
    </script>
    
    <style>
        body { margin: 0; padding: 0; font-family: sans-serif; background: #eaeaea; color: #222; }
        .easy-invoice-invoice-container { max-width: 800px; margin: 40px auto; }
        h1, h2, h3 { margin-top: 0; }
        .invoice-actions { margin-top: 32px; text-align: center; }
        .invoice-actions button, .invoice-actions a { margin: 0 8px; padding: 10px 24px; border: none; border-radius: 4px; background: #6366f1; color: #fff; font-size: 1rem; cursor: pointer; text-decoration: none; }
        .invoice-actions button.pay { background: #10b981; }
        .invoice-actions button.decline { background: #f87171; }
        .template-not-found { text-align: center; padding: 40px; background: #fff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .template-not-found-icon { font-size: 48px; color: #dc3545; margin-bottom: 20px; }
        .template-not-found h3 { font-size: 24px; color: #32325d; margin-bottom: 10px; }
        .template-not-found p { color: #8898aa; margin-bottom: 10px; }
        
        /* Modal System Styles */
        .ei-modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 9999;
            opacity: 0;
            transition: opacity 0.3s ease;
        }
        
        .ei-modal-overlay.show {
            opacity: 1;
        }
        
        .ei-modal {
            background: white;
            border-radius: 8px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
            max-width: 500px;
            width: 90%;
            max-height: 80vh;
            overflow-y: auto;
            transform: scale(0.9);
            transition: transform 0.3s ease;
        }
        
        .ei-modal.show {
            transform: scale(1);
        }
        
        .ei-modal-header {
            padding: 20px 24px 0;
            display: flex;
            align-items: center;
            gap: 12px;
        }
        
        .ei-modal-icon {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
        }
        
        .ei-modal-icon.info {
            background: #dbeafe;
        }
        
        .ei-modal-icon.danger {
            background: #fee2e2;
        }
        
        .ei-modal-icon svg {
            width: 20px;
            height: 20px;
        }
        
        .ei-modal-title {
            margin: 0;
            font-size: 18px;
            font-weight: 600;
            color: #1f2937;
        }
        
        .ei-modal-body {
            padding: 16px 24px 20px;
        }
        
        .ei-modal-message {
            color: #6b7280;
            line-height: 1.5;
            white-space: pre-line;
        }
        
        .ei-modal-actions {
            padding: 0 24px 20px;
            display: flex;
            gap: 12px;
            justify-content: flex-end;
        }
        
        .ei-modal-btn {
            padding: 8px 16px;
            border: none;
            border-radius: 6px;
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            transition: background-color 0.2s ease;
        }
        
        .ei-modal-btn-primary {
            background: #3b82f6;
            color: white;
        }
        
        .ei-modal-btn-primary:hover {
            background: #2563eb;
        }
        
        .ei-modal-btn-secondary {
            background: #f3f4f6;
            color: #374151;
        }
        
        .ei-modal-btn-secondary:hover {
            background: #e5e7eb;
        }
        
        .ei-modal-btn-danger {
            background: #ef4444;
            color: white;
        }
        
        .ei-modal-btn-danger:hover {
            background: #dc2626;
        }
        
        .ei-modal-reason-field {
            margin-top: 16px;
        }
        
        .ei-modal-label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: #374151;
        }
        
        .ei-modal-textarea {
            width: 100%;
            padding: 12px;
            border: 1px solid #d1d5db;
            border-radius: 6px;
            font-family: inherit;
            font-size: 14px;
            line-height: 1.5;
            resize: vertical;
            min-height: 80px;
        }
        
        .ei-modal-textarea:focus {
            outline: none;
            border-color: #3b82f6;
            box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
        }
        
        .ei-modal-textarea.error {
            border-color: #ef4444;
        }
    </style>
</head>
<body>
    <div class="easy-invoice-invoice-container">
        <!-- Invoice Actions - Always show at the top regardless of template -->
        <div class="invoice-actions" style="margin-bottom: 32px;">
            <?php if ($invoice->getStatus() === 'unpaid'): ?>
                <form method="post" style="display:inline;">
                    <?php wp_nonce_field('easy_invoice_invoice_action', 'invoice_nonce'); ?>
                    <input type="hidden" name="invoice_id" value="<?php echo esc_attr($invoice->getId()); ?>">
                    <button type="submit" name="pay_invoice" class="pay"><?php echo esc_html($text_settings['pay_now']); ?></button>
                </form>
            <?php endif; ?>
            
            <!-- Additional action buttons -->
            <button type="button" onclick="printInvoiceContent()" style="background: #10b981;"><?php echo esc_html($text_settings['print']); ?></button>
            
            <button type="button" onclick="downloadInvoicePdf(<?php echo esc_js($invoice->getId()); ?>)" style="background: #f59e0b;">
                <?php echo esc_html($text_settings['download_pdf']); ?>
            </button>
            
            <button class="send-email-button" type="button" style="background: #8b5cf6; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">
                <?php echo esc_html($text_settings['send_email']); ?>
            </button>
            
            <!-- Pay Now button to toggle payment panel -->
            <?php 
            $invoice_status = $invoice->getStatus();

            $show_pay_button = $invoice  && in_array($invoice_status, ['unpaid', 'available']);
            ?>
            <?php if ($show_pay_button): ?>
                <button type="button" id="toggle-payment-panel" onclick="togglePaymentPanel()" style="background: #27ae60; color: white; padding: 10px 24px; border: none; border-radius: 4px; font-size: 1rem; cursor: pointer;">
                    <?php echo esc_html($text_settings['pay_now']); ?>
                </button>
            <?php endif; ?>
        </div>
        <?php do_action('easy_invoice_before_invoice_content_top', $invoice); ?>

        <!-- Main content area with invoice and payment panel -->
        <div class="invoice-layout" style="display: flex; gap: 32px; max-width: 1200px; margin: 0 auto;">
            <!-- Invoice content (left side) -->
            <div class="invoice-content" style="flex: 1; min-width: 0; position: relative;">
                <?php do_action('easy_invoice_invoice_view_content_top', $invoice); ?>
                <?php if (file_exists($template_file)): ?>
                    <?php
                    // Include the selected template file
                    include $template_file;
                    ?>
                <?php else: ?>
                    <!-- Template not found - fallback to basic display -->
                    <div class="template-not-found">
                        <div class="template-not-found-icon">
                            <i class="fas fa-exclamation-circle"></i>
                        </div>
                        <h3><?php _e('Template Not Found', 'easy-invoice'); ?></h3>
                        <p><?php printf(__('The selected template "%s" does not exist.', 'easy-invoice'), esc_html($current_template)); ?></p>
                        <p><?php _e('Please contact support if you believe this is an error.', 'easy-invoice'); ?></p>
                    </div>
                    
                    <!-- Fallback basic invoice display -->
                    <div class="invoice-header">
                        <h1><?php echo esc_html($invoice->getTitle() ?: __('Invoice', 'easy-invoice')); ?>
                            <span class="invoice-status status-<?php echo esc_attr($invoice->getStatus() ?: 'draft'); ?>"><?php echo esc_html(ucfirst($invoice->getStatus() ?: 'draft')); ?></span>
                        </h1>
                        <div><?php echo esc_html($invoice->getNumber()); ?> &bull; <?php echo esc_html(\EasyInvoice\Controllers\SettingsController::formatDate($invoice->getIssueDate())); ?></div>
                        <?php if ($invoice->getCustomerName()): ?>
                            <div style="margin-top: 12px;">
                                <strong><?php echo esc_html($invoice->getCustomerName()); ?></strong><br>
                                <?php echo esc_html($invoice->getCustomerEmail()); ?><br>
                                <?php echo esc_html($invoice->getCustomerAddress()); ?>
                            </div>
                        <?php endif; ?>
                    </div>

                    <?php if ($invoice->getNotes()): ?>
                        <div style="margin-bottom: 24px; color: #555;">
                            <?php echo nl2br(esc_html($invoice->getNotes())); ?>
                        </div>
                    <?php endif; ?>

                    <table class="invoice-items">
                        <thead>
                            <tr>
                                <th><?php _e('Item', 'easy-invoice'); ?></th>
                                <th><?php _e('Description', 'easy-invoice'); ?></th>
                                <th><?php _e('Qty', 'easy-invoice'); ?></th>
                                <th><?php _e('Unit Price', 'easy-invoice'); ?></th>
                                <?php if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()): ?>
                                <th><?php _e('Adjust (%)', 'easy-invoice'); ?></th>
                                <?php endif; ?>
                                <th><?php _e('Total', 'easy-invoice'); ?></th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($invoice->getItems() as $item): ?>
                                <tr>
                                    <td><?php echo esc_html($item->getName()); ?></td>
                                    <td><?php echo esc_html($item->getDescription()); ?></td>
                                    <td><?php echo esc_html($item->getQuantity()); ?></td>
                                    <td><?php echo esc_html($formatter->format($item->getPrice())); ?></td>
                                    <?php if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()): ?>
                                    <td><?php 
                                        $adjust_percentage = $item->getAdjustPercentage();
                                        if ($adjust_percentage != 0) {
                                            echo esc_html($adjust_percentage > 0 ? '+' : '') . esc_html($adjust_percentage) . '%';
                                        } else {
                                            echo esc_html__('—', 'easy-invoice');
                                        }
                                    ?></td>
                                    <?php endif; ?>
                                    <td><?php echo esc_html($formatter->format($item->getAmount())); ?></td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>

                    <div class="invoice-summary">
                        <div><strong><?php _e('Subtotal', 'easy-invoice'); ?>:</strong> <?php echo esc_html($formatter->format($invoice->getSubtotal())); ?></div>
                        <?php if ($invoice->getDiscountAmount() > 0): ?>
                            <div><strong><?php _e('Discount', 'easy-invoice'); ?>:</strong> -<?php echo esc_html($formatter->format($invoice->getDiscountAmount())); ?></div>
                        <?php endif; ?>
                        <?php if ($invoice->getTaxAmount() > 0): ?>
                            <div><strong><?php _e('Tax', 'easy-invoice'); ?>:</strong> <?php echo esc_html($formatter->format($invoice->getTaxAmount())); ?></div>
                        <?php endif; ?>
                        <?php do_action('easy_invoice_invoice_totals_after_tax', $invoice); ?>
                        <div style="font-size: 1.2em; margin-top: 8px;"><strong><?php _e('Total', 'easy-invoice'); ?>:</strong> <?php echo esc_html($formatter->format($invoice->getTotal())); ?></div>
                    </div>
                <?php endif; ?>
            </div>

            <!-- Payment panel (right side) - hidden by default -->
            <?php if ($show_pay_button): ?>
                <div id="payment-panel" class="payment-panel" style="width: 450px; flex-shrink: 0; display: none; transition: transform 0.3s ease; position: fixed; top: 0; right: 0; height: 100vh; z-index: 1000; background: white; box-shadow: -2px 0 10px rgba(0,0,0,0.1);">
                    <div style="position: relative; height: 100%; overflow-y: auto;">
                        <button onclick="closePaymentPanel()" style="position: absolute; top: 15px; right: 15px; background: rgba(0,0,0,0.1); border: none; color: #333; width: 35px; height: 35px; border-radius: 50%; cursor: pointer; font-size: 18px; z-index: 10; display: flex; align-items: center; justify-content: center;">×</button>
                        <?php include EASY_INVOICE_PLUGIN_DIR . 'templates/payment-section.php'; ?>
                    </div>
                </div>
            <?php endif; ?>
        </div>
    </div>
    
    <script>
    function printInvoiceContent() {
        // Get the invoice content
        const invoiceContent = document.querySelector('.invoice-content');
        
        if (!invoiceContent) {
            alert('<?php _e('Invoice content not found', 'easy-invoice'); ?>');
            return;
        }
        
        // Create a new window for printing
        const printWindow = window.open('', '_blank', 'width=800,height=600');
        
        // Create the print HTML with comprehensive styles
        const printHTML = `
            <!DOCTYPE html>
            <html>
            <head>
                <title><?php echo esc_js($invoice->getNumber() ?: __('Invoice', 'easy-invoice')); ?></title>
                <meta charset="utf-8">
                <style>
                    /* Reset and base styles */
                    * {
                        margin: 0;
                        padding: 0;
                        box-sizing: border-box;
                    }
                    
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        line-height: 1.6;
                        color: #333;
                        background: white;
                        padding: 20px;
                    }
                    
                    /* Invoice container styles */
                    .invoice-container {
                        max-width: 800px;
                        margin: 0 auto;
                        background: white;
                        padding: 30px;
                        border: 1px solid #e5e7eb;
                        border-radius: 8px;
                    }
                    
                    /* Header styles */
                    .invoice-header {
                        text-align: center;
                        margin-bottom: 40px;
                        padding-bottom: 20px;
                        border-bottom: 2px solid #e5e7eb;
                    }
                    
                    .invoice-header h1 {
                        font-size: 32px;
                        font-weight: 700;
                        color: #1f2937;
                        margin-bottom: 10px;
                    }
                    
                    .invoice-number {
                        font-size: 18px;
                        color: #6b7280;
                        font-weight: 500;
                    }
                    
                    .invoice-date {
                        font-size: 14px;
                        color: #9ca3af;
                        margin-top: 5px;
                    }
                    
                    /* Company and client info */
                    .invoice-info {
                        display: flex;
                        justify-content: space-between;
                        margin-bottom: 40px;
                        gap: 40px;
                    }
                    
                    .company-info, .client-info {
                        flex: 1;
                    }
                    
                    .company-info h2, .client-info h2 {
                        font-size: 16px;
                        font-weight: 600;
                        color: #374151;
                        margin-bottom: 10px;
                        text-transform: uppercase;
                        letter-spacing: 0.5px;
                    }
                    
                    .company-info p, .client-info p {
                        margin-bottom: 5px;
                        color: #6b7280;
                        font-size: 14px;
                    }
                    
                    .client-name {
                        font-weight: 600;
                        color: #1f2937;
                        font-size: 16px;
                        margin-bottom: 8px;
                    }
                    
                    /* Items table */
                    .invoice-items {
                        width: 100%;
                        border-collapse: collapse;
                        margin-bottom: 30px;
                    }
                    
                    .invoice-items th {
                        background: #f9fafb;
                        padding: 12px 15px;
                        text-align: left;
                        font-weight: 600;
                        color: #374151;
                        border-bottom: 2px solid #e5e7eb;
                        font-size: 14px;
                        text-transform: uppercase;
                        letter-spacing: 0.5px;
                    }
                    
                    .invoice-items td {
                        padding: 15px;
                        border-bottom: 1px solid #f3f4f6;
                        vertical-align: top;
                    }
                    
                    .invoice-items tr:hover {
                        background: #f9fafb;
                    }
                    
                    .item-name {
                        font-weight: 500;
                        color: #1f2937;
                    }
                    
                    .item-description {
                        font-size: 13px;
                        color: #6b7280;
                        margin-top: 5px;
                    }
                    
                    .item-quantity, .item-price, .item-total {
                        text-align: right;
                        font-weight: 500;
                    }
                    
                    /* Totals section */
                    .invoice-summary {
                        margin-left: auto;
                        width: 300px;
                        border-top: 2px solid #e5e7eb;
                        padding-top: 20px;
                    }
                    
                    .summary-row {
                        display: flex;
                        justify-content: space-between;
                        padding: 8px 0;
                        font-size: 14px;
                    }
                    
                    .summary-row.total {
                        font-size: 18px;
                        font-weight: 700;
                        color: #1f2937;
                        border-top: 1px solid #e5e7eb;
                        padding-top: 15px;
                        margin-top: 10px;
                    }
                    
                    .summary-label {
                        color: #6b7280;
                    }
                    
                    .summary-value {
                        font-weight: 500;
                        color: #1f2937;
                    }
                    
                    /* Notes section */
                    .invoice-notes {
                        margin-top: 40px;
                        padding: 20px;
                        background: #f9fafb;
                        border-radius: 6px;
                        border-left: 4px solid #3b82f6;
                    }
                    
                    .invoice-notes h3 {
                        font-size: 16px;
                        font-weight: 600;
                        color: #374151;
                        margin-bottom: 10px;
                    }
                    
                    .invoice-notes p {
                        color: #6b7280;
                        line-height: 1.6;
                    }
                    
                    /* Status badge */
                    .invoice-status {
                        display: inline-block;
                        padding: 4px 12px;
                        border-radius: 20px;
                        font-size: 12px;
                        font-weight: 600;
                        text-transform: uppercase;
                        letter-spacing: 0.5px;
                        margin-left: 10px;
                    }
                    
                    .status-draft { background: #e5e7eb; color: #374151; }
                    .status-unpaid { background: #fef2f2; color: #dc2626; }
                    .status-paid { background: #f0fdf4; color: #166534; }
                    .status-overdue { background: #fffbeb; color: #d97706; }
                    .status-available { background: #eff6ff; color: #1d4ed8; }
                    
                    /* Print-specific styles */
                    @media print {
                        body {
                            margin: 0;
                            padding: 0;
                        }
                        
                        .invoice-container {
                            border: none;
                            padding: 0;
                            max-width: none;
                        }
                        
                        .invoice-items th {
                            background: #f9fafb !important;
                            -webkit-print-color-adjust: exact;
                            color-adjust: exact;
                        }
                        
                        .invoice-notes {
                            background: #f9fafb !important;
                            -webkit-print-color-adjust: exact;
                            color-adjust: exact;
                        }
                        
                        .status-draft { background: #e5e7eb !important; }
                        .status-unpaid { background: #fef2f2 !important; }
                        .status-paid { background: #f0fdf4 !important; }
                        .status-overdue { background: #fffbeb !important; }
                        .status-available { background: #eff6ff !important; }
                        
                        /* Ensure proper page breaks */
                        .invoice-content {
                            page-break-inside: avoid;
                        }
                        
                        table {
                            page-break-inside: avoid;
                        }
                        
                        tr {
                            page-break-inside: avoid;
                        }
                    }
                </style>
            </head>
            <body>
                ${invoiceContent.outerHTML}
            </body>
            </html>
        `;
        
        // Write the content to the new window
        printWindow.document.write(printHTML);
        printWindow.document.close();
        
        // Wait for content to load, then print
        printWindow.onload = function() {
            setTimeout(function() {
                printWindow.print();
                printWindow.close();
            }, 500);
        };
    }
    
    function downloadInvoicePdf(invoiceId) {
        // Show loading state
        const button = event.target;
        const originalText = button.innerHTML;
        button.innerHTML = '<?php _e('Generating PDF...', 'easy-invoice'); ?>';
        button.disabled = true;
        
        try {
            // Use the unified PDF generator
            if (typeof DocumentPdfGenerator !== 'undefined') {
                const pdfGenerator = new DocumentPdfGenerator('invoice');
                pdfGenerator.generatePDF();
                
            } else {
                // Fallback if PDF generator not available
                if (typeof EasyInvoiceToast !== 'undefined') {
                    EasyInvoiceToast.error('<?php _e('PDF generator not available', 'easy-invoice'); ?>');
                } else {
                    alert('<?php _e('PDF generator not available', 'easy-invoice'); ?>');
                }
            }
        } catch (error) {
            console.error('PDF generation error:', error);
            if (typeof EasyInvoiceToast !== 'undefined') {
                EasyInvoiceToast.error('<?php _e('Error generating PDF', 'easy-invoice'); ?>');
            } else {
                alert('<?php _e('Error generating PDF', 'easy-invoice'); ?>');
            }
        }
        
        // Reset button state
        setTimeout(function() {
            button.innerHTML = originalText;
            button.disabled = false;
        }, 1000);
    }
    
    function sendInvoiceEmail(invoiceId) {
        // Show loading state
        const button = event.target;
        const originalText = button.innerHTML;
        button.innerHTML = '<?php _e('Sending...', 'easy-invoice'); ?>';
        button.disabled = true;
        
        // Make AJAX request
        jQuery.ajax({
            url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
            type: 'POST',
            data: {
                action: 'easy_invoice_send_invoice_email',
                invoice_id: invoiceId,
                nonce: '<?php echo wp_create_nonce('send_invoice_email'); ?>'
            },
            success: function(response) {
                if (response.success) {
                    if (typeof EasyInvoiceToast !== 'undefined') {
                        EasyInvoiceToast.success('<?php _e('Invoice sent successfully', 'easy-invoice'); ?>');
                    } else {
                        alert('<?php _e('Invoice sent successfully', 'easy-invoice'); ?>');
                    }
                } else {
                    if (typeof EasyInvoiceToast !== 'undefined') {
                        EasyInvoiceToast.error(response.data || '<?php _e('Error sending invoice', 'easy-invoice'); ?>');
                    } else {
                        alert(response.data || '<?php _e('Error sending invoice', 'easy-invoice'); ?>');
                    }
                }
            },
            error: function() {
                if (typeof EasyInvoiceToast !== 'undefined') {
                    EasyInvoiceToast.error('<?php _e('Network error occurred', 'easy-invoice'); ?>');
                } else {
                    alert('<?php _e('Network error occurred', 'easy-invoice'); ?>');
                }
            },
            complete: function() {
                // Reset button state
                button.innerHTML = originalText;
                button.disabled = false;
            }
        });
    }
    
    // Modal System and Event Listeners
    document.addEventListener('DOMContentLoaded', function() {
        const invoiceId = '<?php echo esc_js($invoice->getId()); ?>';
        
        // Utility: Show loading spinner in a button
        function setButtonLoading(btn, loadingText) {
            btn.disabled = true;
            btn.innerHTML = `<span class='ei-btn-spinner' style='display:inline-block;vertical-align:middle;width:18px;height:18px;margin-right:8px;'>
                <svg width='18' height='18' viewBox='0 0 50 50'><circle cx='25' cy='25' r='20' fill='none' stroke='#fff' stroke-width='5' stroke-linecap='round' stroke-dasharray='31.415, 31.415' transform='rotate(0 25 25)'><animateTransform attributeName='transform' type='rotate' from='0 25 25' to='360 25 25' dur='0.8s' repeatCount='indefinite'/></circle></svg>
            </span>${loadingText}`;
        }
        function resetButtonLoading(btn, originalText) {
            btn.disabled = false;
            btn.innerHTML = originalText;
        }
        
        // Send Email Button
        const emailButton = document.querySelector('.send-email-button');
        if (emailButton) {
            emailButton.addEventListener('click', function() {
                const message = '<?php echo esc_js(__('Send this invoice via email?', 'easy-invoice')); ?>\n\n<?php echo esc_js(__('This will send the invoice to the client\'s email address.', 'easy-invoice')); ?>';
                
                showConfirmationModal(
                    '<?php echo esc_js($text_settings['send_email']); ?>',
                    message,
                    '<?php echo esc_js($text_settings['send_email']); ?>',
                    '<?php echo esc_js(__('Cancel', 'easy-invoice')); ?>',
                    'primary',
                    function(modal, confirmBtn, originalText) {
                        handleSendEmail(invoiceId, confirmBtn, originalText);
                    }
                );
            });
        }
        
        // Custom Modal System
        function showConfirmationModal(title, message, confirmText, cancelText, confirmType, onConfirm) {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }
            
            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';
            
            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';
            
            const confirmBtnClass = confirmType === 'danger' ? 'ei-modal-btn-danger' : 'ei-modal-btn-primary';
            const iconClass = confirmType === 'danger' ? 'danger' : 'info';
            const icon = confirmType === 'danger' ? 
                '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>' : 
                '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="none"/><path d="M12 16v-4M12 8h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
            
            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon ${iconClass}">
                        ${icon}
                    </div>
                    <h3 class="ei-modal-title">${title}</h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                </div>
                <div class="ei-modal-actions">
                    <button type="button" class="ei-modal-btn ei-modal-btn-secondary" id="modal-cancel">${cancelText}</button>
                    <button type="button" class="ei-modal-btn ${confirmBtnClass}" id="modal-confirm">${confirmText}</button>
                </div>
            `;
            
            overlay.appendChild(modal);
            document.body.appendChild(overlay);
            
            // Show modal with animation
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
            
            // Handle button clicks
            const confirmBtn = modal.querySelector('#modal-confirm');
            const cancelBtn = modal.querySelector('#modal-cancel');
            
            confirmBtn.addEventListener('click', function() {
                const originalText = confirmBtn.innerHTML;
                setButtonLoading(confirmBtn, confirmBtn.textContent.trim());
                onConfirm(modal, confirmBtn, originalText);
            });
            
            cancelBtn.addEventListener('click', function() {
                hideModal(overlay);
            });
            
            // Handle overlay click to close
            overlay.addEventListener('click', function(e) {
                if (e.target === overlay) {
                    hideModal(overlay);
                }
            });
            
            // Handle escape key
            const handleEscape = function(e) {
                if (e.key === 'Escape') {
                    hideModal(overlay);
                    document.removeEventListener('keydown', handleEscape);
                }
            };
            document.addEventListener('keydown', handleEscape);
            
            // Focus on confirm button
            setTimeout(() => {
                confirmBtn.focus();
            }, 100);
        }
        
        function hideModal(overlay) {
            const modal = overlay.querySelector('.ei-modal');
            modal.classList.remove('show');
            overlay.classList.remove('show');
            
            setTimeout(() => {
                if (overlay.parentNode) {
                    overlay.remove();
                }
            }, 300);
        }
        
        // Show message in modal (used for AJAX responses)
        function showModalMessage(type, message, onClose) {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }
            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';
            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';
            const iconClass = type === 'success' ? 'info' : 'danger';
            const icon = type === 'success'
                ? '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#10b981"/><path d="M7 13l3 3 7-7" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
                : '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#ef4444"/><path d="M12 7v4.5M12 16h.01" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon ${iconClass}">${icon}</div>
                    <h3 class="ei-modal-title">${type === 'success' ? '<?php echo esc_js(__('Success', 'easy-invoice')); ?>' : '<?php echo esc_js(__('Error', 'easy-invoice')); ?>'}</h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                </div>
                <div class="ei-modal-actions">
                    <button type="button" class="ei-modal-btn ei-modal-btn-primary" id="modal-close"><?php echo esc_js(__('Close', 'easy-invoice')); ?></button>
                </div>
            `;
            overlay.appendChild(modal);
            document.body.appendChild(overlay);
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
            const closeBtn = modal.querySelector('#modal-close');
            closeBtn.addEventListener('click', function() {
                hideModal(overlay);
                if (onClose) onClose();
            });
            overlay.addEventListener('click', function(e) {
                if (e.target === overlay) {
                    hideModal(overlay);
                    if (onClose) onClose();
                }
            });
            const handleEscape = function(e) {
                if (e.key === 'Escape') {
                    hideModal(overlay);
                    document.removeEventListener('keydown', handleEscape);
                    if (onClose) onClose();
                }
            };
            document.addEventListener('keydown', handleEscape);
            setTimeout(() => {
                closeBtn.focus();
            }, 100);
        }
        
        // Show loading state in modal
        function showModalLoading(message) {
            // Remove existing modal if any
            const existingModal = document.querySelector('.ei-modal-overlay');
            if (existingModal) {
                existingModal.remove();
            }
            // Create modal overlay
            const overlay = document.createElement('div');
            overlay.className = 'ei-modal-overlay';
            // Create modal content
            const modal = document.createElement('div');
            modal.className = 'ei-modal';
            modal.innerHTML = `
                <div class="ei-modal-header">
                    <div class="ei-modal-icon info">
                        <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="12" fill="#3b82f6"/><circle cx="12" cy="12" r="6" fill="#fff"/><animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/></svg>
                    </div>
                    <h3 class="ei-modal-title"><?php echo esc_js(__('Please wait...', 'easy-invoice')); ?></h3>
                </div>
                <div class="ei-modal-body">
                    <div class="ei-modal-message">${message}</div>
                </div>
            `;
            overlay.appendChild(modal);
            document.body.appendChild(overlay);
            setTimeout(() => {
                overlay.classList.add('show');
                modal.classList.add('show');
            }, 10);
        }
        
        // Handle Send Email
        function handleSendEmail(invoiceId, confirmBtn, originalText) {
            showModalLoading('<?php echo esc_js(__('Sending email...', 'easy-invoice')); ?>');
            jQuery.ajax({
                url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
                type: 'POST',
                data: {
                    action: 'easy_invoice_send_invoice_email',
                    invoice_id: invoiceId,
                    nonce: '<?php echo wp_create_nonce('easy_invoice_send_invoice_email'); ?>'
                },
                success: function(response) {
                    if (response.success) {
                        var msg = (response && response.data && (response.data.message || (response.data.toast && response.data.toast.message))) || '<?php _e('Email sent successfully', 'easy-invoice'); ?>';
                        showModalMessage('success', msg);
                    } else {
                        // Handle both response.data.message and response.data (direct string)
                        var msg = '';
                        if (response && response.data) {
                            if (response.data.message) {
                                msg = response.data.message;
                            } else if (typeof response.data === 'string') {
                                msg = response.data;
                            } else if (response.data.toast && response.data.toast.message) {
                                msg = response.data.toast.message;
                            }
                        }
                        msg = msg || '<?php _e('Error sending email', 'easy-invoice'); ?>';
                        
                        resetButtonLoading(confirmBtn, originalText);
                        showModalMessage('error', msg);
                    }
                },
                error: function() {
                    resetButtonLoading(confirmBtn, originalText);
                    showModalMessage('error', '<?php _e('Error connecting to server', 'easy-invoice'); ?>');
                }
            });
        }
    });
    </script>
    
    <!-- Payment variables for the payment form -->
    <script>
    // Global variables needed by the payment form (basic payment functionality)
    window.easy_invoice_vars = {
        ajax_url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
        nonce: '<?php echo wp_create_nonce('easy_invoice_payment'); ?>',
        currency_symbol: '<?php echo esc_js(\EasyInvoice\Helpers\CurrencyHelper::getCurrencySymbol($invoice->getCurrencyCode() ?: 'USD')); ?>',
        currency_code: '<?php echo esc_js($invoice->getCurrencyCode() ?: 'USD'); ?>'
    };
    
    // Invoice data for PDF generation
    window.invoiceData = <?php 
        $invoice_data = \EasyInvoice\Includes\Helpers\PdfHelper::getInvoiceDataForPdf($invoice);
        $invoice_data['status'] = $invoice->getStatus();
        echo json_encode($invoice_data); 
    ?>;
    </script>
    <script>
    document.addEventListener('DOMContentLoaded', function() {
        // Auto-download PDF if ?auto_download_pdf=1 is present
        if (window.location.search.indexOf('auto_download_pdf=1') !== -1) {
            setTimeout(function() {
                if (typeof DocumentPdfGenerator !== 'undefined') {
                    const pdfGenerator = new DocumentPdfGenerator('invoice');
                    pdfGenerator.generatePDF();
                }
            }, 800);
        }
    });
    </script>
</body>
</html> 
```
