From c24564dc350693719504b1e66319061d19cd4944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81?= Date: Fri, 6 Feb 2026 20:46:31 +0100 Subject: [PATCH] hotfix rapido de crear facturas --- src/pages/CreateInvoicePage.js | 90 +++++++++++++++++++++++--- src/style.css | 115 +++++++++++++++++++++++++++------ 2 files changed, 176 insertions(+), 29 deletions(-) diff --git a/src/pages/CreateInvoicePage.js b/src/pages/CreateInvoicePage.js index a91bef8..362412d 100644 --- a/src/pages/CreateInvoicePage.js +++ b/src/pages/CreateInvoicePage.js @@ -60,10 +60,34 @@ export function renderCreateInvoicePage() {

Líneas de Factura

- + +
+ +
+ Descripción + Cantidad + Precio + IVA % + Total +
+ +
+
+ Subtotal (sin IVA): + 0,00 € +
+
+ IVA: + 0,00 € +
+
+ Total: + 0,00 € +
+
@@ -118,6 +142,34 @@ export function renderCreateInvoicePage() { }); }); + // Formatear moneda + function formatCurrency(amount) { + return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR' }).format(amount); + } + + // Actualizar total general + function updateGrandTotal() { + const lines = container.querySelectorAll('.line-row-compact'); + let subtotal = 0; + let totalTax = 0; + + lines.forEach(line => { + const qty = parseFloat(line.querySelector('.line-qty-compact').value) || 0; + const price = parseFloat(line.querySelector('.line-price-compact').value) || 0; + const tax = parseFloat(line.querySelector('.line-tax-compact').value) || 0; + const lineSubtotal = qty * price; + subtotal += lineSubtotal; + totalTax += lineSubtotal * (tax / 100); + }); + + const grandSubtotalEl = container.querySelector('#grand-subtotal'); + const grandTaxEl = container.querySelector('#grand-tax'); + const grandTotalEl = container.querySelector('#grand-total-value'); + if (grandSubtotalEl) grandSubtotalEl.textContent = formatCurrency(subtotal); + if (grandTaxEl) grandTaxEl.textContent = formatCurrency(totalTax); + if (grandTotalEl) grandTotalEl.textContent = formatCurrency(subtotal + totalTax); + } + let lineCounter = 0; function createInvoiceLine() { @@ -126,15 +178,33 @@ export function renderCreateInvoicePage() { lineDiv.className = 'line-row-compact'; lineDiv.innerHTML = /*html*/` - - - - -
0.00 €
- +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
0,00 €
+
+
+ +
`; - const descInput = lineDiv.querySelector('.line-desc-compact'); const qtyInput = lineDiv.querySelector('.line-qty-compact'); const priceInput = lineDiv.querySelector('.line-price-compact'); const taxInput = lineDiv.querySelector('.line-tax-compact'); @@ -146,7 +216,8 @@ export function renderCreateInvoicePage() { const tax = parseFloat(taxInput.value) || 0; const subtotal = qty * price; const total = subtotal * (1 + tax / 100); - totalDiv.textContent = `${total.toFixed(2)} €`; + totalDiv.textContent = formatCurrency(total); + updateGrandTotal(); } qtyInput.addEventListener('input', updateTotal); @@ -155,6 +226,7 @@ export function renderCreateInvoicePage() { lineDiv.querySelector('.btn-delete-compact').addEventListener('click', () => { lineDiv.remove(); + updateGrandTotal(); }); return lineDiv; diff --git a/src/style.css b/src/style.css index c967b4a..9d6da18 100755 --- a/src/style.css +++ b/src/style.css @@ -1029,23 +1029,49 @@ button:focus-visible { overflow-y: auto; display: flex; flex-direction: column; + gap: 0.5rem; +} + +/* Column headers */ +.lines-columns-header { + display: grid; + grid-template-columns: 4fr 0.8fr 1.2fr 0.8fr 1.2fr 40px; gap: 0.75rem; + padding: 0.5rem 0.75rem; + font-size: 0.75rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.05em; + border-bottom: 2px solid var(--border-color); + margin-bottom: 0.25rem; } .line-row-compact { display: grid; - grid-template-columns: 4fr 0.8fr 1.2fr 0.8fr 1.2fr auto; + grid-template-columns: 4fr 0.8fr 1.2fr 0.8fr 1.2fr 40px; gap: 0.75rem; align-items: center; background: #f8fafc; border: 1px solid var(--border-color); - border-radius: 6px; + border-radius: 8px; padding: 0.75rem; transition: all 0.2s; } .line-row-compact:hover { background: #f1f5f9; + border-color: #cbd5e1; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); +} + +.line-label-mobile { + display: none; +} + +.line-field { + display: flex; + flex-direction: column; } .line-desc-compact, @@ -1076,23 +1102,22 @@ button:focus-visible { .line-total-compact { font-weight: 600; - color: var(--text-primary); + color: var(--primary); font-size: 0.9375rem; text-align: right; - padding-right: 0.5rem; + padding: 0.5rem 0.25rem; + background: rgba(37, 99, 235, 0.04); + border-radius: 4px; } .btn-delete-compact { background: transparent; color: #94a3b8; border: 1px solid transparent; - width: 32px; - height: 32px; - border-radius: 4px; + width: 36px; + height: 36px; + border-radius: 6px; cursor: pointer; - font-size: 1.5rem; - font-weight: 300; - line-height: 1; display: flex; align-items: center; justify-content: center; @@ -1103,7 +1128,45 @@ button:focus-visible { .btn-delete-compact:hover { color: #ef4444; background: #fee2e2; - border-color: transparent; + border-color: #fecaca; +} + +/* Grand total section */ +.invoice-grand-total { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-top: 1rem; + padding: 1rem 1.25rem; + background: #f8fafc; + border: 1px solid var(--border-color); + border-radius: 8px; + max-width: 300px; + margin-left: auto; +} + +.grand-total-row { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.875rem; + color: var(--text-secondary); +} + +.grand-total-row strong { + color: var(--text-primary); + font-weight: 600; +} + +.grand-total-final { + padding-top: 0.5rem; + border-top: 2px solid var(--border-color); + font-size: 1.05rem; +} + +.grand-total-final strong { + color: var(--primary); + font-size: 1.125rem; } .form-actions-compact { @@ -1170,25 +1233,37 @@ button:focus-visible { grid-column: 1; } + .lines-columns-header { + display: none; + } + .line-row-compact { - grid-template-columns: 1fr auto; + grid-template-columns: 1fr 1fr; gap: 0.5rem; padding: 0.75rem; } - .line-desc-compact { - grid-column: 1; + .line-label-mobile { + display: block; + font-size: 0.7rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.04em; + margin-bottom: 0.2rem; } - .line-qty-compact, - .line-price-compact, - .line-tax-compact, - .line-total-compact { - width: 60px; + .line-field-desc { + grid-column: 1 / -1; } - .btn-delete-compact { + .line-field-actions { grid-column: 2; + justify-self: end; + } + + .invoice-grand-total { + max-width: 100%; } }