Update lab_formularios.php
This commit is contained in:
+70
-50
@@ -34,6 +34,12 @@ $puedeEscribir = $esAdmin && hasModuleWrite('lab_formularios');
|
||||
.badge-completado { background:#0d6efd; }
|
||||
.badge-firmado { background:#198754; }
|
||||
.badge-expirado { background:#dc3545; }
|
||||
|
||||
/* ── Animación toast ────────────────────────────── */
|
||||
@keyframes fadeInUp {
|
||||
from { opacity:0; transform:translateY(12px); }
|
||||
to { opacity:1; transform:translateY(0); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -118,53 +124,58 @@ $puedeEscribir = $esAdmin && hasModuleWrite('lab_formularios');
|
||||
|
||||
<!-- ── ENVÍOS ─────────────────────────────────────────────── -->
|
||||
<div id="panel-envios" style="display:none">
|
||||
<!-- Filtros fila 1 -->
|
||||
<div class="row g-2 mb-2 align-items-end">
|
||||
<div class="col-sm-2">
|
||||
<label class="form-label small mb-1">Desde</label>
|
||||
<input type="date" id="env-f-desde" class="form-control form-control-sm" oninput="envios.filtrar()">
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label class="form-label small mb-1">Hasta</label>
|
||||
<input type="date" id="env-f-hasta" class="form-control form-control-sm" oninput="envios.filtrar()">
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<label class="form-label small mb-1">Formulario</label>
|
||||
<select id="env-f-formulario" class="form-select form-select-sm" onchange="envios.filtrar()">
|
||||
<option value="">Todos los formularios</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label class="form-label small mb-1">Estado</label>
|
||||
<select id="env-f-estado" class="form-select form-select-sm" onchange="envios.filtrar()">
|
||||
<option value="">Todos los estados</option>
|
||||
<option value="pendiente">🕐 Pendiente</option>
|
||||
<option value="completado">✅ Completado</option>
|
||||
<option value="firmado">✍️ Firmado</option>
|
||||
<option value="expirado">⏰ Expirado</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Filtros fila 2 -->
|
||||
<div class="row g-2 mb-3 align-items-end">
|
||||
<div class="col-sm-4">
|
||||
<label class="form-label small mb-1">Paciente</label>
|
||||
<input type="text" id="env-f-paciente" class="form-control form-control-sm"
|
||||
placeholder="Buscar paciente…" oninput="envios.filtrar()">
|
||||
</div>
|
||||
<div class="col-sm-auto ms-auto">
|
||||
<button class="btn btn-success btn-sm" onclick="envios.exportarExcel()">
|
||||
<i class="fas fa-file-excel me-1"></i>Exportar Excel
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-auto">
|
||||
<button class="btn btn-outline-secondary btn-sm" onclick="envios.limpiarFiltros()">
|
||||
<i class="fas fa-times me-1"></i>Limpiar
|
||||
</button>
|
||||
<!-- Filtros en una sola fila compacta -->
|
||||
<div class="card border-0 bg-light mb-3 px-3 py-2">
|
||||
<div class="row g-2 align-items-end">
|
||||
<div class="col-6 col-sm-2">
|
||||
<label class="form-label form-label-sm mb-1 text-muted">Desde</label>
|
||||
<input type="date" id="env-f-desde" class="form-control form-control-sm" oninput="envios.filtrar()">
|
||||
</div>
|
||||
<div class="col-6 col-sm-2">
|
||||
<label class="form-label form-label-sm mb-1 text-muted">Hasta</label>
|
||||
<input type="date" id="env-f-hasta" class="form-control form-control-sm" oninput="envios.filtrar()">
|
||||
</div>
|
||||
<div class="col-12 col-sm-3">
|
||||
<label class="form-label form-label-sm mb-1 text-muted">Formulario</label>
|
||||
<select id="env-f-formulario" class="form-select form-select-sm" onchange="envios.filtrar()">
|
||||
<option value="">Todos los formularios</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6 col-sm-2">
|
||||
<label class="form-label form-label-sm mb-1 text-muted">Estado</label>
|
||||
<select id="env-f-estado" class="form-select form-select-sm" onchange="envios.filtrar()">
|
||||
<option value="">Todos</option>
|
||||
<option value="pendiente">🕐 Pendiente</option>
|
||||
<option value="completado">✅ Completado</option>
|
||||
<option value="firmado">✍️ Firmado</option>
|
||||
<option value="expirado">⏰ Expirado</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3">
|
||||
<label class="form-label form-label-sm mb-1 text-muted">Paciente</label>
|
||||
<input type="text" id="env-f-paciente" class="form-control form-control-sm"
|
||||
placeholder="Buscar…" oninput="envios.filtrar()">
|
||||
</div>
|
||||
<div class="col-12 col-sm-auto ms-sm-auto d-flex gap-2">
|
||||
<button class="btn btn-success btn-sm" onclick="envios.exportarExcel()" title="Exportar a Excel">
|
||||
<i class="fas fa-file-excel me-1"></i><span class="d-none d-md-inline">Excel</span>
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary btn-sm" onclick="envios.limpiarFiltros()" title="Limpiar filtros">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<!-- Spinner de carga -->
|
||||
<div id="env-spinner" class="text-center py-5" style="display:none">
|
||||
<div class="spinner-border text-primary" role="status" style="width:2rem;height:2rem">
|
||||
<span class="visually-hidden">Cargando…</span>
|
||||
</div>
|
||||
<p class="text-muted small mt-2 mb-0">Cargando envíos…</p>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive" id="env-tabla-wrap">
|
||||
<table class="table table-hover align-middle small" id="tabla-envios">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
@@ -504,12 +515,21 @@ const envios = {
|
||||
_pagina: 1,
|
||||
|
||||
async cargar() {
|
||||
// Mostrar spinner, ocultar tabla
|
||||
const spinner = $('env-spinner');
|
||||
const tabla = $('env-tabla-wrap');
|
||||
if (spinner) spinner.style.display = '';
|
||||
if (tabla) tabla.style.display = 'none';
|
||||
|
||||
const r = await fetch('api/lab/get_formularios.php?envios=1');
|
||||
const d = await r.json();
|
||||
this._data = d.data || [];
|
||||
this._pagina = 1;
|
||||
this._poblarSelectFormulario();
|
||||
this._aplicarFiltros();
|
||||
|
||||
if (spinner) spinner.style.display = 'none';
|
||||
if (tabla) tabla.style.display = '';
|
||||
},
|
||||
|
||||
filtrar() {
|
||||
@@ -644,7 +664,7 @@ const envios = {
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
showToast('✅ Exportando ' + rows.length + ' envíos…');
|
||||
showToast('✅ Excel descargado — ' + rows.length + ' registro(s)', 'success', 4000);
|
||||
},
|
||||
|
||||
_render() {
|
||||
@@ -1042,13 +1062,13 @@ function renderCampoPreview(c, valores) {
|
||||
// ══════════════════════════════════════════════════════════════════════
|
||||
// HELPERS UI
|
||||
// ══════════════════════════════════════════════════════════════════════
|
||||
function showToast(msg) {
|
||||
function showToast(msg, tipo = 'success', ms = 3000) {
|
||||
const t = document.createElement('div');
|
||||
t.className = 'alert alert-success position-fixed bottom-0 end-0 m-3 shadow py-2 px-3';
|
||||
t.style.zIndex = '9999';
|
||||
t.textContent = msg;
|
||||
t.className = `alert alert-${tipo} d-flex align-items-center gap-2 position-fixed bottom-0 end-0 m-3 shadow-sm py-2 px-3`;
|
||||
t.style.cssText = 'z-index:9999;min-width:220px;max-width:360px;font-size:.875rem;border-radius:8px;animation:fadeInUp .2s ease';
|
||||
t.innerHTML = `<span style="flex:1">${esc(msg)}</span><button type="button" class="btn-close btn-close-sm ms-2" style="font-size:.65rem" onclick="this.closest('.alert').remove()"></button>`;
|
||||
document.body.appendChild(t);
|
||||
setTimeout(() => t.remove(), 3000);
|
||||
setTimeout(() => t && t.remove(), ms);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
|
||||
Reference in New Issue
Block a user