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