// email-modal.js — ES Module // Modal to review and send invoice emails via AWS SES import { showSpinner, hideSpinner } from '../utils/helpers.js'; let currentInvoice = null; let quillInstance = null; // ============================================================ // DOM & Render // ============================================================ function ensureModalElement() { let modal = document.getElementById('email-modal'); if (!modal) { modal = document.createElement('div'); modal.id = 'email-modal'; modal.className = 'modal fixed inset-0 bg-black bg-opacity-50 z-50 justify-center items-start pt-10 overflow-y-auto hidden'; document.body.appendChild(modal); } } function renderModalContent() { const modal = document.getElementById('email-modal'); if (!modal) return; const defaultEmail = currentInvoice.email || ''; // Editor-Container hat jetzt eine feste, kompaktere Höhe (h-48 = 12rem/192px) und scrollt bei viel Text modal.innerHTML = `

📤 Send Invoice #${currentInvoice.invoice_number || currentInvoice.id}

You can override this for testing.

📎
Invoice_${currentInvoice.invoice_number || currentInvoice.id}.pdf will be generated and attached automatically.
`; // Initialize Quill const editorDiv = document.getElementById('email-message-editor'); quillInstance = new Quill(editorDiv, { theme: 'snow', modules: { toolbar: [ ['bold', 'italic', 'underline'], [{ 'list': 'ordered'}, { 'list': 'bullet' }], ['clean'] ] } }); // Variablen für den Text aufbereiten const invoiceNum = currentInvoice.invoice_number || currentInvoice.id; const totalDue = parseFloat(currentInvoice.balance ?? currentInvoice.total).toFixed(2); // Datum formatieren let dueDateStr = 'Upon Receipt'; if (currentInvoice.due_date) { const d = new Date(currentInvoice.due_date); dueDateStr = d.toLocaleDateString('en-US', { timeZone: 'UTC' }); } // Dynamischer Text für die Fälligkeit (Löst das "payable by Upon Receipt" Problem) let paymentText = ''; if (currentInvoice.terms && currentInvoice.terms.toLowerCase().includes('receipt')) { paymentText = 'which is due upon receipt.'; } else if (dueDateStr !== 'Upon Receipt') { paymentText = `payable by ${dueDateStr}.`; } else { paymentText = 'which is due upon receipt.'; } // Der neue Standard-Text const defaultHtml = `

Good afternoon,

Attached is invoice #${invoiceNum} for service performed at your location. The total amount due is $${totalDue}, ${paymentText}

Please pay at your earliest convenience. We appreciate your continued business.

If you have any questions about the invoice, feel free to reply to this email.

Best regards,

Claudia Knuth

Bay Area Affiliates, Inc.

accounting@bayarea-cc.com

`; quillInstance.root.innerHTML = defaultHtml; // Bind Submit Handler document.getElementById('email-send-form').addEventListener('submit', submitEmail); } // ============================================================ // Logic & API // ============================================================ export async function openEmailModal(invoiceId) { ensureModalElement(); if (typeof showSpinner === 'function') showSpinner('Loading invoice data...'); try { const res = await fetch(`/api/invoices/${invoiceId}`); const data = await res.json(); if (!data.invoice) throw new Error('Invoice not found'); currentInvoice = data.invoice; renderModalContent(); // Tailwind hidden toggle document.getElementById('email-modal').classList.remove('hidden'); document.getElementById('email-modal').classList.add('flex'); } catch (e) { console.error('Error loading invoice for email:', e); alert('Could not load invoice details.'); } finally { if (typeof hideSpinner === 'function') hideSpinner(); } } export function closeEmailModal() { const modal = document.getElementById('email-modal'); if (modal) { modal.classList.add('hidden'); modal.classList.remove('flex'); } currentInvoice = null; quillInstance = null; } async function submitEmail(e) { e.preventDefault(); const recipientEmail = document.getElementById('email-recipient').value.trim(); const melioLink = document.getElementById('email-melio-link').value.trim(); const customText = quillInstance.root.innerHTML; if (!recipientEmail) { alert('Please enter a recipient email.'); return; } const submitBtn = document.getElementById('email-submit-btn'); submitBtn.innerHTML = '⏳ Sending...'; submitBtn.disabled = true; if (typeof showSpinner === 'function') showSpinner('Generating PDF and sending email...'); try { const response = await fetch(`/api/invoices/${currentInvoice.id}/send-email`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ recipientEmail, melioLink, customText }) }); const result = await response.json(); if (response.ok) { alert('✅ Invoice sent successfully!'); closeEmailModal(); // Reload the invoice view so the "Sent" badge updates if (window.invoiceView) window.invoiceView.loadInvoices(); } else { alert(`❌ Error: ${result.error}`); } } catch (e) { console.error('Send email error:', e); alert('Network error while sending email.'); } finally { submitBtn.innerHTML = 'Send via AWS SES'; submitBtn.disabled = false; if (typeof hideSpinner === 'function') hideSpinner(); } } // ============================================================ // Expose // ============================================================ window.emailModal = { open: openEmailModal, close: closeEmailModal };