feat(bandeja): badges de comentarios y estado en tarjeta de lista

- Indicadores por tipo: Recep. (azul) / Toma (verde) / Gral. (amarillo)
- Label de estado del servicio: En servicio / En espera / Finalizado / etc.
- Query agrega SUM por tipo de comentario sin subquery adicional

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-27 21:42:55 -05:00
co-authored by Claude Sonnet 4.6
parent 0b39e3f0d0
commit b76c2f11e9
2 changed files with 40 additions and 1 deletions
+5 -1
View File
@@ -96,12 +96,16 @@ $stmt = $pdo->prepare("
t.inicio_lugar_at, t.fin_lugar_at, t.bandeja_visto_at,
ts.numero_orden,
l.nombre AS lugar_nombre,
GROUP_CONCAT(et.codigo ORDER BY et.codigo SEPARATOR ' ') AS examenes_txt
GROUP_CONCAT(DISTINCT et.codigo ORDER BY et.codigo SEPARATOR ' ') AS examenes_txt,
SUM(tc.tipo = 'recepcion') AS com_recepcion,
SUM(tc.tipo = 'muestras') AS com_muestras,
SUM(tc.tipo = 'general') AS com_general
FROM turnero_turnos t
JOIN turnero_solicitudes ts ON ts.turno_id = t.id
JOIN turnero_lugares l ON l.id = t.lugar_destino_id
LEFT JOIN turnero_examen_items tei ON tei.solicitud_id = ts.id
LEFT JOIN exam_tipos et ON et.id = tei.exam_tipo_id
LEFT JOIN turnero_comentarios tc ON tc.turno_id = t.id
WHERE t.sesion_id = ? AND t.inicio_lugar_at IS NOT NULL
GROUP BY t.id
ORDER BY ts.numero_orden ASC
+35
View File
@@ -134,6 +134,18 @@ Layout::open('Bandeja del día', 'fas fa-layer-group');
.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; }
@@ -382,10 +394,29 @@ function _bndFiltrar() {
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">
@@ -397,6 +428,10 @@ function _renderLista(pendientes, vistos) {
<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>`;
};