This commit is contained in:
Lizandro Guarnizo
2026-03-16 21:33:01 -05:00
parent fe1d3c31b3
commit 4106840a39
2 changed files with 86 additions and 18 deletions
+2
View File
@@ -86,6 +86,7 @@ class Domicilio {
p.telefono AS paciente_telefono,
e.nombre_completo AS enfermera_nombre,
e.telefono AS enfermera_telefono,
a.enfermera_id AS enfermera_lab_id,
a.id AS asignacion_id,
a.estado AS asignacion_estado
FROM lab_domicilios d
@@ -121,6 +122,7 @@ class Domicilio {
o.local_file AS orden_local_file,
e.nombre_completo AS enfermera_nombre,
e.telefono AS enfermera_telefono,
a.enfermera_id AS enfermera_lab_id,
a.id AS asignacion_id,
a.estado AS asignacion_estado,
adm.full_name AS creado_por_nombre
+84 -18
View File
@@ -42,7 +42,7 @@ $domIdParam = (int)($_GET['id'] ?? 0);
<li><a href="lab_ordenes.php" class="nav-link"><i class="fas fa-file-medical"></i> Órdenes</a></li>
<li><a href="lab_pacientes.php" class="nav-link"><i class="fas fa-users"></i> Pacientes</a></li>
<li><a href="lab_domicilios.php" class="nav-link active"><i class="fas fa-house-medical"></i> Domicilios</a></li>
<li><a href="lab_enfermeras.php" class="nav-link"><i class="fas fa-user-nurse"></i> Enfermeras</a></li>
<li><a href="lab_enfermeras.php" class="nav-link"><i class="fas fa-user-nurse"></i> Enfermeros</a></li>
<li><a href="lab_formularios.php" class="nav-link"><i class="fas fa-wpforms"></i> Formularios</a></li>
<li><a href="lab_reportes.php" class="nav-link"><i class="fas fa-chart-bar"></i> Reportes</a></li>
<li><a href="lab_configuracion.php" class="nav-link"><i class="fas fa-sliders-h"></i> Configuración</a></li>
@@ -96,7 +96,7 @@ $domIdParam = (int)($_GET['id'] ?? 0);
</div>
<div class="col-md-2">
<select id="filtro-enfermera" class="form-select form-select-sm" onchange="cargarLista()">
<option value="">Todas las enfermeras</option>
<option value="">Todos los enfermeros</option>
</select>
</div>
<div class="col-md-2">
@@ -117,7 +117,7 @@ $domIdParam = (int)($_GET['id'] ?? 0);
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr><th>Fecha</th><th>Hora</th><th>Paciente</th><th>Enfermera</th><th>Estado</th></tr>
<tr><th>Fecha</th><th>Hora</th><th>Paciente</th><th>Enfermero</th><th>Estado</th></tr>
</thead>
<tbody id="tabla-body">
<tr><td colspan="5" class="text-center py-4 text-muted"><i class="fas fa-spinner fa-spin"></i></td></tr>
@@ -395,10 +395,39 @@ $domIdParam = (int)($_GET['id'] ?? 0);
</div>
</div>
<!-- Modal Asignar / Reasignar Enfermero -->
<div class="modal fade" id="modalAsignarEnf" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-user-nurse me-2"></i>Asignar Enfermero</h5>
<button class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" id="asig-dom-id">
<div class="mb-3">
<label class="form-label fw-semibold">Selecciona el enfermero</label>
<select class="form-select" id="asig-sel-enfermero">
<option value="">— Cargando... —</option>
</select>
</div>
<div id="asig-info-enf" class="alert alert-info py-2 small d-none"></div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button class="btn btn-primary" onclick="confirmarAsignacion()">
<i class="fas fa-check me-1"></i>Confirmar asignación
</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const modal = new bootstrap.Modal('#modalDomicilio');
let _modalRespForm = null;
let _modalRespForm = null;
let _modalAsignarEnf = null;
// ── Estado orden en el modal ───────────────────────────────────────────────
let _domOrderFile = null; // File pendiente de subir
@@ -575,7 +604,7 @@ function renderResumen(stats, sinAsignar) {
{ label:'Programados', val: stats.programado||0, color:'secondary' },
{ label:'En camino', val: stats.en_camino||0, color:'primary' },
{ label:'Completados', val: stats.completado||0, color:'success' },
{ label:'Sin enfermera',val: sinAsignar||0, color:'danger' },
{ label:'Sin enfermero',val: sinAsignar||0, color:'danger' },
];
document.getElementById('resumen-hoy').innerHTML = items.map(i =>
`<div class="col-6 col-md-3">
@@ -641,16 +670,17 @@ async function verDomicilio(id) {
<label class="form-label small text-muted text-uppercase">Estado actual</label><br>
<span class="badge bg-${COLOR_DOM[dom.estado]||'secondary'} fs-6">${esc(dom.estado)}</span>
</div>
<!-- Enfermera asignada -->
<!-- Enfermero asignado -->
<div class="mb-3">
<label class="form-label small text-muted text-uppercase">Enfermera</label>
<label class="form-label small text-muted text-uppercase">Enfermero</label>
${dom.enfermera_nombre
? `<div class="d-flex align-items-center gap-2">
? `<div class="d-flex align-items-center gap-2 flex-wrap">
<span><i class="fas fa-user-nurse text-success me-1"></i>${esc(dom.enfermera_nombre)}</span>
<button class="btn btn-xs btn-outline-secondary py-0 px-2" onclick="mostrarAsignacion(${dom.id})">Reasignar</button>
${dom.enfermera_lab_id ? `<a href="enfermero_portal.php?eid=${dom.enfermera_lab_id}" target="_blank" class="btn btn-xs btn-outline-info py-0 px-2"><i class="fas fa-eye me-1"></i>Ver portal</a>` : ''}
</div>`
: `<div class="alert alert-warning py-2 small d-flex align-items-center justify-content-between mb-0">
<span><i class="fas fa-exclamation-triangle me-2"></i>Sin enfermera asignada</span>
<span><i class="fas fa-exclamation-triangle me-2"></i>Sin enfermero asignado</span>
<button class="btn btn-sm btn-warning" onclick="mostrarAsignacion(${dom.id})"><i class="fas fa-user-plus me-1"></i>Asignar</button>
</div>`}
</div>
@@ -746,23 +776,59 @@ function cerrarDetalle() {
// ── Asignación rápida ──────────────────────────────────────────────────────
async function mostrarAsignacion(domId) {
document.getElementById('asig-dom-id').value = domId;
const sel = document.getElementById('asig-sel-enfermero');
sel.innerHTML = '<option value="">— Cargando... —</option>';
document.getElementById('asig-info-enf').classList.add('d-none');
if (!_modalAsignarEnf) _modalAsignarEnf = new bootstrap.Modal('#modalAsignarEnf');
_modalAsignarEnf.show();
const re = await fetch('api/lab/get_enfermeras.php');
const de = await re.json();
const opts = (de.data||[]).map(e => `<option value="${e.id}">${esc(e.nombre_completo)} (${e.domicilios_hoy||0} hoy)</option>`).join('');
sel.innerHTML = '<option value="">— Selecciona enfermero —</option>'
+ (de.data||[]).map(e =>
`<option value="${e.id}" data-user="${esc(e.username_acceso||'')}">${esc(e.nombre_completo)} (${e.domicilios_hoy||0} hoy)</option>`
).join('');
if (!confirm('¿Asignar enfermera?')) return;
sel.addEventListener('change', function onSelChange() {
const opt = this.options[this.selectedIndex];
const user = opt?.dataset?.user;
const info = document.getElementById('asig-info-enf');
if (this.value && user) {
info.textContent = `Usuario de acceso al portal: ${user}`;
info.classList.remove('d-none');
} else {
info.classList.add('d-none');
}
sel.removeEventListener('change', onSelChange);
sel.addEventListener('change', function() {
const o = this.options[this.selectedIndex];
const u = o?.dataset?.user;
const inf = document.getElementById('asig-info-enf');
if (this.value && u) { inf.textContent = `Usuario de acceso al portal: ${u}`; inf.classList.remove('d-none'); }
else inf.classList.add('d-none');
});
});
}
const sel = prompt(`Selecciona el ID de la enfermera:\n${(de.data||[]).map(e=>`${e.id}: ${e.nombre_completo}`).join('\n')}`);
if (!sel) return;
async function confirmarAsignacion() {
const domId = parseInt(document.getElementById('asig-dom-id').value);
const enfId = parseInt(document.getElementById('asig-sel-enfermero').value);
if (!enfId) { mostrarToast('Selecciona un enfermero', 'warning'); return; }
const rr = await fetch('api/lab/save_asignacion.php', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({ domicilio_id: domId, enfermera_id: parseInt(sel) }),
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ domicilio_id: domId, enfermera_id: enfId }),
});
const dd = await rr.json();
mostrarToast(dd.success ? dd.message : (dd.error||'Error'), dd.success?'success':'danger');
if (dd.success) { cargarLista(paginaActual); verDomicilio(domId); }
mostrarToast(dd.success ? dd.message : (dd.error||'Error'), dd.success ? 'success' : 'danger');
if (dd.success) {
_modalAsignarEnf.hide();
cargarLista(paginaActual);
verDomicilio(domId);
}
}
// ── Cambio de estado ───────────────────────────────────────────────────────