import { getInvoiceById, updateInvoice, validateInvoice, addInvoiceLine } from '../services/invoices.js'; export function InvoiceModal(invoiceId, onClose, onUpdate) { const modal = document.createElement('div'); modal.className = 'modal-overlay'; let invoice = null; let isLoading = true; // Formatear fecha para input type="date" const formatDateForInput = (dateString) => { if (!dateString) return ''; const date = new Date(dateString); return date.toISOString().split('T')[0]; }; // Formatear fecha para mostrar const formatDate = (dateString) => { if (!dateString) return '-'; const date = new Date(dateString); return date.toLocaleDateString('es-ES'); }; // Formatear moneda const formatCurrency = (amount) => { return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR' }).format(amount || 0); }; // Obtener texto de estado const getStatusText = (status) => { const statusTextMap = { 'draft': 'Borrador', 'validated': 'Validada', 'paid': 'Pagada', 'unpaid': 'Impagada', 'canceled': 'Cancelada' }; return statusTextMap[status] || status; }; // Renderizar contenido del modal const renderContent = () => { const modalContent = modal.querySelector('.modal-content'); if (isLoading) { modalContent.innerHTML = ` `; return; } if (!invoice) { modalContent.innerHTML = ` `; return; } const isDraft = invoice.status === 'draft'; const canEdit = isDraft || invoice.status === 'validated' || invoice.status === 'unpaid'; modalContent.innerHTML = ` `; attachEventListeners(); }; // Adjuntar event listeners const attachEventListeners = () => { // Botón cerrar const closeBtn = modal.querySelector('.btn-close'); closeBtn?.addEventListener('click', handleClose); // Botón cancelar modal const cancelBtn = modal.querySelector('.btn-cancel-modal'); cancelBtn?.addEventListener('click', handleClose); // Botón guardar const saveBtn = modal.querySelector('.btn-save'); saveBtn?.addEventListener('click', handleSave); // Botón validar const validateBtn = modal.querySelector('.btn-validate'); validateBtn?.addEventListener('click', handleValidate); // Botón añadir línea const addLineBtn = modal.querySelector('.btn-add-line'); addLineBtn?.addEventListener('click', toggleAddLineForm); // Botón guardar línea const saveLineBtn = modal.querySelector('.btn-save-line'); saveLineBtn?.addEventListener('click', handleSaveLine); // Botón cancelar línea const cancelLineBtn = modal.querySelector('.btn-cancel-line'); cancelLineBtn?.addEventListener('click', () => { const form = modal.querySelector('.add-line-form'); if (form) form.style.display = 'none'; }); // Click fuera del modal modal.addEventListener('click', (e) => { if (e.target === modal) { handleClose(); } }); }; // Manejar cierre const handleClose = () => { modal.remove(); if (onClose) onClose(); }; // Manejar guardado const handleSave = async () => { const form = modal.querySelector('#invoice-form'); const formData = new FormData(form); // La API espera camelCase en el PUT (notePublic/notePrivate) const data = { number: formData.get('number') || undefined, expireDate: formData.get('expireDate') || undefined, notePublic: formData.get('note_public') || undefined, notePrivate: formData.get('note_private') || undefined }; // Filtrar valores undefined Object.keys(data).forEach(key => { if (data[key] === undefined || data[key] === '') { delete data[key]; } }); try { const saveBtn = modal.querySelector('.btn-save'); saveBtn.disabled = true; saveBtn.textContent = 'Guardando...'; await updateInvoice(invoiceId, data); alert('Factura actualizada correctamente'); if (onUpdate) onUpdate(); handleClose(); } catch (error) { console.error('Error al guardar:', error); alert('Error al guardar la factura: ' + error.message); } finally { const saveBtn = modal.querySelector('.btn-save'); if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = 'Guardar Cambios'; } } }; // Manejar validación const handleValidate = async () => { if (!confirm('¿Estás seguro de que quieres validar esta factura? No podrás editarla completamente después.')) { return; } try { const validateBtn = modal.querySelector('.btn-validate'); validateBtn.disabled = true; validateBtn.textContent = 'Validando...'; await validateInvoice(invoiceId); alert('Factura validada correctamente'); if (onUpdate) onUpdate(); // Recargar la factura para mostrar el nuevo estado await loadInvoice(); } catch (error) { console.error('Error al validar:', error); alert('Error al validar la factura: ' + error.message); const validateBtn = modal.querySelector('.btn-validate'); if (validateBtn) { validateBtn.disabled = false; validateBtn.innerHTML = 'Validar Factura'; } } }; // Mostrar/ocultar formulario de añadir línea const toggleAddLineForm = () => { const form = modal.querySelector('.add-line-form'); if (form) { const isVisible = form.style.display !== 'none'; form.style.display = isVisible ? 'none' : 'block'; if (!isVisible) { // Limpiar campos modal.querySelector('#line-description').value = ''; modal.querySelector('#line-quantity').value = '1'; modal.querySelector('#line-price').value = '0'; modal.querySelector('#line-tax').value = '21'; } } }; // Guardar nueva línea const handleSaveLine = async () => { const description = modal.querySelector('#line-description').value.trim(); const quantity = parseFloat(modal.querySelector('#line-quantity').value); const unitPrice = parseFloat(modal.querySelector('#line-price').value); const taxRate = parseFloat(modal.querySelector('#line-tax').value); if (!description) { alert('La descripción es obligatoria'); return; } if (!quantity || quantity <= 0) { alert('La cantidad debe ser mayor que 0'); return; } if (unitPrice < 0) { alert('El precio no puede ser negativo'); return; } if (taxRate < 0 || taxRate > 100) { alert('El IVA debe estar entre 0 y 100'); return; } try { const saveBtn = modal.querySelector('.btn-save-line'); saveBtn.disabled = true; saveBtn.textContent = 'Guardando...'; await addInvoiceLine(invoiceId, { description, quantity, unitPrice, taxRate }); alert('Línea añadida correctamente'); toggleAddLineForm(); await loadInvoice(); } catch (error) { console.error('Error al añadir línea:', error); alert('Error al añadir línea: ' + error.message); } finally { const saveBtn = modal.querySelector('.btn-save-line'); if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = 'Guardar Línea'; } } }; // Cargar factura const loadInvoice = async () => { try { isLoading = true; renderContent(); invoice = await getInvoiceById(invoiceId); isLoading = false; renderContent(); } catch (error) { console.error('Error al cargar factura:', error); isLoading = false; invoice = null; renderContent(); } }; // Inicializar modal modal.innerHTML = ` `; // Cargar factura loadInvoice(); return modal; }