Muestra que el paciente trae después no se muestra como rechazo. Colores rojo → naranja, botón/etiqueta/íconos actualizados en lugar.php y bandeja.php. DB/API internos sin cambio (enum 'rechazada' se mantiene). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
691 lines
26 KiB
PHP
691 lines
26 KiB
PHP
<?php
|
|
Layout::open('Bandeja del día', 'fas fa-layer-group');
|
|
?>
|
|
<style>
|
|
/* ── Layout ──────────────────────────────────────────────────── */
|
|
.bnd-wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: calc(100vh - 60px);
|
|
overflow: hidden;
|
|
background: #f8fafc;
|
|
}
|
|
.bnd-topbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 8px 16px;
|
|
background: #fff;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
flex-shrink: 0;
|
|
flex-wrap: wrap;
|
|
}
|
|
.bnd-title {
|
|
font-size: 1rem;
|
|
font-weight: 700;
|
|
color: #1e293b;
|
|
margin-right: 4px;
|
|
white-space: nowrap;
|
|
}
|
|
.bnd-chip {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 3px 10px;
|
|
border-radius: 20px;
|
|
font-size: 0.78rem;
|
|
font-weight: 600;
|
|
line-height: 1.6;
|
|
white-space: nowrap;
|
|
}
|
|
.bnd-chip-total { background:#ede9fe; color:#5b21b6; }
|
|
.bnd-chip-pend { background:#fef3c7; color:#92400e; }
|
|
.bnd-chip-vis { background:#f1f5f9; color:#475569; }
|
|
.bnd-chip-mp { background:#fff7ed; color:#c2410c; }
|
|
.bnd-refresh-btn {
|
|
margin-left: auto;
|
|
background: none;
|
|
border: 1px solid #cbd5e1;
|
|
border-radius: 6px;
|
|
padding: 3px 10px;
|
|
font-size: 0.78rem;
|
|
color: #475569;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
white-space: nowrap;
|
|
}
|
|
.bnd-refresh-btn:hover { background:#f1f5f9; }
|
|
|
|
/* ── Cuerpo ──────────────────────────────────────────────────── */
|
|
.bnd-body { display: flex; flex: 1; overflow: hidden; }
|
|
|
|
/* ── Lista izquierda ─────────────────────────────────────────── */
|
|
.bnd-list {
|
|
width: 290px;
|
|
flex-shrink: 0;
|
|
border-right: 1px solid #e2e8f0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: #fff;
|
|
}
|
|
.bnd-search-box {
|
|
padding: 8px 10px;
|
|
border-bottom: 1px solid #f1f5f9;
|
|
flex-shrink: 0;
|
|
}
|
|
.bnd-search-box input {
|
|
width: 100%;
|
|
border: 1.5px solid #e2e8f0;
|
|
border-radius: 7px;
|
|
padding: 5px 10px;
|
|
font-size: 0.8rem;
|
|
outline: none;
|
|
font-family: inherit;
|
|
box-sizing: border-box;
|
|
}
|
|
.bnd-search-box input:focus { border-color: #7c3aed; }
|
|
.bnd-list-scroll { flex: 1; overflow-y: auto; }
|
|
.bnd-section-hdr {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 1;
|
|
padding: 5px 12px;
|
|
font-size: 0.68rem;
|
|
font-weight: 700;
|
|
letter-spacing: .07em;
|
|
text-transform: uppercase;
|
|
background: #f8fafc;
|
|
color: #64748b;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
border-top: 1px solid #e2e8f0;
|
|
}
|
|
.bnd-card {
|
|
display: flex;
|
|
align-items: stretch;
|
|
cursor: pointer;
|
|
border-bottom: 1px solid #f1f5f9;
|
|
transition: background .1s;
|
|
}
|
|
.bnd-card:hover { background: #f8fafc; }
|
|
.bnd-card.selected { background: #eef2ff; }
|
|
.bnd-card-bar { width: 3px; flex-shrink: 0; }
|
|
.bnd-card-bar.pendiente { background: #f59e0b; }
|
|
.bnd-card-bar.visto { background: #cbd5e1; }
|
|
.bnd-card-inner { padding: 8px 10px; min-width: 0; flex: 1; }
|
|
.bnd-card-top {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 5px;
|
|
margin-bottom: 1px;
|
|
}
|
|
.bnd-orden { font-size: 0.68rem; font-weight: 700; color: #7c3aed; white-space: nowrap; }
|
|
.bnd-nombre {
|
|
font-size: 0.81rem;
|
|
font-weight: 600;
|
|
color: #1e293b;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
min-width: 0;
|
|
}
|
|
.bnd-card.visto .bnd-nombre { color: #94a3b8; }
|
|
.bnd-card-bot { display: flex; align-items: center; justify-content: space-between; }
|
|
.bnd-lugar-badge { font-size: 0.67rem; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.bnd-hora { font-size: 0.67rem; color: #94a3b8; white-space: nowrap; margin-left: 4px; }
|
|
.bnd-com-badges { display: flex; gap: 3px; margin-left: 2px; }
|
|
.bnd-com-dot {
|
|
font-size: 0.62rem;
|
|
font-weight: 700;
|
|
padding: 1px 5px;
|
|
border-radius: 8px;
|
|
white-space: nowrap;
|
|
line-height: 1.5;
|
|
}
|
|
.bnd-com-dot.recepcion { background: #dbeafe; color: #1d4ed8; }
|
|
.bnd-com-dot.muestras { background: #dcfce7; color: #15803d; }
|
|
.bnd-com-dot.general { background: #fef3c7; color: #92400e; }
|
|
|
|
/* ── Detalle derecha ─────────────────────────────────────────── */
|
|
.bnd-detail { flex: 1; overflow-y: auto; }
|
|
.bnd-empty {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
color: #cbd5e1;
|
|
gap: 10px;
|
|
}
|
|
.bnd-empty i { font-size: 3rem; }
|
|
.bnd-empty p { font-size: 0.9rem; }
|
|
|
|
/* Detail header */
|
|
.bnd-dh {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 2;
|
|
background: #fff;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
padding: 12px 20px 10px;
|
|
}
|
|
.bnd-dh-nombre { font-size: 1.05rem; font-weight: 700; color: #1e293b; margin-bottom: 3px; }
|
|
.bnd-dh-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
.bnd-dh-meta span { font-size: 0.77rem; color: #64748b; }
|
|
.bnd-dh-meta .sep { color: #cbd5e1; }
|
|
.bnd-dh-actions { display: flex; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
|
|
.bnd-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 5px 13px;
|
|
border-radius: 6px;
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
border: 1.5px solid;
|
|
transition: all .12s;
|
|
}
|
|
.bnd-btn-pdf { border-color:#3b82f6; color:#2563eb; background:#fff; }
|
|
.bnd-btn-pdf:hover { background:#eff6ff; }
|
|
.bnd-btn-visto { border-color:#7c3aed; color:#5b21b6; background:#fff; }
|
|
.bnd-btn-visto:hover { background:#f5f3ff; }
|
|
.bnd-btn-ya-visto{ border-color:#cbd5e1; color:#94a3b8; background:#f8fafc; cursor:default; }
|
|
|
|
/* Secciones */
|
|
.bnd-sec { padding: 14px 20px; border-bottom: 1px solid #f1f5f9; }
|
|
.bnd-sec-title {
|
|
font-size: 0.7rem;
|
|
font-weight: 700;
|
|
letter-spacing: .07em;
|
|
text-transform: uppercase;
|
|
color: #94a3b8;
|
|
margin-bottom: 10px;
|
|
}
|
|
/* Exámenes */
|
|
.bnd-cat { margin-bottom: 8px; }
|
|
.bnd-cat-name { font-size: 0.71rem; font-weight: 600; color: #475569; margin-bottom: 4px; }
|
|
.bnd-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
.bnd-exam-chip {
|
|
background: #f1f5f9;
|
|
color: #334155;
|
|
font-size: 0.71rem;
|
|
font-weight: 600;
|
|
padding: 2px 8px;
|
|
border-radius: 12px;
|
|
}
|
|
/* Muestras */
|
|
.bnd-muestra { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 0.82rem; }
|
|
.bnd-m-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
|
.bnd-m-dot.pendiente { background: #f59e0b; }
|
|
.bnd-m-dot.recibida { background: #22c55e; }
|
|
.bnd-m-dot.rechazada { background: #f97316; }
|
|
.bnd-m-label { font-weight: 600; color: #1e293b; }
|
|
.bnd-m-estado { color: #64748b; font-size: 0.74rem; }
|
|
.bnd-m-rechazado { color: #ef4444; font-size: 0.72rem; }
|
|
/* Consentimientos */
|
|
.bnd-consent { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 0.82rem; }
|
|
.bnd-consent-ico.firmado { color: #22c55e; }
|
|
.bnd-consent-ico.pendiente{ color: #f59e0b; }
|
|
.bnd-consent a { font-size: 0.74rem; color: #3b82f6; margin-left: 4px; text-decoration: none; }
|
|
.bnd-consent a:hover { text-decoration: underline; }
|
|
/* Comentarios */
|
|
.bnd-com-list { display: flex; flex-direction: column; gap: 7px; }
|
|
.bnd-com { background: #f8fafc; border-radius: 8px; padding: 8px 12px; font-size: 0.82rem; }
|
|
.bnd-com-header { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
|
|
.bnd-com-tipo {
|
|
font-size: 0.66rem;
|
|
font-weight: 700;
|
|
letter-spacing: .04em;
|
|
padding: 1px 6px;
|
|
border-radius: 10px;
|
|
text-transform: uppercase;
|
|
}
|
|
.bnd-com-tipo.recepcion { background:#dbeafe; color:#1d4ed8; }
|
|
.bnd-com-tipo.muestras { background:#dcfce7; color:#15803d; }
|
|
.bnd-com-tipo.general { background:#fef3c7; color:#92400e; }
|
|
.bnd-com-user { font-weight: 600; color: #1e293b; }
|
|
.bnd-com-date { font-size: 0.7rem; color: #94a3b8; margin-left: auto; }
|
|
.bnd-com-text { color: #334155; }
|
|
/* Agregar comentario */
|
|
.bnd-add-com { display: flex; gap: 8px; align-items: flex-end; }
|
|
.bnd-add-com textarea {
|
|
flex: 1;
|
|
border: 1.5px solid #e2e8f0;
|
|
border-radius: 8px;
|
|
padding: 8px 10px;
|
|
font-size: 0.82rem;
|
|
resize: none;
|
|
font-family: inherit;
|
|
height: 52px;
|
|
outline: none;
|
|
transition: border-color .15s;
|
|
}
|
|
.bnd-add-com textarea:focus { border-color: #7c3aed; }
|
|
.bnd-add-com button {
|
|
background: #7c3aed;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 8px;
|
|
padding: 10px 14px;
|
|
font-size: 0.82rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
height: 52px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
.bnd-add-com button:hover { background: #6d28d9; }
|
|
.bnd-add-com button:disabled { background: #c4b5fd; cursor:default; }
|
|
/* Toast */
|
|
.bnd-toast {
|
|
position: fixed;
|
|
bottom: 24px;
|
|
left: 50%;
|
|
transform: translateX(-50%) translateY(20px);
|
|
background: #1e293b;
|
|
color: #fff;
|
|
padding: 8px 18px;
|
|
border-radius: 20px;
|
|
font-size: 0.82rem;
|
|
z-index: 9999;
|
|
opacity: 0;
|
|
transition: all .25s;
|
|
pointer-events: none;
|
|
}
|
|
.bnd-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
/* ── Modal consentimiento ── */
|
|
.bnd-modal-consent {
|
|
display: none;
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 9200;
|
|
background: rgba(0,0,0,.55);
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.bnd-modal-consent.open { display: flex; }
|
|
.bnd-modal-inner {
|
|
background: #fff;
|
|
border-radius: 12px;
|
|
width: min(820px, 96vw);
|
|
height: min(88vh, 700px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
box-shadow: 0 20px 60px rgba(0,0,0,.25);
|
|
}
|
|
.bnd-modal-hdr {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 18px;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
flex-shrink: 0;
|
|
}
|
|
.bnd-modal-hdr span { font-size:.88rem; font-weight:600; color:#1e293b; }
|
|
.bnd-modal-hdr button {
|
|
background: none; border: none; cursor: pointer;
|
|
font-size: 1.1rem; color: #64748b; line-height:1;
|
|
}
|
|
.bnd-modal-hdr button:hover { color:#1e293b; }
|
|
.bnd-modal-body { flex:1; overflow:hidden; position:relative; }
|
|
.bnd-modal-body iframe { width:100%; height:100%; border:none; }
|
|
.bnd-modal-loading {
|
|
position: absolute; inset: 0;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: .9rem; color: #94a3b8;
|
|
gap: 8px;
|
|
}
|
|
/* ── Print ── */
|
|
@media print {
|
|
.bnd-list, .bnd-topbar, .bnd-dh-actions,
|
|
.bnd-add-com, nav, .sidebar, .erp-sidebar,
|
|
#sidebar, .navbar, #navbar { display: none !important; }
|
|
.bnd-wrap, .bnd-body { height: auto !important; overflow: visible !important; }
|
|
.bnd-detail { overflow: visible !important; }
|
|
.bnd-dh { position: static !important; }
|
|
}
|
|
</style>
|
|
|
|
<div class="bnd-wrap">
|
|
<div class="bnd-topbar">
|
|
<span class="bnd-title"><i class="fas fa-layer-group"></i> Bandeja del día</span>
|
|
<span class="bnd-chip bnd-chip-total" id="st-total"><i class="fas fa-users"></i> —</span>
|
|
<span class="bnd-chip bnd-chip-pend" id="st-pend"><i class="fas fa-clock"></i> Por revisar: —</span>
|
|
<span class="bnd-chip bnd-chip-vis" id="st-vis"><i class="fas fa-eye"></i> Vistos: —</span>
|
|
<span class="bnd-chip bnd-chip-mp" id="st-mp"><i class="fas fa-exclamation-triangle"></i> Muestras pend.: —</span>
|
|
<button class="bnd-refresh-btn" onclick="_bndRefrescarLista()">
|
|
<i class="fas fa-sync-alt" id="bnd-spin"></i> Actualizar
|
|
</button>
|
|
</div>
|
|
|
|
<div class="bnd-body">
|
|
<div class="bnd-list">
|
|
<div class="bnd-search-box">
|
|
<input type="text" id="bnd-filtro" placeholder="Buscar por nombre o examen…" oninput="_bndFiltrar()" autocomplete="off">
|
|
</div>
|
|
<div class="bnd-list-scroll" id="bnd-list-scroll">
|
|
<div class="bnd-section-hdr">Cargando...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bnd-detail" id="bnd-detail">
|
|
<div class="bnd-empty">
|
|
<i class="fas fa-hand-pointer"></i>
|
|
<p>Selecciona un paciente para ver el detalle</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal consentimiento -->
|
|
<div class="bnd-modal-consent" id="bnd-modal-consent" onclick="_bndCerrarConsent(event)">
|
|
<div class="bnd-modal-inner">
|
|
<div class="bnd-modal-hdr">
|
|
<span id="bnd-modal-title"><i class="fas fa-file-signature"></i> Consentimiento</span>
|
|
<button onclick="_bndCerrarConsent()"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div class="bnd-modal-body">
|
|
<div class="bnd-modal-loading" id="bnd-modal-loading">
|
|
<i class="fas fa-spinner fa-spin"></i> Cargando...
|
|
</div>
|
|
<iframe id="bnd-modal-iframe" src="" style="display:none"
|
|
onload="document.getElementById('bnd-modal-loading').style.display='none';this.style.display='block'">
|
|
</iframe>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bnd-toast" id="bnd-toast"></div>
|
|
|
|
<script>
|
|
const BND_API = 'modules/turnero/api/get_bandeja.php';
|
|
const COM_API = 'modules/turnero/api/comentarios.php';
|
|
const VISTO_API= 'modules/turnero/api/marcar_visto.php';
|
|
|
|
let _bndTurnoId = null;
|
|
let _bndAllData = { pendientes: [], vistos: [] };
|
|
|
|
function _hora(dt) {
|
|
if (!dt) return '';
|
|
return new Date(dt.replace(' ','T')).toLocaleTimeString('es-CO',{hour:'2-digit',minute:'2-digit'});
|
|
}
|
|
function _toast(msg, ms = 2200) {
|
|
const t = document.getElementById('bnd-toast');
|
|
t.textContent = msg;
|
|
t.classList.add('show');
|
|
setTimeout(() => t.classList.remove('show'), ms);
|
|
}
|
|
|
|
// ── Lista ─────────────────────────────────────────────────────
|
|
async function _bndRefrescarLista() {
|
|
const spin = document.getElementById('bnd-spin');
|
|
spin.style.transition = 'transform .4s';
|
|
spin.style.transform = 'rotate(360deg)';
|
|
setTimeout(()=>{ spin.style.transition=''; spin.style.transform=''; }, 400);
|
|
|
|
const res = await fetch(BND_API).then(r=>r.json()).catch(()=>null);
|
|
if (!res?.ok) return;
|
|
|
|
_bndAllData = res;
|
|
const s = res.stats;
|
|
document.getElementById('st-total').innerHTML = `<i class="fas fa-users"></i> Total: ${s.total}`;
|
|
document.getElementById('st-pend').innerHTML = `<i class="fas fa-clock"></i> Por revisar: ${s.pendientes}`;
|
|
document.getElementById('st-vis').innerHTML = `<i class="fas fa-eye"></i> Vistos: ${s.vistos}`;
|
|
document.getElementById('st-mp').innerHTML = `<i class="fas fa-exclamation-triangle"></i> Muestras pend.: ${s.muestras_pendientes}`;
|
|
|
|
_bndFiltrar();
|
|
}
|
|
|
|
function _bndFiltrar() {
|
|
const q = (document.getElementById('bnd-filtro')?.value || '').toLowerCase().trim();
|
|
const match = t =>
|
|
!q ||
|
|
(t.paciente_nombre || '').toLowerCase().includes(q) ||
|
|
(t.examenes_txt || '').toLowerCase().includes(q);
|
|
|
|
_renderLista(
|
|
_bndAllData.pendientes?.filter(match) || [],
|
|
_bndAllData.vistos?.filter(match) || []
|
|
);
|
|
}
|
|
|
|
function _renderLista(pendientes, vistos) {
|
|
const el = document.getElementById('bnd-list-scroll');
|
|
const _estadoLabel = {
|
|
en_servicio: ['En servicio', '#15803d', '#dcfce7'],
|
|
en_espera_lugar: ['En espera', '#92400e', '#fef3c7'],
|
|
finalizado: ['Finalizado', '#475569', '#f1f5f9'],
|
|
ausente: ['Ausente', '#b91c1c', '#fee2e2'],
|
|
cancelado: ['Cancelado', '#b91c1c', '#fee2e2'],
|
|
};
|
|
|
|
const card = (t, tipo) => {
|
|
const sel = t.id === _bndTurnoId ? ' selected' : '';
|
|
const orden = t.numero_orden || t.codigo;
|
|
const nombre = (t.paciente_nombre || '—').split(' ').slice(0,3).join(' ');
|
|
|
|
// Badges de comentarios
|
|
let comBadges = '';
|
|
if (+t.com_recepcion > 0) comBadges += `<span class="bnd-com-dot recepcion"><i class="fas fa-comment-dots"></i> Recep.</span>`;
|
|
if (+t.com_muestras > 0) comBadges += `<span class="bnd-com-dot muestras"><i class="fas fa-comment-dots"></i> Toma</span>`;
|
|
if (+t.com_general > 0) comBadges += `<span class="bnd-com-dot general"><i class="fas fa-comment-dots"></i> Gral.</span>`;
|
|
|
|
// Label de estado
|
|
const [etiq, color, bg] = _estadoLabel[t.estado] || ['—', '#94a3b8', '#f8fafc'];
|
|
const estadoBadge = `<span style="font-size:.62rem;font-weight:700;padding:1px 6px;border-radius:8px;background:${bg};color:${color};white-space:nowrap">${etiq}</span>`;
|
|
|
|
return `<div class="bnd-card ${tipo}${sel}" onclick="_bndVerDetalle(${t.id})">
|
|
<div class="bnd-card-bar ${tipo}"></div>
|
|
<div class="bnd-card-inner">
|
|
<div class="bnd-card-top">
|
|
<span class="bnd-orden">${orden}</span>
|
|
<span class="bnd-nombre">${nombre}</span>
|
|
</div>
|
|
<div class="bnd-card-bot">
|
|
<span class="bnd-lugar-badge">${t.lugar_nombre||''}</span>
|
|
<span class="bnd-hora">${_hora(t.inicio_lugar_at)}</span>
|
|
</div>
|
|
<div class="bnd-card-bot" style="margin-top:3px">
|
|
${estadoBadge}
|
|
<div class="bnd-com-badges">${comBadges}</div>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
};
|
|
|
|
let html = `<div class="bnd-section-hdr">Por revisar (${pendientes.length})</div>`;
|
|
if (!pendientes.length) html += `<div style="padding:10px 12px;font-size:.77rem;color:#94a3b8">Sin pacientes pendientes</div>`;
|
|
pendientes.forEach(t => html += card(t, 'pendiente'));
|
|
|
|
html += `<div class="bnd-section-hdr">Vistos (${vistos.length})</div>`;
|
|
if (!vistos.length) html += `<div style="padding:10px 12px;font-size:.77rem;color:#94a3b8">Ninguno visto aún</div>`;
|
|
vistos.forEach(t => html += card(t, 'visto'));
|
|
|
|
el.innerHTML = html;
|
|
}
|
|
|
|
// ── Modal consentimiento ──────────────────────────────────────
|
|
function _bndAbrirConsent(token, nombre, ev) {
|
|
if (ev) ev.stopPropagation();
|
|
const modal = document.getElementById('bnd-modal-consent');
|
|
const iframe = document.getElementById('bnd-modal-iframe');
|
|
const loading = document.getElementById('bnd-modal-loading');
|
|
document.getElementById('bnd-modal-title').innerHTML = `<i class="fas fa-file-signature"></i> ${nombre||'Consentimiento'}`;
|
|
iframe.style.display = 'none';
|
|
iframe.src = '';
|
|
loading.style.display = 'flex';
|
|
modal.classList.add('open');
|
|
setTimeout(() => {
|
|
iframe.src = `ver_formulario_enviado.php?token=${encodeURIComponent(token)}&embed=1&compact=1&zoom=1.1`;
|
|
}, 60);
|
|
}
|
|
function _bndCerrarConsent(ev) {
|
|
if (ev && ev.target !== document.getElementById('bnd-modal-consent')) return;
|
|
document.getElementById('bnd-modal-consent').classList.remove('open');
|
|
document.getElementById('bnd-modal-iframe').src = '';
|
|
}
|
|
|
|
// ── Detalle ───────────────────────────────────────────────────
|
|
async function _bndVerDetalle(turnoId) {
|
|
_bndTurnoId = turnoId;
|
|
document.querySelectorAll('.bnd-card').forEach(c => {
|
|
c.classList.toggle('selected', c.onclick?.toString().includes(`${turnoId}`));
|
|
});
|
|
|
|
const det = document.getElementById('bnd-detail');
|
|
det.innerHTML = `<div class="bnd-empty"><i class="fas fa-spinner fa-spin"></i><p>Cargando...</p></div>`;
|
|
|
|
const res = await fetch(`${BND_API}?turno_id=${turnoId}`).then(r=>r.json()).catch(()=>null);
|
|
if (!res?.ok) { det.innerHTML = `<div class="bnd-empty"><i class="fas fa-times-circle"></i><p>Error al cargar</p></div>`; return; }
|
|
|
|
_renderDetalle(res);
|
|
}
|
|
|
|
function _renderDetalle(d) {
|
|
const t = d.turno;
|
|
const yaVisto= !!t.bandeja_visto_at;
|
|
|
|
let hdr = `<div class="bnd-dh">
|
|
<div class="bnd-dh-nombre">${t.paciente_nombre||'—'}</div>
|
|
<div class="bnd-dh-meta">
|
|
<span><b>${t.numero_orden||t.codigo}</b></span>
|
|
<span class="sep">·</span>
|
|
<span>${t.lugar_nombre||''}</span>
|
|
<span class="sep">·</span>
|
|
<span>${_hora(t.inicio_lugar_at)}</span>
|
|
</div>
|
|
<div class="bnd-dh-actions">
|
|
<button class="bnd-btn bnd-btn-pdf" onclick="window.print()"><i class="fas fa-print"></i> PDF</button>`;
|
|
|
|
if (yaVisto) {
|
|
hdr += `<button class="bnd-btn bnd-btn-ya-visto" disabled><i class="fas fa-eye"></i> Visto ${_hora(t.bandeja_visto_at)}</button>`;
|
|
} else {
|
|
hdr += `<button class="bnd-btn bnd-btn-visto" onclick="_bndMarcarVisto(${t.id})"><i class="fas fa-eye"></i> Marcar como visto</button>`;
|
|
}
|
|
hdr += `</div></div>`;
|
|
|
|
// Exámenes
|
|
let secEx = `<div class="bnd-sec"><div class="bnd-sec-title"><i class="fas fa-vial"></i> Exámenes</div>`;
|
|
const cats = Object.keys(d.examenes_por_cat||{});
|
|
if (!cats.length) {
|
|
secEx += `<span style="color:#94a3b8;font-size:.82rem">Sin exámenes registrados</span>`;
|
|
} else {
|
|
cats.forEach(cat => {
|
|
const chips = d.examenes_por_cat[cat].map(c=>`<span class="bnd-exam-chip">${c}</span>`).join('');
|
|
secEx += `<div class="bnd-cat"><div class="bnd-cat-name">${cat}</div><div class="bnd-chips">${chips}</div></div>`;
|
|
});
|
|
}
|
|
secEx += `</div>`;
|
|
|
|
// Muestras
|
|
let secM = `<div class="bnd-sec"><div class="bnd-sec-title"><i class="fas fa-tint"></i> Muestras</div>`;
|
|
if (!d.muestras?.length) {
|
|
secM += `<span style="color:#94a3b8;font-size:.82rem">Sin muestras registradas</span>`;
|
|
} else {
|
|
d.muestras.forEach(m => {
|
|
const rechazo = m.estado==='rechazada'&&m.motivo_rechazo
|
|
? `<span class="bnd-m-rechazado"> · ${m.motivo_rechazo}</span>` : '';
|
|
secM += `<div class="bnd-muestra">
|
|
<div class="bnd-m-dot ${m.estado}"></div>
|
|
<span class="bnd-m-label">${m.tipo_muestra}</span>
|
|
<span class="bnd-m-estado">${m.estado==='rechazada'?'Pendiente':m.estado}${m.recibida_at?' · '+_hora(m.recibida_at):''}</span>
|
|
${rechazo}
|
|
</div>`;
|
|
});
|
|
}
|
|
secM += `</div>`;
|
|
|
|
// Consentimientos
|
|
let secC = `<div class="bnd-sec"><div class="bnd-sec-title"><i class="fas fa-file-signature"></i> Consentimientos</div>`;
|
|
if (!d.consentimientos?.length) {
|
|
secC += `<span style="color:#94a3b8;font-size:.82rem">Sin consentimientos</span>`;
|
|
} else {
|
|
d.consentimientos.forEach(c => {
|
|
const esFirmado = c.estado==='firmado';
|
|
const ico = esFirmado ? 'firmado fas fa-check-circle' : 'pendiente fas fa-clock';
|
|
const link = c.token
|
|
? `<button onclick="_bndAbrirConsent('${c.token}','${c.formulario_nombre.replace(/'/g,"\\'")}',event)" style="background:none;border:none;cursor:pointer;font-size:.74rem;color:#3b82f6;padding:0;margin-left:4px"><i class="fas fa-eye"></i> Ver</button>` : '';
|
|
secC += `<div class="bnd-consent">
|
|
<i class="bnd-consent-ico ${ico}"></i>
|
|
<span style="font-size:.82rem">${c.formulario_nombre}</span>
|
|
${c.firmado_at?`<span style="font-size:.71rem;color:#94a3b8">${_hora(c.firmado_at)}</span>`:''}
|
|
${link}
|
|
</div>`;
|
|
});
|
|
}
|
|
secC += `</div>`;
|
|
|
|
// Comentarios
|
|
let secCom = `<div class="bnd-sec"><div class="bnd-sec-title"><i class="fas fa-comments"></i> Comentarios</div>
|
|
<div class="bnd-com-list" id="bnd-com-list">`;
|
|
if (!d.comentarios?.length) {
|
|
secCom += `<span style="color:#94a3b8;font-size:.82rem">Sin comentarios</span>`;
|
|
} else {
|
|
d.comentarios.forEach(c => {
|
|
const tStr = new Date((c.creado_at||'').replace(' ','T'))
|
|
.toLocaleTimeString('es-CO',{hour:'2-digit',minute:'2-digit'});
|
|
secCom += `<div class="bnd-com">
|
|
<div class="bnd-com-header">
|
|
<span class="bnd-com-tipo ${c.tipo}">${c.tipo}</span>
|
|
<span class="bnd-com-user">${c.usuario_nombre||''}</span>
|
|
<span class="bnd-com-date">${tStr}</span>
|
|
</div>
|
|
<div class="bnd-com-text">${c.comentario}</div>
|
|
</div>`;
|
|
});
|
|
}
|
|
secCom += `</div>
|
|
<div class="bnd-add-com" style="margin-top:10px">
|
|
<textarea id="bnd-new-com" placeholder="Agregar comentario de toma de muestras..."></textarea>
|
|
<button onclick="_bndEnviarCom(${t.id})"><i class="fas fa-paper-plane"></i> Enviar</button>
|
|
</div></div>`;
|
|
|
|
document.getElementById('bnd-detail').innerHTML = hdr + secEx + secM + secC + secCom;
|
|
}
|
|
|
|
// ── Marcar visto ──────────────────────────────────────────────
|
|
async function _bndMarcarVisto(turnoId) {
|
|
const res = await fetch(VISTO_API, {
|
|
method: 'POST',
|
|
headers: {'Content-Type':'application/json'},
|
|
body: JSON.stringify({turno_id: turnoId})
|
|
}).then(r=>r.json()).catch(()=>null);
|
|
|
|
if (!res?.ok) { _toast('Error al marcar como visto'); return; }
|
|
_toast('Marcado como visto');
|
|
await _bndRefrescarLista();
|
|
_bndVerDetalle(turnoId);
|
|
}
|
|
|
|
// ── Comentario ────────────────────────────────────────────────
|
|
async function _bndEnviarCom(turnoId) {
|
|
const ta = document.getElementById('bnd-new-com');
|
|
const txt = ta.value.trim();
|
|
if (!txt) return;
|
|
const btn = ta.nextElementSibling;
|
|
btn.disabled = true;
|
|
|
|
const res = await fetch(COM_API, {
|
|
method: 'POST',
|
|
headers: {'Content-Type':'application/json'},
|
|
body: JSON.stringify({turno_id: turnoId, comentario: txt, tipo: 'muestras'})
|
|
}).then(r=>r.json()).catch(()=>null);
|
|
|
|
btn.disabled = false;
|
|
if (!res?.ok) { _toast('Error al guardar comentario'); return; }
|
|
ta.value = '';
|
|
_toast('Comentario guardado');
|
|
_bndVerDetalle(turnoId);
|
|
}
|
|
|
|
// ── Init ──────────────────────────────────────────────────────
|
|
_bndRefrescarLista();
|
|
setInterval(_bndRefrescarLista, 30000);
|
|
</script>
|
|
|
|
<?php Layout::close(); ?>
|