This commit is contained in:
Lizandro Guarnizo
2026-06-18 09:35:17 -05:00
parent c58998599b
commit 8d577947a6
7 changed files with 87 additions and 12 deletions
+3 -3
View File
@@ -135,16 +135,16 @@ try {
if (!str_starts_with($cel, '+')) {
$cel = '+57' . ltrim($cel, '0');
}
$nombrePacWA = $pacienteNombre ?: 'Paciente';
require_once __DIR__ . '/../../../services/WhatsAppService.php';
try {
$wa = new WhatsAppService();
// Enviar solo el código, sin nombre/apellido
$wa->sendTemplateMessage(
$cel,
$waTemplate,
$waLang,
[
htmlspecialchars($nombrePacWA, ENT_QUOTES),
'Paciente',
$codigo,
'',
],
@@ -152,7 +152,7 @@ try {
);
} catch (\Throwable $eTmpl) {
try {
$mensajeTexto = "Hola {$nombrePacWA}, su turno *{$codigo}* ha sido registrado en {$codigo}. Preséntese al laboratorio.";
$mensajeTexto = "Su turno *{$codigo}* ha sido registrado. Preséntese al laboratorio.";
$wa->sendTextMessage($cel, $mensajeTexto);
} catch (\Throwable $eTxt) {
// Silenciar
+4 -2
View File
@@ -14,6 +14,8 @@ $input = inputJson();
$id = (int)($input['id'] ?? 0);
$nombre = trim($input['nombre'] ?? '');
$color = trim($input['color'] ?? '#6b7280');
$icono = trim($input['icono'] ?? null) ?: null;
$descripcion = trim($input['descripcion'] ?? null) ?: null;
$ordenPeso = (int)($input['orden_peso'] ?? 1);
$activo = (int)($input['activo'] ?? 1);
@@ -23,9 +25,9 @@ if ($ordenPeso < 1) jsonError('El orden debe ser mayor a 0');
if (!preg_match('/^#[0-9a-f]{6}$/i', $color)) jsonError('Color hexadecimal inválido (formato: #RRGGBB)');
$stmt = db()->prepare(
'UPDATE turnero_prioridades SET nombre=?, color=?, orden_peso=?, activo=? WHERE id=?'
'UPDATE turnero_prioridades SET nombre=?, color=?, icono=?, descripcion=?, orden_peso=?, activo=? WHERE id=?'
);
$stmt->execute([$nombre, $color, $ordenPeso, $activo, $id]);
$stmt->execute([$nombre, $color, $icono, $descripcion, $ordenPeso, $activo, $id]);
if ($stmt->rowCount() === 0) {
jsonError('Prioridad no encontrada', 404);
+28 -3
View File
@@ -575,7 +575,7 @@ $tab = $_GET['tab'] ?? 'lugares';
<span class="badge <?= $pr['activo'] ? 'bg-success-subtle text-success' : 'bg-secondary-subtle text-secondary' ?>">
<?= $pr['activo'] ? 'Activo' : 'Inactivo' ?>
</span>
<button class="btn-icon text-primary" onclick="editarPrioridad(<?= $pr['id'] ?>,'<?= addslashes($pr['codigo']) ?>','<?= addslashes($pr['nombre']) ?>','<?= htmlspecialchars($pr['color']) ?>',<?= $pr['orden_peso'] ?>,<?= $pr['activo'] ?>)" title="Editar">
<button class="btn-icon text-primary" onclick="editarPrioridad(<?= $pr['id'] ?>,'<?= addslashes($pr['codigo']) ?>','<?= addslashes($pr['nombre']) ?>','<?= htmlspecialchars($pr['color']) ?>','<?= htmlspecialchars($pr['icono'] ?? '') ?>','<?= addslashes($pr['descripcion'] ?? '') ?>',<?= $pr['orden_peso'] ?>,<?= $pr['activo'] ?>)" title="Editar">
<i class="fas fa-pencil-alt"></i>
</button>
</div>
@@ -618,6 +618,27 @@ $tab = $_GET['tab'] ?? 'lugares';
<input type="number" id="edit-pr-orden" class="form-control form-control-sm" min="1">
</div>
</div>
<div class="mb-2">
<label class="form-label small fw-semibold">Icono</label>
<select id="edit-pr-icono" class="form-select form-select-sm">
<option value="">— Sin icono —</option>
<option value="fas fa-child">👶 Niños (fas fa-child)</option>
<option value="fas fa-heart">❤ Embarazada (fas fa-heart)</option>
<option value="fas fa-person-cane">🦯 Adulto mayor (fas fa-person-cane)</option>
<option value="fas fa-wheelchair">♿ Discapacidad (fas fa-wheelchair)</option>
<option value="fas fa-user">👤 Paciente general (fas fa-user)</option>
<option value="fas fa-vial">🧪 Muestra (fas fa-vial)</option>
<option value="fas fa-heartbeat">💓 Embarazada alt (fas fa-heartbeat)</option>
<option value="fas fa-venus">♀ Mujer (fas fa-venus)</option>
<option value="fas fa-baby">🍼 Bebé (fas fa-baby)</option>
<option value="fas fa-star">⭐ VIP (fas fa-star)</option>
</select>
</div>
<div class="mb-2">
<label class="form-label small fw-semibold">Descripción</label>
<textarea id="edit-pr-descripcion" class="form-control form-control-sm" rows="2" maxlength="200" placeholder="Descripción para el kiosko"></textarea>
<small class="text-muted">Se muestra bajo el nombre en el kiosko de turnos</small>
</div>
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="edit-pr-activo">
<label class="form-check-label small" for="edit-pr-activo">Activo</label>
@@ -993,12 +1014,14 @@ async function eliminarExamen(id, nombre) {
// ─────────────────────────────────────────────────────────────
// TAB 3: PRIORIDADES
// ─────────────────────────────────────────────────────────────
function editarPrioridad(id, codigo, nombre, color, orden, activo) {
function editarPrioridad(id, codigo, nombre, color, icono, descripcion, orden, activo) {
document.getElementById('edit-pr-id').value = id;
document.getElementById('edit-pr-codigo').value = codigo;
document.getElementById('edit-pr-nombre').value = nombre;
document.getElementById('edit-pr-color').value = color;
document.getElementById('edit-pr-color-text').value = color;
document.getElementById('edit-pr-icono').value = icono || '';
document.getElementById('edit-pr-descripcion').value = descripcion || '';
document.getElementById('edit-pr-orden').value = orden;
document.getElementById('edit-pr-activo').checked = !!activo;
new bootstrap.Modal(document.getElementById('modalEditarPrioridad')).show();
@@ -1022,6 +1045,8 @@ async function guardarPrioridad() {
const id = parseInt(document.getElementById('edit-pr-id').value);
const nombre = document.getElementById('edit-pr-nombre').value.trim();
const color = document.getElementById('edit-pr-color-text').value.trim() || document.getElementById('edit-pr-color').value;
const icono = document.getElementById('edit-pr-icono').value.trim() || null;
const descripcion = document.getElementById('edit-pr-descripcion').value.trim() || null;
const orden = parseInt(document.getElementById('edit-pr-orden').value) || 1;
const activo = document.getElementById('edit-pr-activo').checked ? 1 : 0;
@@ -1031,7 +1056,7 @@ async function guardarPrioridad() {
try {
const res = await fetch(API + 'save_prioridad.php', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id, nombre, color, orden_peso: orden, activo })
body: JSON.stringify({ id, nombre, color, icono, descripcion, orden_peso: orden, activo })
});
const json = await res.json();
if (!json.ok) { toast(json.error || 'Error', 'error'); return; }
+16 -3
View File
@@ -207,10 +207,10 @@ unset($p);
.btn-prioridad:active { transform: scale(.95); filter: brightness(.93); }
.btn-prioridad:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,.13); }
.btn-prioridad .icon-wrap {
width: 52px; height: 52px;
width: 62px; height: 62px;
border-radius: 14px;
display: flex; align-items: center; justify-content: center;
font-size: 1.7rem;
font-size: 2.04rem;
color: #fff;
margin-bottom: .2rem;
}
@@ -513,7 +513,20 @@ unset($p);
badge.style.background = prioColor;
mostrar('screen-datos');
document.getElementById('inp-cedula').focus();
const inpCedula = document.getElementById('inp-cedula');
inpCedula.focus();
inpCedula.value = '';
// Detector de scanner: cuando se pega/escribe rápido una cédula válida
let _timerAutoSubmit = null;
inpCedula.addEventListener('input', () => {
clearTimeout(_timerAutoSubmit);
const val = inpCedula.value.trim();
if (/^\d{5,15}$/.test(val)) {
// Cédula válida: auto-submit en 300ms (tiempo para que termine el scanner)
_timerAutoSubmit = setTimeout(() => confirmarTurno(), 300);
}
}, { once: false });
}
function volverPrioridades() { mostrar('screen-prio'); }
+8 -1
View File
@@ -881,7 +881,14 @@ function desvincularPaciente() {
}
function abrirNuevoPaciente(nombre) {
window.open('<?= BASE_URL ?>lab_pacientes.php?nuevo=1&nombre=' + encodeURIComponent(nombre), '_blank');
const ventana = window.open('<?= BASE_URL ?>lab_pacientes.php?nuevo=1&nombre=' + encodeURIComponent(nombre), '_blank');
// Detectar cuando se cierra la ventana y refrescar la búsqueda
const chequeo = setInterval(() => {
if (ventana.closed) {
clearInterval(chequeo);
setTimeout(() => buscarPaciente(), 500); // Buscar nuevamente después de cerrar
}
}, 500);
}
// ── Historial del paciente ──────────────────────────────────────