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

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.3.4. 1,275 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.3.4/code/templates/invoices/single.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.3.4/raw/templates/invoices/single.php
- Modified: 2026-05-21T08:29:24+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.3.4/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';

$template_file = file_exists($template_file) ? $template_file : EASY_INVOICE_PLUGIN_DIR . 'templates/invoice-templates/default.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>
    <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>


    <script src="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/js/document-pdf.js?ver=' . rawurlencode(EASY_INVOICE_VERSION)); ?>"></script>


    <link rel="stylesheet" href="<?php echo esc_url(EASY_INVOICE_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css'); ?>">

    <?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">
        <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; ?>

            <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>

            <?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); ?>

        <div class="invoice-layout" style="display: flex; gap: 32px; max-width: 1200px; margin: 0 auto;">
            <div class="invoice-content" style="flex: 1; min-width: 0; position: relative;">
                <?php
                // Add Additional CSS button for admin users
                if (is_user_logged_in() && current_user_can('manage_options')):
                    $additional_css = get_post_meta($invoice->getId(), '_easy_invoice_additional_css', true) ?: '';
                    $has_css = !empty($additional_css);
                ?>
                <button type="button" id="additional-css-btn" style="position: absolute; top: 0; left: -40px; background: <?php echo $has_css ? '#10b981' : '#3b82f6'; ?>; color: white; border: none; padding: 6px 10px; border-radius: 3px; cursor: pointer; font-weight: 500; font-size: 11px; line-height: 1; z-index: 1000;" title="Additional CSS<?php echo $has_css ? ' (CSS already added)' : ''; ?>">
                    <i class="fas fa-code"></i>
                    <?php if ($has_css): ?>
                    <span style="position: absolute; top: -4px; right: -4px; background: #ef4444; color: white; border-radius: 50%; width: 8px; height: 8px; font-size: 6px; display: flex; align-items: center; justify-content: center;">•</span>
                    <?php endif; ?>
                </button>
                <?php endif; ?>

                <?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: ?>
                    <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>

                    <div class="invoice-header" style="position: relative;">
                        <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>

            <?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>

    <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>

    <?php
    // Load additional CSS for all users (not just admin)
    $additional_css = get_post_meta($invoice->getId(), '_easy_invoice_additional_css', true) ?: '';
    if (!empty($additional_css)):
    ?>
    <style id="custom-invoice-css">
        <?php echo esc_html($additional_css); ?>
    </style>
    <?php endif; ?>

    <?php
    // Add Additional CSS feature for admin users
    if (is_user_logged_in() && current_user_can('manage_options')):
    ?>
    <div id="css-panel" style="display: none; position: fixed; top: 0; left: 0; width: 400px; height: 100vh; background: white; box-shadow: 2px 0 10px rgba(0,0,0,0.1); z-index: 1001; overflow-y: auto;">
        <div style="padding: 20px; border-bottom: 1px solid #e5e7eb; display: flex; justify-content: space-between; align-items: center;">
            <h3 style="margin: 0; font-size: 18px; font-weight: 600;">Additional CSS</h3>
            <button type="button" id="close-css-panel" style="background: none; border: none; font-size: 24px; cursor: pointer; color: #6b7280;">&times;</button>
        </div>
        <div style="padding: 20px;">
            <div style="margin-bottom: 15px;">
                <label style="display: block; margin-bottom: 8px; font-weight: 500; color: #374151;">Custom CSS for this invoice:</label>
                <textarea id="additional-css-textarea" style="width: calc(100% - 24px); height: 300px; padding: 12px; border: 1px solid #d1d5db; border-radius: 6px; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 13px; resize: vertical; box-sizing: border-box;" placeholder="Enter your custom CSS here..."><?php echo esc_textarea($additional_css); ?></textarea>
            </div>
            <div style="display: flex; gap: 10px;">
                <button type="button" id="save-css-btn" style="background: #10b981; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">Save CSS</button>
                <button type="button" id="preview-css-btn" style="background: #6366f1; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">Preview</button>
                <button type="button" id="clear-css-btn" style="background: #ef4444; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500;">Clear</button>
            </div>
            <div id="css-status" style="margin-top: 15px; padding: 10px; border-radius: 4px; display: none;"></div>
        </div>
    </div>

    <div id="css-overlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;"></div>

    <script>
    // Additional CSS functionality
    document.addEventListener('DOMContentLoaded', function() {
        const cssBtn = document.getElementById('additional-css-btn');
        const cssPanel = document.getElementById('css-panel');
        const closeBtn = document.getElementById('close-css-panel');
        const overlay = document.getElementById('css-overlay');
        const saveBtn = document.getElementById('save-css-btn');
        const previewBtn = document.getElementById('preview-css-btn');
        const clearBtn = document.getElementById('clear-css-btn');
        const textarea = document.getElementById('additional-css-textarea');
        const status = document.getElementById('css-status');

        if (!cssBtn) return; // Exit if CSS button doesn't exist

        let originalCSS = textarea.value;

        // Toggle panel
        cssBtn.addEventListener('click', function() {
            cssPanel.style.display = 'block';
            overlay.style.display = 'block';
        });

        // Close panel
        function closePanel() {
            cssPanel.style.display = 'none';
            overlay.style.display = 'none';
        }

        closeBtn.addEventListener('click', closePanel);
        overlay.addEventListener('click', closePanel);

        // Save CSS
        saveBtn.addEventListener('click', function() {
            const css = textarea.value;

            // AJAX request to save CSS
            fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    'action': 'save_additional_css',
                    'post_id': <?php echo $invoice->getId(); ?>,
                    'css': css,
                    'nonce': '<?php echo wp_create_nonce('save_additional_css_nonce'); ?>'
                })
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    originalCSS = css;
                    status.textContent = 'CSS saved successfully!';
                    status.style.background = '#d1fae5';
                    status.style.color = '#065f46';
                    status.style.display = 'block';

                    // Apply the saved CSS
                    applyCustomCSS(css);

                    setTimeout(() => {
                        status.style.display = 'none';
                    }, 3000);
                } else {
                    status.textContent = 'Error saving CSS: ' + data.message;
                    status.style.background = '#fee2e2';
                    status.style.color = '#991b1b';
                    status.style.display = 'block';
                }
            })
            .catch(error => {
                status.textContent = 'Error saving CSS: ' + error.message;
                status.style.background = '#fee2e2';
                status.style.color = '#991b1b';
                status.style.display = 'block';
            });
        });

        // Preview CSS
        previewBtn.addEventListener('click', function() {
            const css = textarea.value;
            applyCustomCSS(css);

            status.textContent = 'CSS preview applied';
            status.style.background = '#dbeafe';
            status.style.color = '#1e40af';
            status.style.display = 'block';

            setTimeout(() => {
                status.style.display = 'none';
            }, 2000);
        });

        // Clear CSS
        clearBtn.addEventListener('click', function() {
            if (confirm('Are you sure you want to clear all custom CSS?')) {
                textarea.value = '';
                applyCustomCSS('');

                status.textContent = 'CSS cleared';
                status.style.background = '#fee2e2';
                status.style.color = '#991b1b';
                status.style.display = 'block';

                setTimeout(() => {
                    status.style.display = 'none';
                }, 2000);
            }
        });

        // Apply custom CSS function
        function applyCustomCSS(css) {
            // Remove existing custom CSS
            const existingStyle = document.getElementById('custom-invoice-css');
            if (existingStyle) {
                existingStyle.remove();
            }

            // Add new custom CSS if not empty
            if (css.trim()) {
                const style = document.createElement('style');
                style.id = 'custom-invoice-css';
                style.textContent = css;
                document.head.appendChild(style);
            }
        }

        // Apply saved CSS on page load
        applyCustomCSS(originalCSS);
    });
    </script>
    <?php endif; ?>
</body>
</html>

```
