Enhance invoice and client modals with improved UI elements and payment history table styling

This commit is contained in:
javiermengual 2026-02-19 16:54:39 +01:00
parent 3a1844e17f
commit a9b8970e4b
4 changed files with 139 additions and 41 deletions

View File

@ -254,30 +254,28 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
<!-- Historial de pagos -->
<div class="form-section payments-history-section">
<h3>Historial de Pagos</h3>
<div class="table-responsive">
<table class="invoice-lines-table">
<thead>
<table class="payments-history-table">
<thead>
<tr>
<th>Fecha</th>
<th>Referencia</th>
<th>Tipo</th>
<th>Nº Transacción</th>
<th>Importe</th>
</tr>
</thead>
<tbody>
${payments.map(p => `
<tr>
<th>Fecha</th>
<th>Importe</th>
<th>Referencia</th>
<th>Tipo</th>
<th>Nº Transacción</th>
<td>${formatDate(p.paymentDate)}</td>
<td class="payment-ref-cell">${p.ref || '—'}</td>
<td>${p.type ? `<span class="payment-type-pill">${p.type}</span>` : '—'}</td>
<td class="payment-ref-cell">${p.transactionNum || '—'}</td>
<td><span class="payment-amount-cell">${formatCurrency(p.amount)}</span></td>
</tr>
</thead>
<tbody>
${payments.map(p => `
<tr>
<td>${formatDate(p.paymentDate)}</td>
<td><strong class="payment-amount-cell">${formatCurrency(p.amount)}</strong></td>
<td>${p.ref || '-'}</td>
<td>${p.type || '-'}</td>
<td>${p.transactionNum || '-'}</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
`).join('')}
</tbody>
</table>
</div>
` : ''}

View File

@ -135,17 +135,24 @@ export function renderClientesPage() {
const modal = document.createElement('div');
modal.className = 'client-modal-overlay';
const contactsHtml = client.contacts && client.contacts.length > 0
const iconMail = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>`;
const iconPhone = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 12 19.79 19.79 0 0 1 1.61 3.38 2 2 0 0 1 3.6 1.22h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.91 8.82a16 16 0 0 0 6.27 6.27l.96-.96a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z"/></svg>`;
const iconMobile = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>`;
const contactsHtml = client.contacts && client.contacts.length > 0
? client.contacts.map(contact => `
<div class="contact-card">
<div class="contact-header">
<div class="contact-avatar">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
</div>
<span class="contact-full-name">${displayValue(contact.firstname)} ${displayValue(contact.lastname)}</span>
</div>
<div class="contact-details">
<div class="contact-row"><span class="label">📧 Email:</span> <span>${displayValue(contact.email)}</span></div>
<div class="contact-row"><span class="label">📱 Móvil:</span> <span>${displayValue(contact.phoneMobile)}</span></div>
<div class="contact-row"><span class="label">☎️ Profesional:</span> <span>${displayValue(contact.phonePro)}</span></div>
<div class="contact-row"><span class="label">📞 Personal:</span> <span>${displayValue(contact.phonePerso)}</span></div>
${contact.email ? `<div class="contact-row"><span class="contact-icon">${iconMail}</span><span>${displayValue(contact.email)}</span></div>` : ''}
${contact.phoneMobile ? `<div class="contact-row"><span class="contact-icon">${iconMobile}</span><span>${displayValue(contact.phoneMobile)}</span></div>` : ''}
${contact.phonePro ? `<div class="contact-row"><span class="contact-icon">${iconPhone}</span><span>${displayValue(contact.phonePro)}</span></div>` : ''}
${contact.phonePerso ? `<div class="contact-row"><span class="contact-icon">${iconPhone}</span><span>${displayValue(contact.phonePerso)}</span></div>` : ''}
</div>
</div>
`).join('')

View File

@ -1473,38 +1473,60 @@ button:disabled {
}
.contact-card {
background: var(--gray-50);
background: var(--card-bg);
border-radius: var(--radius-md);
padding: var(--space-3);
padding: var(--space-4);
border: 1px solid var(--border-color);
}
.contact-header {
margin-bottom: var(--space-2);
display: flex;
align-items: center;
gap: var(--space-2);
margin-bottom: var(--space-3);
padding-bottom: var(--space-3);
border-bottom: 1px solid var(--border-color);
}
.contact-avatar {
width: 28px;
height: 28px;
border-radius: 50%;
background: var(--gray-100);
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
flex-shrink: 0;
}
.contact-full-name {
font-weight: 500;
font-weight: 600;
color: var(--text-primary);
font-size: 14px;
font-size: 13px;
}
.contact-details {
display: flex;
flex-direction: column;
gap: var(--space-1);
gap: var(--space-2);
}
.contact-row {
display: flex;
align-items: center;
gap: var(--space-2);
font-size: 13px;
color: var(--text-secondary);
}
.contact-row .label {
min-width: 110px;
.contact-icon {
display: flex;
align-items: center;
justify-content: center;
color: var(--gray-400);
flex-shrink: 0;
width: 16px;
}
.no-contacts {

View File

@ -376,19 +376,90 @@
/* Payment History */
.payments-history-section {
border-top: 2px solid var(--border-color);
padding-top: 1.25rem;
margin-top: 1rem;
border-top: 1px solid var(--border-color);
padding-top: 1.5rem;
margin-top: 1.5rem;
}
.payments-history-section h3 {
margin: 0 0 0.75rem;
font-size: 1.05rem;
margin: 0 0 1rem;
font-size: 0.75rem;
font-weight: 600;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.payments-history-table {
width: 100%;
border-collapse: collapse;
font-size: 0.8125rem;
border: 1px solid var(--border-color);
border-radius: 8px;
overflow: hidden;
}
.payments-history-table thead th {
padding: 0.5rem 0.875rem;
text-align: left;
font-size: 0.6875rem;
font-weight: 600;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
background: var(--bg-subtle, #f3f4f6);
border-bottom: 1px solid var(--border-color);
white-space: nowrap;
}
.payments-history-table thead th:last-child {
text-align: right;
}
.payments-history-table tbody tr {
border-bottom: 1px solid var(--border-color);
transition: background 0.12s ease;
}
.payments-history-table tbody tr:last-child {
border-bottom: none;
}
.payments-history-table tbody tr:hover {
background: var(--bg-subtle, #f3f4f6);
}
.payments-history-table td {
padding: 0.625rem 0.875rem;
color: var(--text-primary);
vertical-align: middle;
}
.payments-history-table td:last-child {
text-align: right;
}
.payment-amount-cell {
color: var(--success, #22c55e);
font-weight: 600;
color: var(--success, #16a34a);
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.payment-ref-cell {
color: var(--text-secondary);
font-size: 0.75rem;
}
.payment-type-pill {
display: inline-block;
padding: 2px 8px;
background: var(--bg-subtle, #f3f4f6);
border-radius: 99px;
font-size: 0.6875rem;
font-weight: 500;
color: var(--text-secondary);
white-space: nowrap;
}
/* Button Styles */