feat(lugar): botón quitar consentimiento con motivo obligatorio y auditoría
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* modules/turnero/api/quitar_consentimiento.php
|
||||||
|
* POST {consent_id, motivo} → elimina un consentimiento con auditoría
|
||||||
|
*/
|
||||||
|
require_once __DIR__ . '/_helpers.php';
|
||||||
|
require_once __DIR__ . '/../../../classes/lab/ActividadAdmin.php';
|
||||||
|
|
||||||
|
requireTurnero();
|
||||||
|
requireMethod('POST');
|
||||||
|
|
||||||
|
$input = inputJson();
|
||||||
|
$consentId = (int)($input['consent_id'] ?? 0);
|
||||||
|
$motivo = trim($input['motivo'] ?? '');
|
||||||
|
|
||||||
|
if (!$consentId) jsonError('consent_id requerido');
|
||||||
|
if ($motivo === '') jsonError('Debe ingresar un motivo para quitar el consentimiento');
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Leer datos antes de borrar (para el log)
|
||||||
|
$row = $pdo->prepare(
|
||||||
|
"SELECT tc.id, tc.turno_id, tc.formulario_id, tc.estado,
|
||||||
|
lf.nombre AS formulario_nombre,
|
||||||
|
t.codigo AS turno_codigo
|
||||||
|
FROM turnero_consentimientos tc
|
||||||
|
JOIN lab_formularios lf ON lf.id = tc.formulario_id
|
||||||
|
JOIN turnero_turnos t ON t.id = tc.turno_id
|
||||||
|
WHERE tc.id = ? LIMIT 1"
|
||||||
|
);
|
||||||
|
$row->execute([$consentId]);
|
||||||
|
$consent = $row->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$consent) jsonError('Consentimiento no encontrado', 404);
|
||||||
|
|
||||||
|
$pdo->prepare('DELETE FROM turnero_consentimientos WHERE id = ?')->execute([$consentId]);
|
||||||
|
|
||||||
|
(new ActividadAdmin())->registrar(
|
||||||
|
adminId(),
|
||||||
|
'turnero_config',
|
||||||
|
'quitar_consentimiento',
|
||||||
|
$consentId,
|
||||||
|
[
|
||||||
|
'turno_codigo' => $consent['turno_codigo'],
|
||||||
|
'turno_id' => $consent['turno_id'],
|
||||||
|
'formulario_id' => $consent['formulario_id'],
|
||||||
|
'formulario_nombre' => $consent['formulario_nombre'],
|
||||||
|
'estado_previo' => $consent['estado'],
|
||||||
|
'motivo' => $motivo,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
jsonOk([], 'Consentimiento quitado');
|
||||||
@@ -843,6 +843,40 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Modal: quitar consentimiento ───────────────────────────── -->
|
||||||
|
<div id="modal-quitar-consent" style="
|
||||||
|
display:none;position:fixed;inset:0;z-index:9100;
|
||||||
|
background:rgba(0,0,0,.55);align-items:center;justify-content:center;padding:16px">
|
||||||
|
<div style="background:#fff;border-radius:14px;box-shadow:0 8px 40px rgba(0,0,0,.25);
|
||||||
|
width:min(96vw,480px);padding:24px;display:flex;flex-direction:column;gap:14px">
|
||||||
|
<div style="font-weight:700;font-size:.95rem;color:#1e293b">
|
||||||
|
<i class="fas fa-trash me-2 text-danger"></i>Quitar consentimiento
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.85rem;color:#475569">
|
||||||
|
<strong id="mqc-nombre"></strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label style="font-size:.82rem;font-weight:600;color:#374151;display:block;margin-bottom:4px">
|
||||||
|
Motivo <span style="color:#dc2626">*</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="mqc-motivo" rows="3" placeholder="Explique por qué se quita este consentimiento…"
|
||||||
|
style="width:100%;border:1px solid #d1d5db;border-radius:8px;padding:8px 10px;
|
||||||
|
font-size:.85rem;resize:vertical;font-family:inherit"></textarea>
|
||||||
|
<div id="mqc-error" style="color:#dc2626;font-size:.78rem;margin-top:4px;display:none"></div>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;gap:8px;justify-content:flex-end">
|
||||||
|
<button onclick="_cerrarModalQuitarConsent()"
|
||||||
|
style="padding:7px 18px;border:1px solid #d1d5db;border-radius:8px;
|
||||||
|
background:#fff;cursor:pointer;font-size:.85rem">Cancelar</button>
|
||||||
|
<button id="mqc-btn-confirmar" onclick="_confirmarQuitarConsent()"
|
||||||
|
style="padding:7px 18px;border:none;border-radius:8px;
|
||||||
|
background:#dc2626;color:#fff;cursor:pointer;font-weight:600;font-size:.85rem">
|
||||||
|
<i class="fas fa-trash me-1"></i>Quitar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ── Modal de consentimiento embebido (modo embebido) ────────── -->
|
<!-- ── Modal de consentimiento embebido (modo embebido) ────────── -->
|
||||||
<div id="modal-consentimiento" style="
|
<div id="modal-consentimiento" style="
|
||||||
display:none;position:fixed;inset:0;z-index:9000;
|
display:none;position:fixed;inset:0;z-index:9000;
|
||||||
@@ -1476,17 +1510,60 @@ function renderConsentimientos(lista) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const btnQuitar = `<button class="btn btn-outline-danger" title="Quitar consentimiento"
|
||||||
|
onclick="_abrirModalQuitarConsent(${idJs}, ${nomJs.replace(/"/g,'"')})">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>`;
|
||||||
|
|
||||||
return `<div class="consent-row ${c.estado}" data-consent-id="${c.id}">
|
return `<div class="consent-row ${c.estado}" data-consent-id="${c.id}">
|
||||||
<i class="fas ${ico}"></i>
|
<i class="fas ${ico}"></i>
|
||||||
<span class="nom-form">${escHtml(c.formulario_nombre || 'Consentimiento')}</span>
|
<span class="nom-form">${escHtml(c.formulario_nombre || 'Consentimiento')}</span>
|
||||||
${progresoBadge}
|
${progresoBadge}
|
||||||
${countdownEl}
|
${countdownEl}
|
||||||
<span class="c-badge">${label}</span>
|
<span class="c-badge">${label}</span>
|
||||||
<div class="acciones-consent">${btnAccion}${btnVer}</div>
|
<div class="acciones-consent">${btnAccion}${btnVer}${btnQuitar}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Quitar consentimiento ─────────────────────────────────────
|
||||||
|
let _mqcConsentId = null;
|
||||||
|
function _abrirModalQuitarConsent(consentId, formNombre) {
|
||||||
|
_mqcConsentId = consentId;
|
||||||
|
document.getElementById('mqc-nombre').textContent = formNombre;
|
||||||
|
document.getElementById('mqc-motivo').value = '';
|
||||||
|
document.getElementById('mqc-error').style.display = 'none';
|
||||||
|
document.getElementById('modal-quitar-consent').style.display = 'flex';
|
||||||
|
setTimeout(() => document.getElementById('mqc-motivo').focus(), 50);
|
||||||
|
}
|
||||||
|
function _cerrarModalQuitarConsent() {
|
||||||
|
document.getElementById('modal-quitar-consent').style.display = 'none';
|
||||||
|
_mqcConsentId = null;
|
||||||
|
}
|
||||||
|
async function _confirmarQuitarConsent() {
|
||||||
|
const motivo = document.getElementById('mqc-motivo').value.trim();
|
||||||
|
const errEl = document.getElementById('mqc-error');
|
||||||
|
if (!motivo) { errEl.textContent = 'El motivo es obligatorio.'; errEl.style.display = ''; return; }
|
||||||
|
const btn = document.getElementById('mqc-btn-confirmar');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Quitando…';
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API}quitar_consentimiento.php`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type':'application/json'},
|
||||||
|
body: JSON.stringify({consent_id: _mqcConsentId, motivo})
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
if (!json.ok) { errEl.textContent = json.error || 'Error al quitar.'; errEl.style.display = ''; }
|
||||||
|
else {
|
||||||
|
_cerrarModalQuitarConsent();
|
||||||
|
if (turnoActivo?.id) actualizarConsentimientos(turnoActivo.id);
|
||||||
|
}
|
||||||
|
} catch(e) { errEl.textContent = 'Error de red.'; errEl.style.display = ''; }
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.innerHTML = '<i class="fas fa-trash me-1"></i>Quitar';
|
||||||
|
}
|
||||||
|
|
||||||
async function actualizarConsentimientos(turnoId) {
|
async function actualizarConsentimientos(turnoId) {
|
||||||
if (!turnoId) return;
|
if (!turnoId) return;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user