feat: métricas completas, export Excel domicilios con filtros, hora llegada/salida visible

This commit is contained in:
Lizandro Guarnizo
2026-03-25 11:48:24 -05:00
parent 75aac68d65
commit 4ba890a0d5
5 changed files with 743 additions and 114 deletions
+42
View File
@@ -104,6 +104,11 @@ $domIdParam = (int)($_GET['id'] ?? 0);
<i class="fas fa-calendar-day me-1"></i> Hoy
</button>
</div>
<div class="col-md-2">
<button class="btn btn-sm btn-success w-100" onclick="exportarDomicilios()">
<i class="fas fa-file-excel me-1"></i> Excel
</button>
</div>
</div>
<!-- Resumen del día -->
@@ -288,6 +293,18 @@ $domIdParam = (int)($_GET['id'] ?? 0);
<input type="time" class="form-control" name="hora_programada" id="dom-hora">
</div>
</div>
<div class="row g-3 mb-3">
<div class="col-md-4">
<label class="form-label"><i class="fas fa-sign-in-alt text-success me-1"></i>Hora llegada</label>
<input type="time" class="form-control" name="hora_llegada" id="dom-hora-llegada">
<div class="form-text">Registrada automáticamente al iniciar el domicilio</div>
</div>
<div class="col-md-4">
<label class="form-label"><i class="fas fa-sign-out-alt text-danger me-1"></i>Hora salida</label>
<input type="time" class="form-control" name="hora_salida" id="dom-hora-salida">
<div class="form-text">Registrada automáticamente al completar</div>
</div>
</div>
<!-- ── Cobros ── -->
<h6 class="text-muted text-uppercase small fw-semibold border-bottom pb-1 mb-3">
@@ -655,6 +672,10 @@ async function verDomicilio(id) {
<dt class="col-5 text-muted">Barrio</dt><dd class="col-7">${esc(dom.barrio||'—')}</dd>
<dt class="col-5 text-muted">Indicaciones</dt><dd class="col-7">${esc(dom.indicaciones_dir||'—')}</dd>
<dt class="col-5 text-muted">Fecha</dt><dd class="col-7">${esc(dom.fecha_programada)} ${esc(dom.hora_programada||'')}</dd>
${(dom.hora_llegada || dom.hora_salida) ? `
<dt class="col-5 text-muted">Hora llegada</dt><dd class="col-7 text-success fw-semibold">${dom.hora_llegada ? dom.hora_llegada.slice(0,5) : '—'}</dd>
<dt class="col-5 text-muted">Hora salida</dt><dd class="col-7 text-danger fw-semibold">${dom.hora_salida ? dom.hora_salida.slice(0,5) : '—'}</dd>
${dom.hora_llegada && dom.hora_salida ? `<dt class="col-5 text-muted">Duración</dt><dd class="col-7 fw-semibold text-info">${calcDuracion(dom.hora_llegada, dom.hora_salida)}</dd>` : ''}` : ''}
<dt class="col-5 text-muted">Servicio</dt><dd class="col-7">${esc(dom.tipo_servicio||'—')}</dd>
<dt class="col-5 text-muted">Tipo cliente</dt><dd class="col-7">
${dom.tipo_cliente === 'seguro'
@@ -855,6 +876,8 @@ async function editarDomicilio(id) {
document.getElementById('dom-indic').value = dom.indicaciones_dir || '';
document.getElementById('dom-fecha').value = dom.fecha_programada || '';
document.getElementById('dom-hora').value = (dom.hora_programada || '').slice(0, 5);
document.getElementById('dom-hora-llegada').value = (dom.hora_llegada || '').slice(0, 5);
document.getElementById('dom-hora-salida').value = (dom.hora_salida || '').slice(0, 5);
document.getElementById('dom-tipo-cliente').value = dom.tipo_cliente || 'particular';
toggleSeguro(dom.tipo_cliente || 'particular');
document.getElementById('dom-seguro-nombre').value = dom.seguro_nombre || '';
@@ -969,8 +992,27 @@ function verHoy() {
cargarLista();
}
function exportarDomicilios() {
const fecha = document.getElementById('filtro-fecha').value;
const estado = document.getElementById('filtro-estado').value;
const enfId = document.getElementById('filtro-enfermera').value;
let url = `lab_reportes.php?export=domicilios`;
if (fecha) url += `&fecha=${encodeURIComponent(fecha)}`;
if (estado) url += `&estado=${encodeURIComponent(estado)}`;
if (enfId) url += `&enfermera_id=${encodeURIComponent(enfId)}`;
window.open(url, '_blank');
}
// ── Utils ──────────────────────────────────────────────────────────────────
const esc = s => String(s||'').replace(/[<>&"]/g, c => ({'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c]));
function calcDuracion(hl, hs) {
if (!hl || !hs) return '—';
const [h1, m1] = hl.slice(0,5).split(':').map(Number);
const [h2, m2] = hs.slice(0,5).split(':').map(Number);
const mins = (h2 * 60 + m2) - (h1 * 60 + m1);
if (mins <= 0) return '—';
return mins >= 60 ? `${Math.floor(mins/60)}h ${mins%60}min` : `${mins} min`;
}
/**
* Renderiza el bloque de órdenes médicas (multi-archivo) en el detalle de domicilio.