feat: encuesta de satisfacción post-finalizar toma de muestras
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4a4cbc31b8
commit
2455417bb4
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* POST /modules/turnero/api/enviar_encuesta.php
|
||||
* Envía la plantilla "encuesta" al paciente del turno vía WhatsApp turnero.
|
||||
* Body JSON: { turno_id: int }
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
require_once __DIR__ . '/../../../services/WhatsAppService.php';
|
||||
requireMethod('POST');
|
||||
requireTurnero();
|
||||
|
||||
$body = inputJson();
|
||||
$turnoId = (int)($body['turno_id'] ?? 0);
|
||||
if (!$turnoId) jsonError('turno_id requerido.');
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Obtener user_id y teléfono del paciente vía turnero_turnos → lab_pacientes → users
|
||||
$row = $pdo->prepare(
|
||||
"SELECT u.id AS user_id, u.phone_number, t.paciente_cel, t.paciente_nombre
|
||||
FROM turnero_turnos t
|
||||
LEFT JOIN lab_pacientes lp ON lp.id = t.paciente_id
|
||||
LEFT JOIN users u ON u.id = lp.user_id
|
||||
WHERE t.id = ? LIMIT 1"
|
||||
);
|
||||
$row->execute([$turnoId]);
|
||||
$pac = $row->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$pac) jsonError('Turno no encontrado.', 404);
|
||||
|
||||
$userId = $pac['user_id'] ? (int)$pac['user_id'] : null;
|
||||
$phone = $pac['phone_number'] ?? null;
|
||||
|
||||
// Fallback: buscar por paciente_cel si no hay user_id
|
||||
if (!$userId && !empty($pac['paciente_cel'])) {
|
||||
$cel = preg_replace('/\D/', '', $pac['paciente_cel']);
|
||||
$u2 = $pdo->prepare("SELECT id, phone_number FROM users WHERE REPLACE(phone_number,'+','') LIKE ? LIMIT 1");
|
||||
$u2->execute(['%' . substr($cel, -10)]);
|
||||
$uRow = $u2->fetch(PDO::FETCH_ASSOC);
|
||||
if ($uRow) { $userId = (int)$uRow['id']; $phone = $uRow['phone_number']; }
|
||||
}
|
||||
|
||||
if (!$userId || !$phone) jsonError('El paciente no tiene número de WhatsApp registrado.');
|
||||
|
||||
try {
|
||||
$wa = new WhatsAppService('turnero');
|
||||
$meta = ['canal' => 'turnero', 'operator_id' => adminId()];
|
||||
$wa->sendTemplateMessage($phone, 'encuesta', 'es_CO', [], [], null, $meta);
|
||||
jsonOk(['mensaje' => 'Encuesta enviada a ' . ($pac['paciente_nombre'] ?? $phone)]);
|
||||
} catch (\Throwable $e) {
|
||||
jsonError('Error al enviar: ' . $e->getMessage());
|
||||
}
|
||||
@@ -994,6 +994,26 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Bar encuesta post-finalizar ─────────────────────────────── -->
|
||||
<div id="bar-encuesta" style="
|
||||
display:none;position:fixed;bottom:0;left:0;right:0;z-index:9100;
|
||||
background:#0f4c81;color:#fff;padding:14px 20px;
|
||||
display:none;align-items:center;gap:14px;flex-wrap:wrap;
|
||||
box-shadow:0 -4px 20px rgba(0,0,0,.25)">
|
||||
<i class="fas fa-star" style="font-size:1.2rem;color:#fbbf24;flex-shrink:0"></i>
|
||||
<span id="bar-encuesta-txt" style="flex:1;font-size:.95rem;font-weight:500"></span>
|
||||
<button onclick="_enviarEncuesta()" id="btn-enc-enviar"
|
||||
style="background:#22c55e;color:#fff;border:none;border-radius:8px;
|
||||
padding:8px 18px;font-weight:600;cursor:pointer;white-space:nowrap">
|
||||
<i class="fas fa-paper-plane me-1"></i>Enviar encuesta
|
||||
</button>
|
||||
<button onclick="_cerrarEncuestaBar()"
|
||||
style="background:rgba(255,255,255,.15);color:#fff;border:none;border-radius:8px;
|
||||
padding:8px 14px;cursor:pointer;white-space:nowrap">
|
||||
Omitir
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- ── Modal de consentimiento embebido (modo embebido) ────────── -->
|
||||
<div id="modal-consentimiento" style="
|
||||
display:none;position:fixed;inset:0;z-index:9000;
|
||||
@@ -1961,7 +1981,9 @@ async function finalizarAtencion() {
|
||||
if (hayPendientes) { mostrarError('Debe firmar todos los consentimientos antes de finalizar.'); return; }
|
||||
if (hayMuestrasPendientes) { mostrarError('Debe marcar cada muestra como recibida o pendiente antes de finalizar.'); return; }
|
||||
if (!confirm(`¿Finalizar atención del turno ${turnoActivo.codigo}?`)) return;
|
||||
await cambiarEstadoTurno('finalizado');
|
||||
const _t = { id: turnoActivo.id, paciente_nombre: turnoActivo.paciente_nombre };
|
||||
const ok = await cambiarEstadoTurno('finalizado');
|
||||
if (ok) _ofrecerEncuesta(_t);
|
||||
}
|
||||
|
||||
async function marcarAusente() {
|
||||
@@ -2024,15 +2046,58 @@ async function cambiarEstadoTurno(nuevoEstado) {
|
||||
} else {
|
||||
mostrarError(json.error);
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
resetFicha();
|
||||
cargarCola();
|
||||
return true;
|
||||
} catch (err) {
|
||||
mostrarError(err.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Encuesta post-finalizar ───────────────────────────────────
|
||||
let _encuestaTurnoId = null, _encuestaTimer = null;
|
||||
|
||||
function _ofrecerEncuesta(turno) {
|
||||
_encuestaTurnoId = turno.id;
|
||||
const bar = document.getElementById('bar-encuesta');
|
||||
document.getElementById('bar-encuesta-txt').textContent =
|
||||
`¿Enviar encuesta de satisfacción a ${turno.paciente_nombre || 'el paciente'}?`;
|
||||
document.getElementById('btn-enc-enviar').disabled = false;
|
||||
document.getElementById('btn-enc-enviar').innerHTML = '<i class="fas fa-paper-plane me-1"></i>Enviar encuesta';
|
||||
bar.style.display = 'flex';
|
||||
clearTimeout(_encuestaTimer);
|
||||
_encuestaTimer = setTimeout(_cerrarEncuestaBar, 12000);
|
||||
}
|
||||
|
||||
async function _enviarEncuesta() {
|
||||
if (!_encuestaTurnoId) return;
|
||||
const btn = document.getElementById('btn-enc-enviar');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Enviando…';
|
||||
try {
|
||||
const res = await fetch(API + 'enviar_encuesta.php', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ turno_id: _encuestaTurnoId }),
|
||||
});
|
||||
const json = await res.json();
|
||||
_cerrarEncuestaBar();
|
||||
if (json.ok) mostrarToast('Encuesta enviada ✓', 'success', 3000);
|
||||
else mostrarToast('No se pudo enviar: ' + (json.error || 'error'), 'warning', 4000);
|
||||
} catch (e) {
|
||||
_cerrarEncuestaBar();
|
||||
mostrarToast('Error al enviar encuesta', 'warning', 3000);
|
||||
}
|
||||
}
|
||||
|
||||
function _cerrarEncuestaBar() {
|
||||
clearTimeout(_encuestaTimer);
|
||||
document.getElementById('bar-encuesta').style.display = 'none';
|
||||
_encuestaTurnoId = null;
|
||||
}
|
||||
|
||||
// ── Reset ficha ───────────────────────────────────────────────
|
||||
function resetFicha() {
|
||||
clearInterval(pollingConsentId);
|
||||
|
||||
Reference in New Issue
Block a user