Turnero: mejoras UI, historial detallado, kiosko scanner, firma por turno

- Kiosko: detector scanner (gap < 80ms), iconos 90px, fa-person-pregnant, ticket Arial
- Recepción: vincular_paciente.php para persistir paciente_id antes de firmar consentimiento
- Historial y dashboard: recepción desk, empleado recepción/muestras, exámenes y comentarios
- display_global: turno más pequeño, lugar-nombre más grande
- lab_pacientes: modal compacta con form-sm
- Configuración: icono embarazada fa-person-pregnant en prioridades
- ver_formulario_enviado: firma por campo (fix doble firma)
- docker-compose.local.yml: override BD producción para dev local

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-22 22:07:09 -05:00
co-authored by Claude Sonnet 4.6
parent ebbf4ac6cf
commit f363631b32
12 changed files with 285 additions and 98 deletions
+42 -8
View File
@@ -95,6 +95,12 @@ Layout::open('Historial de Turnos', 'fas fa-history');
.detail-item .d-lbl { font-size:.67rem; text-transform:uppercase; letter-spacing:.07em; color:#94a3b8; }
.detail-item .d-val { font-size:.85rem; font-weight:600; color:#1e293b; }
/* ── Exámenes y comentarios ── */
.detail-extra { margin-top:10px; padding-top:10px; border-top:1px solid #e2e8f0; }
.detail-extra .d-lbl { font-size:.67rem; text-transform:uppercase; letter-spacing:.07em; color:#94a3b8; margin-bottom:5px; }
.detail-comment { padding:5px 0; border-bottom:1px solid #f1f5f9; font-size:.82rem; }
.detail-comment:last-child { border-bottom:none; }
/* ── Documentos firmados ── */
.docs-section { margin-top:10px; padding-top:10px; border-top:1px solid #e2e8f0; }
.docs-lbl { font-size:.65rem; font-weight:700; text-transform:uppercase; letter-spacing:.07em; color:#94a3b8; margin-bottom:5px; }
@@ -448,15 +454,42 @@ function renderDetalle(t) {
return d.toLocaleString('es-CO',{dateStyle:'short',timeStyle:'short'});
};
const items = [
{ lbl:'Creado', val: fmt(t.creado_at) },
{ lbl:'Inicio recepción', val: fmt(t.inicio_recepcion_at) },
{ lbl:'Fin recepción', val: fmt(t.fin_recepcion_at) },
{ lbl:'Inicio servicio', val: fmt(t.inicio_lugar_at) },
{ lbl:'Fin servicio', val: fmt(t.fin_lugar_at) },
{ lbl:'Código completo', val: esc(t.codigo) },
{ lbl:'Número en cola', val: t.numero ?? '—' },
{ lbl:'Teléfono', val: esc(t.paciente_cel || '—') },
{ lbl:'Creado', val: fmt(t.creado_at) },
{ lbl:'Inicio recepción', val: fmt(t.inicio_recepcion_at) },
{ lbl:'Fin recepción', val: fmt(t.fin_recepcion_at) },
{ lbl:'Inicio servicio', val: fmt(t.inicio_lugar_at) },
{ lbl:'Fin servicio', val: fmt(t.fin_lugar_at) },
{ lbl:'Código completo', val: esc(t.codigo) },
{ lbl:'Número en cola', val: t.numero ?? '—' },
{ lbl:'Teléfono', val: esc(t.paciente_cel || '—') },
{ lbl:'Recepción (desk)', val: esc(t.recepcion_desk_nombre || '—') },
{ lbl:'Atendió recepción', val: esc(t.atendido_recepcion_nombre || '—') },
{ lbl:'Atendió muestras', val: esc(t.atendido_lugar_nombre || '—') },
];
// Exámenes
let examHtml = '';
if (t.examenes && t.examenes.length) {
examHtml = `<div class="detail-extra">
<div class="d-lbl"><i class="fas fa-vials me-1 text-success"></i>Exámenes (${t.examenes.length})</div>
<div class="d-val">${t.examenes.map(e => `<span class="badge bg-success-subtle text-success me-1 mb-1">${esc(e.nombre)}</span>`).join('')}</div>
</div>`;
}
// Comentarios
let comHtml = '';
if (t.comentarios && t.comentarios.length) {
comHtml = `<div class="detail-extra">
<div class="d-lbl"><i class="fas fa-comments me-1 text-primary"></i>Comentarios</div>
<div>${t.comentarios.map(c => `
<div class="detail-comment">
<span class="fw-semibold">${esc(c.usuario_nombre)}</span>
<span class="text-muted small ms-1">${c.creado_at ? new Date(c.creado_at.replace(' ','T')).toLocaleString('es-CO',{dateStyle:'short',timeStyle:'short'}) : ''}</span>
<div class="text-secondary">${esc(c.comentario)}</div>
</div>`).join('')}
</div>
</div>`;
}
return `<div class="detail-grid">
${items.map(it=>`
<div class="detail-item">
@@ -464,6 +497,7 @@ function renderDetalle(t) {
<div class="d-val">${it.val}</div>
</div>`).join('')}
</div>
${examHtml}${comHtml}
<div class="docs-section" id="docs-${t.id}">
<div class="docs-lbl"><i class="fas fa-file-signature me-1"></i>Documentos</div>
<span class="text-muted small"><i class="fas fa-spinner fa-spin me-1"></i>Cargando…</span>