This commit is contained in:
Lizandro Guarnizo
2026-04-07 15:57:53 -05:00
parent ded060e161
commit 4f1b2e146c
5 changed files with 321 additions and 98 deletions
+95 -13
View File
@@ -185,6 +185,13 @@ $hoy = date('Y-m-d');
transition:transform .2s; }
.fin-section-toggle.open .fin-chev { transform:rotate(180deg); }
#seccion-fin { display:none; }
/* ── Modal temperatura ── */
#modalTemperatura .temp-value-wrap { position:relative; }
#modalTemperatura .temp-unit { position:absolute; right:12px; top:50%; transform:translateY(-50%);
font-weight:700; color:#6b7280; pointer-events:none; }
#modalTemperatura input[type=number] { padding-right:36px; font-size:1.25rem;
font-weight:700; text-align:center; letter-spacing:2px; }
</style>
</head>
<body>
@@ -241,7 +248,35 @@ $hoy = date('Y-m-d');
</div>
</div>
<!-- ═══════════════════════ MODAL: Confirmar cancel ══════════════════ -->
<!-- ═══════════════════════ MODAL: Temperatura ═════════════════════ -->
<div class="modal fade" id="modalTemperatura" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-sm modal-dialog-centered">
<div class="modal-content">
<div class="modal-header py-2" style="background:#0d6efd;color:#fff">
<h6 class="modal-title mb-0" id="temp-modal-titulo">🌡️ Temperatura</h6>
</div>
<div class="modal-body text-center py-4">
<p class="text-muted small mb-3">Registra la temperatura corporal del paciente</p>
<div class="temp-value-wrap d-inline-block">
<input type="number" id="temp-modal-valor" class="form-control form-control-lg"
step="0.1" min="30" max="45" placeholder="36.5"
onkeydown="if(event.key==='Enter')tempModal.confirmar()">
<span class="temp-unit">&deg;C</span>
</div>
<div id="temp-modal-error" class="text-danger small mt-2" style="display:none">
Ingresa un valor válido entre 30 y 45 °C
</div>
</div>
<div class="modal-footer py-2 justify-content-center">
<button class="btn btn-primary px-5" onclick="tempModal.confirmar()">
<i class="fas fa-check me-1"></i>Confirmar
</button>
</div>
</div>
</div>
</div>
<!-- ═══════════════════════ MODAL: Confirmar cancel ═════════════════════ -->
<div class="modal fade" id="modalCancelar" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
@@ -622,7 +657,7 @@ const portal = {
<!-- Horas de llegada / salida (auto-registradas) -->
${(item.hora_llegada || item.hora_salida) ? `
<div class="d-flex gap-3 small mt-1 mb-2">
<div class="d-flex gap-3 small mt-1 mb-1 flex-wrap">
${item.hora_llegada ? `<span class="text-success"><i class="fas fa-sign-in-alt me-1"></i>Llegada: <strong>${item.hora_llegada.slice(0,5)}</strong></span>` : ''}
${item.hora_salida ? `<span class="text-danger"><i class="fas fa-sign-out-alt me-1"></i>Salida: <strong>${item.hora_salida.slice(0,5)}</strong></span>` : ''}
${item.hora_llegada && item.hora_salida ? (() => {
@@ -632,7 +667,12 @@ const portal = {
if (mins > 0) return `<span class="text-info"><i class="fas fa-stopwatch me-1"></i>${mins>=60?Math.floor(mins/60)+'h '+mins%60+'min':mins+' min'}</span>`;
return '';
})() : ''}
</div>` : ''}
</div>
${(item.temperatura_inicio || item.temperatura_salida) ? `
<div class="d-flex gap-3 small mb-2">
${item.temperatura_inicio ? `<span class="text-primary"><i class="fas fa-thermometer-half me-1"></i>Tº inicio: <strong>${item.temperatura_inicio}°C</strong></span>` : ''}
${item.temperatura_salida ? `<span class="text-warning"><i class="fas fa-thermometer-full me-1"></i>Tº salida: <strong>${item.temperatura_salida}°C</strong></span>` : ''}
</div>` : ''}` : ''}
<!-- Órdenes médicas (multi-archivo) -->
${renderOrdenesEnfermero(item)}
@@ -695,10 +735,17 @@ const portal = {
},
// ── Cambiar estado ─────────────────────────────────────────────────────
async actualizarEstado(domId, nuevoEstado, notas = '') {
// ── BLOQUEO: para completar es obligatorio tener al menos una nota ──
async actualizarEstado(domId, nuevoEstado, notas = '', extraDatos = {}) {
// ── BLOQUEO 1: en_domicilio requiere temperatura de inicio ──
if (nuevoEstado === 'en_domicilio' && extraDatos.temperatura_inicio === undefined) {
tempModal.abrir('🌡️ Temperatura de inicio', async (temp) => {
await portal.actualizarEstado(domId, nuevoEstado, notas, { temperatura_inicio: temp });
});
return;
}
// ── BLOQUEO 2: para completar es obligatorio tener ficha clínica ──
if (nuevoEstado === 'completado') {
// Verificar en caché o cargar desde API
let cache = notasManager._cache[domId];
if (!cache) {
try {
@@ -714,12 +761,9 @@ const portal = {
cache = { clinica: null, libres: [] };
}
}
const tieneNota = cache.clinica !== null;
if (!tieneNota) {
// Abrir la ficha clínica directamente (es la nota obligatoria)
if (!cache.clinica) {
notasManager._pendingCompleteId = domId;
notasManager.abrirFicha(domId);
// Colocar banner de advertencia en la parte superior del sheet
const inner = document.getElementById('nota-sheet-inner');
if (inner) {
const banner = document.createElement('div');
@@ -730,18 +774,30 @@ const portal = {
}
return;
}
// ── BLOQUEO 3: completado requiere temperatura de salida ──
if (extraDatos.temperatura_salida === undefined) {
tempModal.abrir('🌡️ Temperatura de salida', async (temp) => {
await portal.actualizarEstado(domId, nuevoEstado, notas, { ...extraDatos, temperatura_salida: temp });
});
return;
}
}
try {
const r = await fetch('api/lab/update_domicilio_enfermero.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ domicilio_id: domId, nuevo_estado: nuevoEstado, notas }),
body: JSON.stringify({ domicilio_id: domId, nuevo_estado: nuevoEstado, notas, ...extraDatos }),
});
const d = await r.json();
if (!d.success) throw new Error(d.error);
// Actualizar estado en memoria y re-render
// Actualizar estado y temperaturas en memoria
const item = this._agenda.find(a => a.domicilio_id == domId);
if (item) item.domicilio_estado = nuevoEstado;
if (item) {
item.domicilio_estado = nuevoEstado;
if (extraDatos.temperatura_inicio !== undefined) item.temperatura_inicio = extraDatos.temperatura_inicio;
if (extraDatos.temperatura_salida !== undefined) item.temperatura_salida = extraDatos.temperatura_salida;
}
this._renderLista();
this._renderResumen(
Object.fromEntries(
@@ -1475,6 +1531,32 @@ const agendaNueva = {
};
</script>
<script>
// ══════════════════════════════════════════════════════════════════════
// tempModal — Modal de captura de temperatura (inicio / salida)
// ══════════════════════════════════════════════════════════════════════
const tempModal = {
_modal: null,
_cb: null,
abrir(titulo, cb) {
this._cb = cb;
document.getElementById('temp-modal-titulo').textContent = titulo;
document.getElementById('temp-modal-valor').value = '';
document.getElementById('temp-modal-error').style.display = 'none';
if (!this._modal) this._modal = new bootstrap.Modal('#modalTemperatura', { backdrop: 'static', keyboard: false });
this._modal.show();
setTimeout(() => document.getElementById('temp-modal-valor').focus(), 350);
},
confirmar() {
const val = parseFloat(document.getElementById('temp-modal-valor').value);
const err = document.getElementById('temp-modal-error');
if (!val || val < 30 || val > 45) { err.style.display = ''; return; }
this._modal.hide();
if (this._cb) this._cb(val);
},
};
</script>
<script>
// ═══════════════════════════════════════════════════════
// formEnvio — Lógica de envío de formularios