hotfix de error en pagar y cosos
This commit is contained in:
parent
75459a90c3
commit
76912ec0d7
|
|
@ -109,7 +109,7 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Fecha</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>Fecha</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
name="date"
|
name="date"
|
||||||
|
|
@ -121,7 +121,7 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Fecha de Vencimiento</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>Fecha de Vencimiento</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
name="expireDate"
|
name="expireDate"
|
||||||
|
|
@ -143,15 +143,15 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group full-width">
|
<div class="form-group full-width">
|
||||||
<label>Nota Pública</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>Nota Pública</label>
|
||||||
<textarea name="note_public" rows="3">${invoice.note_public || ''}</textarea>
|
<textarea name="note_public" rows="3" placeholder="Visible para el cliente" ${!canEdit ? 'disabled' : ''}>${invoice.notePublic || ''}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group full-width">
|
<div class="form-group full-width">
|
||||||
<label>Nota Privada</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Nota Privada</label>
|
||||||
<textarea name="note_private" rows="3">${invoice.note_private || ''}</textarea>
|
<textarea name="note_private" rows="3" placeholder="Solo uso interno" ${!canEdit ? 'disabled' : ''}>${invoice.notePrivate || ''}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -25,24 +25,34 @@ export function renderCreateInvoicePage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-field-compact">
|
<div class="form-field-compact">
|
||||||
<label>Fecha</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>Fecha</label>
|
||||||
<input type="date" id="date" name="date" />
|
<div class="date-input-wrapper">
|
||||||
|
<input type="date" id="date" name="date" min="2000-01-01" max="2100-12-31" />
|
||||||
|
<button type="button" class="date-picker-btn" data-target="date" title="Seleccionar fecha">
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-field-compact">
|
<div class="form-field-compact">
|
||||||
<label>Vencimiento</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>Vencimiento</label>
|
||||||
<input type="date" id="expireDate" name="expireDate" />
|
<div class="date-input-wrapper">
|
||||||
|
<input type="date" id="expireDate" name="expireDate" min="2000-01-01" max="2100-12-31" />
|
||||||
|
<button type="button" class="date-picker-btn" data-target="expireDate" title="Seleccionar fecha">
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="notes-grid-compact">
|
<div class="notes-grid-compact">
|
||||||
<div class="form-field-compact">
|
<div class="form-field-compact">
|
||||||
<label>Nota pública</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>Nota pública</label>
|
||||||
<textarea id="notePublic" name="notePublic" rows="2" placeholder="Visible para el cliente (opcional)"></textarea>
|
<textarea id="notePublic" name="notePublic" rows="2" placeholder="Visible para el cliente (opcional)"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-field-compact">
|
<div class="form-field-compact">
|
||||||
<label>Nota privada</label>
|
<label><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 4px;"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Nota privada</label>
|
||||||
<textarea id="notePrivate" name="notePrivate" rows="2" placeholder="Interna (opcional)"></textarea>
|
<textarea id="notePrivate" name="notePrivate" rows="2" placeholder="Interna (opcional)"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -100,6 +110,14 @@ export function renderCreateInvoicePage() {
|
||||||
expireDate.setDate(expireDate.getDate() + 30);
|
expireDate.setDate(expireDate.getDate() + 30);
|
||||||
container.querySelector('#expireDate').value = expireDate.toISOString().split('T')[0];
|
container.querySelector('#expireDate').value = expireDate.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
// Event listeners para botones de calendario
|
||||||
|
container.querySelectorAll('.date-picker-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const targetInput = container.querySelector(`#${btn.dataset.target}`);
|
||||||
|
if (targetInput) targetInput.showPicker();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
let lineCounter = 0;
|
let lineCounter = 0;
|
||||||
|
|
||||||
function createInvoiceLine() {
|
function createInvoiceLine() {
|
||||||
|
|
@ -204,6 +222,41 @@ export function renderCreateInvoicePage() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validar fechas coherentes
|
||||||
|
const dateValue = container.querySelector('#date').value;
|
||||||
|
const expireDateValue = container.querySelector('#expireDate').value;
|
||||||
|
|
||||||
|
function isValidDate(dateStr) {
|
||||||
|
if (!dateStr) return false;
|
||||||
|
const parts = dateStr.split('-');
|
||||||
|
if (parts.length !== 3) return false;
|
||||||
|
const year = parseInt(parts[0]);
|
||||||
|
const month = parseInt(parts[1]);
|
||||||
|
const day = parseInt(parts[2]);
|
||||||
|
if (year < 2000 || year > 2100) return false;
|
||||||
|
if (month < 1 || month > 12) return false;
|
||||||
|
if (day < 1 || day > 31) return false;
|
||||||
|
const d = new Date(year, month - 1, day);
|
||||||
|
return d.getFullYear() === year && d.getMonth() === month - 1 && d.getDate() === day;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidDate(dateValue)) {
|
||||||
|
alert('La fecha de factura no es válida. Introduce una fecha entre los años 2000 y 2100.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidDate(expireDateValue)) {
|
||||||
|
alert('La fecha de vencimiento no es válida. Introduce una fecha entre los años 2000 y 2100.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateObj = new Date(dateValue);
|
||||||
|
const expireDateObj = new Date(expireDateValue);
|
||||||
|
if (expireDateObj < dateObj) {
|
||||||
|
alert('La fecha de vencimiento no puede ser anterior a la fecha de factura.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
clientId: clientIdValue,
|
clientId: clientIdValue,
|
||||||
date: container.querySelector('#date').value + 'T00:00:00',
|
date: container.querySelector('#date').value + 'T00:00:00',
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ export function renderFacturasPage() {
|
||||||
|
|
||||||
// Manejo de respuesta - obtener todas las facturas
|
// Manejo de respuesta - obtener todas las facturas
|
||||||
allInvoices = Array.isArray(data) ? data : data.data || data.invoices || [];
|
allInvoices = Array.isArray(data) ? data : data.data || data.invoices || [];
|
||||||
filteredInvoices = [...allInvoices];
|
filteredInvoices = [...allInvoices].reverse();
|
||||||
|
|
||||||
console.log(`Total de facturas cargadas: ${allInvoices.length}`);
|
console.log(`Total de facturas cargadas: ${allInvoices.length}`);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -605,6 +605,57 @@ button:focus-visible {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Notes column */
|
||||||
|
.invoice-notes {
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes-preview {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-public {
|
||||||
|
background: rgba(37, 99, 235, 0.08);
|
||||||
|
color: var(--primary);
|
||||||
|
border: 1px solid rgba(37, 99, 235, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-public svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-private {
|
||||||
|
background: rgba(245, 158, 11, 0.08);
|
||||||
|
color: #b45309;
|
||||||
|
border: 1px solid rgba(245, 158, 11, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-private svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-notes {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
.invoice-actions {
|
.invoice-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
@ -893,6 +944,46 @@ button:focus-visible {
|
||||||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Date input wrapper */
|
||||||
|
.date-input-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-input-wrapper input[type="date"] {
|
||||||
|
flex: 1;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-input-wrapper input[type="date"]:focus {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-picker-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
background: var(--primary);
|
||||||
|
color: white;
|
||||||
|
border: 1px solid var(--primary);
|
||||||
|
border-top-right-radius: 6px;
|
||||||
|
border-bottom-right-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-picker-btn:hover {
|
||||||
|
background: var(--primary-hover, #1d4ed8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-picker-btn:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
}
|
||||||
|
|
||||||
.lines-section-compact {
|
.lines-section-compact {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue