up
This commit is contained in:
@@ -525,7 +525,8 @@ let pollingColaId = null;
|
||||
const API = '<?= BASE_URL ?>modules/turnero/api/';
|
||||
const API_PAC = '<?= BASE_URL ?>api/lab/get_pacientes.php';
|
||||
const BASE_WA = '<?= BASE_URL ?>';
|
||||
const DESK_ID = <?= $deskId ?: 'null' ?>;
|
||||
const DESK_ID = <?= $deskId ?: 'null' ?>;
|
||||
const DESK_NOMBRE = '<?= addslashes($deskNombre ?? 'Recepción') ?>';
|
||||
|
||||
// ── Arranque ──────────────────────────────────────────────────
|
||||
let pollingConsentimientosId = null;
|
||||
@@ -1365,6 +1366,183 @@ function mostrarLlamando(codigo) {
|
||||
mostrarToast('Llamando turno ' + codigo + '…', 'info', 2000);
|
||||
}
|
||||
|
||||
/* ── Ocupación exclusiva del escritorio ──────────────────────── */
|
||||
(function(_ID, _NOMBRE, _VIEW, _PARAM) {
|
||||
if (!_ID) return;
|
||||
|
||||
function _e(s) {
|
||||
const d = document.createElement('div');
|
||||
d.appendChild(document.createTextNode(String(s ?? '')));
|
||||
return d.innerHTML;
|
||||
}
|
||||
function _post(body) {
|
||||
return fetch(API + 'ocupar_lugar.php', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(Object.assign({ lugar_id: _ID }, body)),
|
||||
}).then(r => r.json());
|
||||
}
|
||||
function _redirigirSiguiente(disponibles) {
|
||||
if (disponibles && disponibles.length) {
|
||||
window.location.href = BASE_WA + 'erp.php?m=turnero&v=' + _VIEW + '&' + _PARAM + '=' + disponibles[0].id;
|
||||
} else {
|
||||
window.location.href = BASE_WA + 'erp.php?m=turnero';
|
||||
}
|
||||
}
|
||||
|
||||
/* Pantalla de bloqueo */
|
||||
function _mostrarBloqueado(ocupadoPor) {
|
||||
document.body.innerHTML =
|
||||
'<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;' +
|
||||
'min-height:100vh;background:#f8faff;font-family:sans-serif;gap:14px;text-align:center;padding:28px">' +
|
||||
'<div style="font-size:4rem">🔒</div>' +
|
||||
'<h2 style="color:#1565c0;margin:0">' + _e(_NOMBRE) + ' está abierta en otro equipo</h2>' +
|
||||
'<p style="color:#555;font-size:1.05rem;max-width:440px;line-height:1.6">' +
|
||||
'Actualmente usada por <strong>' + _e(ocupadoPor) + '</strong>.<br>' +
|
||||
'Puedes solicitar que cierre su sesión o ir al siguiente escritorio disponible.</p>' +
|
||||
'<div style="display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:4px">' +
|
||||
'<button id="_btn-solicitar" onclick="window._ocToma()" ' +
|
||||
'style="padding:12px 26px;background:#1565c0;color:#fff;border:none;border-radius:8px;font-size:1rem;cursor:pointer;font-weight:600">' +
|
||||
'📢 Solicitar cierre en ese equipo</button>' +
|
||||
'<button id="_btn-siguiente" onclick="window._ocSiguiente()" ' +
|
||||
'style="padding:12px 26px;background:#f0f4ff;color:#1565c0;border:2px solid #1565c0;border-radius:8px;font-size:1rem;cursor:pointer;font-weight:600">' +
|
||||
'➡ Ir al siguiente disponible</button>' +
|
||||
'</div>' +
|
||||
'<div id="_oc-estado" style="min-height:24px;color:#777;font-size:.95rem;margin-top:4px"></div>' +
|
||||
'</div>';
|
||||
}
|
||||
function _setEstado(msg, color) {
|
||||
const el = document.getElementById('_oc-estado');
|
||||
if (el) el.innerHTML = '<span style="color:' + (color||'#555') + '">' + msg + '</span>';
|
||||
}
|
||||
|
||||
/* Solicitar toma de control */
|
||||
let _checkTransferTimer = null;
|
||||
window._ocToma = async function() {
|
||||
const btn = document.getElementById('_btn-solicitar');
|
||||
if (btn) btn.disabled = true;
|
||||
_setEstado('Enviando solicitud…', '#555');
|
||||
try {
|
||||
const j = await _post({ action: 'solicitar' });
|
||||
if (!j.ok) { _setEstado('Error al enviar solicitud.', '#c62828'); if (btn) btn.disabled = false; return; }
|
||||
if (j.transferido) { location.reload(); return; }
|
||||
_setEstado('✉ Solicitud enviada. El otro equipo tiene 5 segundos para responder…', '#1565c0');
|
||||
clearInterval(_checkTransferTimer);
|
||||
_checkTransferTimer = setInterval(async () => {
|
||||
try {
|
||||
const r = await _post({ action: 'check_transfer' });
|
||||
if (r.disponible) {
|
||||
clearInterval(_checkTransferTimer);
|
||||
_setEstado('✅ Escritorio liberado. Tomando control…', '#2e7d32');
|
||||
const rc = await _post({ action: 'claim' });
|
||||
if (rc.disponible) location.reload();
|
||||
else _setEstado('No se pudo tomar el control. Recargue la página.', '#c62828');
|
||||
} else if (r.denegado) {
|
||||
clearInterval(_checkTransferTimer);
|
||||
_setEstado('❌ La solicitud fue denegada.', '#c62828');
|
||||
if (btn) { btn.disabled = false; btn.textContent = '📢 Volver a solicitar'; }
|
||||
}
|
||||
} catch(_) {}
|
||||
}, 1500);
|
||||
} catch(e) {
|
||||
_setEstado('Error de red: ' + e.message, '#c62828');
|
||||
if (btn) btn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Ir al siguiente disponible */
|
||||
window._ocSiguiente = async function() {
|
||||
const btn = document.getElementById('_btn-siguiente');
|
||||
if (btn) btn.disabled = true;
|
||||
_setEstado('Buscando escritorio disponible…', '#555');
|
||||
try {
|
||||
const j = await _post({ action: 'disponibles' });
|
||||
if (!j.ok || !j.disponibles.length) {
|
||||
_setEstado('No hay otros escritorios disponibles.', '#c62828');
|
||||
if (btn) btn.disabled = false;
|
||||
return;
|
||||
}
|
||||
_redirigirSiguiente(j.disponibles);
|
||||
} catch(e) {
|
||||
_setEstado('Error de red.', '#c62828');
|
||||
if (btn) btn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Modal de solicitud entrante (para el ocupante actual) */
|
||||
let _modalActivo = false;
|
||||
function _mostrarModalSolicitud(solicitante) {
|
||||
if (_modalActivo) return;
|
||||
_modalActivo = true;
|
||||
const modal = document.createElement('div');
|
||||
modal.style.cssText =
|
||||
'position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:99999;display:flex;align-items:center;justify-content:center';
|
||||
modal.innerHTML =
|
||||
'<div style="background:#fff;border-radius:14px;padding:32px 28px;max-width:420px;width:92%;text-align:center;box-shadow:0 8px 32px rgba(0,0,0,.25)">' +
|
||||
'<div style="font-size:2.5rem">⚠️</div>' +
|
||||
'<h3 style="color:#c62828;margin:10px 0 6px">Solicitud de transferencia</h3>' +
|
||||
'<p style="color:#333;margin:0 0 6px"><strong>' + _e(solicitante) + '</strong> quiere usar este escritorio.</p>' +
|
||||
'<p style="color:#555;font-size:.95rem">Si no responde, se cerrará automáticamente en <strong id="_sol-cnt">5</strong> segundos.</p>' +
|
||||
'<div style="display:flex;gap:10px;justify-content:center;margin-top:18px">' +
|
||||
'<button id="_sol-aceptar" style="padding:10px 22px;background:#c62828;color:#fff;border:none;border-radius:8px;font-size:1rem;cursor:pointer;font-weight:600">Aceptar y ceder</button>' +
|
||||
'<button id="_sol-denegar" style="padding:10px 22px;background:#f5f5f5;color:#333;border:1px solid #ccc;border-radius:8px;font-size:1rem;cursor:pointer">Denegar</button>' +
|
||||
'</div></div>';
|
||||
document.body.appendChild(modal);
|
||||
|
||||
let secs = 5;
|
||||
const tick = setInterval(() => {
|
||||
secs--;
|
||||
const el = document.getElementById('_sol-cnt');
|
||||
if (el) el.textContent = secs;
|
||||
if (secs <= 0) { clearInterval(tick); _liberar(); }
|
||||
}, 1000);
|
||||
|
||||
async function _liberar() {
|
||||
modal.remove();
|
||||
await _post({ action: 'aceptar' }).catch(() => {});
|
||||
try {
|
||||
const j = await _post({ action: 'disponibles' });
|
||||
_redirigirSiguiente(j.disponibles || []);
|
||||
} catch(_) {
|
||||
window.location.href = BASE_WA + 'erp.php?m=turnero';
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('_sol-aceptar').onclick = () => { clearInterval(tick); _liberar(); };
|
||||
document.getElementById('_sol-denegar').onclick = async () => {
|
||||
clearInterval(tick);
|
||||
modal.remove();
|
||||
_modalActivo = false;
|
||||
await _post({ action: 'denegar' }).catch(() => {});
|
||||
};
|
||||
}
|
||||
|
||||
/* Arranque */
|
||||
async function _iniciar() {
|
||||
try {
|
||||
const j = await _post({ action: 'claim' });
|
||||
if (!j.ok) return;
|
||||
if (!j.disponible) { _mostrarBloqueado(j.ocupado_por); return; }
|
||||
// Heartbeat cada 60 s
|
||||
setInterval(() => _post({ action: 'ping' }).catch(() => {}), 60000);
|
||||
// Polling de solicitudes entrantes cada 2 s
|
||||
setInterval(async () => {
|
||||
if (_modalActivo) return;
|
||||
try {
|
||||
const r = await _post({ action: 'check_solicitud' });
|
||||
if (r.hay_solicitud) _mostrarModalSolicitud(r.solicitante);
|
||||
} catch(_) {}
|
||||
}, 2000);
|
||||
} catch(_) {}
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', () => {
|
||||
navigator.sendBeacon(API + 'ocupar_lugar.php',
|
||||
new Blob([JSON.stringify({ lugar_id: _ID, action: 'release' })], { type: 'application/json' }));
|
||||
});
|
||||
|
||||
_iniciar();
|
||||
})(DESK_ID, DESK_NOMBRE, 'recepcion', 'desk_id');
|
||||
|
||||
// ── Toast ────────────────────────────────────────────────────
|
||||
let toastTimer = null;
|
||||
function mostrarToast(msg, type = 'info', duration = 2500) {
|
||||
|
||||
Reference in New Issue
Block a user