Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0189a61eb | ||
|
|
27135e4d2f |
@@ -322,16 +322,12 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Sección: Consentimientos ── -->
|
<!-- ── Sección: Consentimientos ── -->
|
||||||
<!-- ── Formulario embebido (modo=embebido) ── -->
|
<!-- ── Botón firma embebida (modo=embebido) ── -->
|
||||||
<div class="ficha-sec d-none" id="sec-form-embebido">
|
<div class="ficha-sec d-none" id="sec-form-embebido">
|
||||||
<h6><i class="fas fa-file-alt me-1"></i>Formulario de consentimiento</h6>
|
<h6><i class="fas fa-file-signature me-1"></i>Consentimiento informado</h6>
|
||||||
<div id="form-embebido-loading" class="text-muted small py-2">
|
<button class="btn btn-primary w-100" onclick="abrirModalConsentimiento()">
|
||||||
<i class="fas fa-spinner fa-spin me-1"></i>Cargando formulario...
|
<i class="fas fa-pen me-2"></i>Abrir formulario de firma
|
||||||
</div>
|
</button>
|
||||||
<iframe id="form-embebido-iframe" src="" frameborder="0"
|
|
||||||
style="width:100%;min-height:520px;border-radius:8px;border:1px solid #e2e8f0;display:none"
|
|
||||||
onload="this.style.display='block';document.getElementById('form-embebido-loading').style.display='none'">
|
|
||||||
</iframe>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ficha-sec" id="sec-consent">
|
<div class="ficha-sec" id="sec-consent">
|
||||||
@@ -393,6 +389,38 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
|||||||
</div><!-- /lugar-layout -->
|
</div><!-- /lugar-layout -->
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- ── Modal de consentimiento embebido ──────────────────────── -->
|
||||||
|
<div id="modal-consentimiento" style="
|
||||||
|
display:none;position:fixed;inset:0;z-index:9000;
|
||||||
|
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,680px);max-height:92vh;
|
||||||
|
display:flex;flex-direction:column;overflow:hidden">
|
||||||
|
<!-- Header modal -->
|
||||||
|
<div style="
|
||||||
|
display:flex;align-items:center;justify-content:space-between;
|
||||||
|
padding:12px 18px;border-bottom:1px solid #e2e8f0;flex-shrink:0">
|
||||||
|
<span style="font-weight:700;font-size:.95rem;color:#1e293b">
|
||||||
|
<i class="fas fa-file-signature me-2 text-primary"></i>Formulario de consentimiento
|
||||||
|
</span>
|
||||||
|
<button onclick="cerrarModalConsentimiento()"
|
||||||
|
style="background:none;border:none;font-size:1.2rem;color:#94a3b8;cursor:pointer;padding:2px 6px">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<!-- Loading -->
|
||||||
|
<div id="modal-consent-loading" style="padding:32px;text-align:center;color:#64748b;flex-shrink:0">
|
||||||
|
<i class="fas fa-spinner fa-spin fa-2x mb-2 d-block"></i>Cargando formulario…
|
||||||
|
</div>
|
||||||
|
<!-- Iframe -->
|
||||||
|
<iframe id="modal-consent-iframe" src="" frameborder="0"
|
||||||
|
style="flex:1;border:none;display:none;min-height:60vh"
|
||||||
|
onload="document.getElementById('modal-consent-loading').style.display='none';this.style.display='block'">
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// ── Estado global ─────────────────────────────────────────────
|
// ── Estado global ─────────────────────────────────────────────
|
||||||
@@ -858,41 +886,83 @@ async function cambiarEstadoTurno(nuevoEstado) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Reset ─────────────────────────────────────────────────────
|
// ── Embebido como modal ───────────────────────────────────────
|
||||||
|
let _consentTokenCache = null; // { turnoId, token }
|
||||||
|
|
||||||
async function cargarFormEmbebido(turnoId) {
|
async function cargarFormEmbebido(turnoId) {
|
||||||
const sec = document.getElementById('sec-form-embebido');
|
const sec = document.getElementById('sec-form-embebido');
|
||||||
const iframe = document.getElementById('form-embebido-iframe');
|
if (sec) sec.classList.remove('d-none');
|
||||||
const load = document.getElementById('form-embebido-loading');
|
// Pre-cargar token para que el modal abra rápido
|
||||||
if (!sec || !iframe) return;
|
|
||||||
sec.classList.remove('d-none');
|
|
||||||
iframe.style.display = 'none';
|
|
||||||
load.style.display = '';
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API}get_consent_token.php?turno_id=${turnoId}&lugar_id=${lugarId}`);
|
const res = await fetch(`${API}get_consent_token.php?turno_id=${turnoId}&lugar_id=${lugarId}`);
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (json.ok && json.token) {
|
if (json.ok && json.token) {
|
||||||
iframe.src = `${BASE_WA}ver_formulario_enviado.php?token=${encodeURIComponent(json.token)}`;
|
_consentTokenCache = { turnoId, token: json.token };
|
||||||
} else {
|
} else {
|
||||||
load.innerHTML = '<span class="text-danger small"><i class="fas fa-exclamation-triangle me-1"></i>' + (json.error || 'No hay formulario configurado') + '</span>';
|
_consentTokenCache = null;
|
||||||
|
if (sec) sec.innerHTML = `<h6><i class="fas fa-file-signature me-1"></i>Consentimiento informado</h6>
|
||||||
|
<div class="text-danger small"><i class="fas fa-exclamation-triangle me-1"></i>${json.error || 'Sin formulario configurado'}</div>`;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
load.innerHTML = '<span class="text-danger small"><i class="fas fa-exclamation-triangle me-1"></i>Error al cargar formulario</span>';
|
_consentTokenCache = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function abrirModalConsentimiento() {
|
||||||
|
if (!_consentTokenCache) { mostrarError('Token de consentimiento no disponible.'); return; }
|
||||||
|
const modal = document.getElementById('modal-consentimiento');
|
||||||
|
const iframe = document.getElementById('modal-consent-iframe');
|
||||||
|
const load = document.getElementById('modal-consent-loading');
|
||||||
|
iframe.style.display = 'none';
|
||||||
|
iframe.src = '';
|
||||||
|
load.style.display = '';
|
||||||
|
modal.style.display = 'flex';
|
||||||
|
// Pequeño delay para que el modal sea visible antes de cargar el iframe
|
||||||
|
setTimeout(() => {
|
||||||
|
iframe.src = `${BASE_WA}ver_formulario_enviado.php?token=${encodeURIComponent(_consentTokenCache.token)}&embed=1`;
|
||||||
|
}, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cerrarModalConsentimiento() {
|
||||||
|
const modal = document.getElementById('modal-consentimiento');
|
||||||
|
const iframe = document.getElementById('modal-consent-iframe');
|
||||||
|
modal.style.display = 'none';
|
||||||
|
iframe.src = '';
|
||||||
|
iframe.style.display = 'none';
|
||||||
|
document.getElementById('modal-consent-loading').style.display = '';
|
||||||
|
// Refrescar estado del consentimiento
|
||||||
|
if (turnoActivo) actualizarConsentimientos(turnoActivo.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cerrar modal si se firma desde el iframe
|
||||||
|
window.addEventListener('message', function(e) {
|
||||||
|
if (e.data && e.data.type === 'turneroFirmado') {
|
||||||
|
cerrarModalConsentimiento();
|
||||||
|
mostrarToast('Consentimiento firmado ✓', 'success', 3000);
|
||||||
|
if (turnoActivo) actualizarConsentimientos(turnoActivo.id);
|
||||||
|
// Ocultar botón de firma
|
||||||
|
const sec = document.getElementById('sec-form-embebido');
|
||||||
|
if (sec) sec.classList.add('d-none');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function resetFicha() {
|
function resetFicha() {
|
||||||
clearInterval(pollingConsentId);
|
clearInterval(pollingConsentId);
|
||||||
turnoActivo = null;
|
turnoActivo = null;
|
||||||
tieneConsent = false;
|
tieneConsent = false;
|
||||||
hayPendientes = false;
|
hayPendientes = false;
|
||||||
|
_consentTokenCache = null;
|
||||||
|
|
||||||
// Limpiar iframe embebido
|
// Limpiar modal embebido
|
||||||
const iframe = document.getElementById('form-embebido-iframe');
|
cerrarModalConsentimiento();
|
||||||
const sec = document.getElementById('sec-form-embebido');
|
const sec = document.getElementById('sec-form-embebido');
|
||||||
const load = document.getElementById('form-embebido-loading');
|
if (sec) {
|
||||||
if (iframe) { iframe.src = ''; iframe.style.display = 'none'; }
|
sec.classList.add('d-none');
|
||||||
if (sec) { sec.classList.add('d-none'); }
|
sec.innerHTML = `<h6><i class="fas fa-file-signature me-1"></i>Consentimiento informado</h6>
|
||||||
if (load) { load.style.display = ''; load.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Cargando formulario...'; }
|
<button class="btn btn-primary w-100" onclick="abrirModalConsentimiento()">
|
||||||
|
<i class="fas fa-pen me-2"></i>Abrir formulario de firma
|
||||||
|
</button>`;
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('ficha-turno').classList.add('d-none');
|
document.getElementById('ficha-turno').classList.add('d-none');
|
||||||
document.getElementById('ficha-placeholder').classList.remove('d-none');
|
document.getElementById('ficha-placeholder').classList.remove('d-none');
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ $datosCliente = json_decode($envio['datos_cliente'] ?? '{}', true) ?? [];
|
|||||||
$datosPrefilled = json_decode($envio['datos_prefilled'] ?? '{}', true) ?? [];
|
$datosPrefilled = json_decode($envio['datos_prefilled'] ?? '{}', true) ?? [];
|
||||||
$todos = array_merge($datosPrefilled, $datosCliente);
|
$todos = array_merge($datosPrefilled, $datosCliente);
|
||||||
$modoEditar = $modoTurnero && $envio['estado'] !== 'firmado';
|
$modoEditar = $modoTurnero && $envio['estado'] !== 'firmado';
|
||||||
|
$embebido = isset($_GET['embed']) && $_GET['embed'] === '1';
|
||||||
|
|
||||||
// Mapa id → label
|
// Mapa id → label
|
||||||
$labelMap = [];
|
$labelMap = [];
|
||||||
@@ -298,6 +299,31 @@ function esc2(mixed $v): string {
|
|||||||
.hash-seal-header { background: #000 !important; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
|
.hash-seal-header { background: #000 !important; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<?php if ($embebido): ?>
|
||||||
|
/* ── Modo embebido (iframe) ── */
|
||||||
|
body { background: #fff; font-size: 12px; }
|
||||||
|
.action-bar { display: none !important; }
|
||||||
|
.doc-wrap { margin: 0; border-radius: 0; box-shadow: none; max-width: 100%; }
|
||||||
|
.doc-header { padding: 10px 14px 8px; }
|
||||||
|
.doc-header-text h3 { font-size: 14px; }
|
||||||
|
.doc-header-text h4 { font-size: 12px; }
|
||||||
|
.doc-body { padding: 12px 14px; }
|
||||||
|
.doc-footer { display: none; }
|
||||||
|
.section-title { font-size: 10px; margin: 14px 0 8px; }
|
||||||
|
.campo-label { font-size: 11px; }
|
||||||
|
.campo-valor { font-size: 12px; }
|
||||||
|
.campo-edit { margin-bottom: 8px; }
|
||||||
|
.campo-edit label { font-size: 11px; margin-bottom: 2px; }
|
||||||
|
.campo-edit .form-control,
|
||||||
|
.campo-edit .form-select { font-size: 12px; padding: 3px 7px; }
|
||||||
|
.campo-edit .form-check-label { font-size: 12px; }
|
||||||
|
.campo-row { padding: 3px 0; }
|
||||||
|
.turnero-cv { height: 110px !important; }
|
||||||
|
.btn { font-size: 12px; padding: 3px 10px; }
|
||||||
|
.hash-seal { display: none; }
|
||||||
|
.alert { font-size: 12px; padding: 6px 10px; }
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
/* ── Canvas firma profesional ───────────────────── */
|
/* ── Canvas firma profesional ───────────────────── */
|
||||||
.firma-pro-widget { max-width: 520px; margin-top: 8px; }
|
.firma-pro-widget { max-width: 520px; margin-top: 8px; }
|
||||||
.fpw-canvas { border: 2px solid #198754; border-radius: 8px; background: #f8fff9;
|
.fpw-canvas { border: 2px solid #198754; border-radius: 8px; background: #f8fff9;
|
||||||
@@ -470,6 +496,11 @@ function esc2(mixed $v): string {
|
|||||||
if (!$cid) continue;
|
if (!$cid) continue;
|
||||||
$isPro = ($tipo === 'firma_profesional');
|
$isPro = ($tipo === 'firma_profesional');
|
||||||
|
|
||||||
|
// Marcar siempre que el esquema tiene campo firma paciente
|
||||||
|
if (!$isPro) {
|
||||||
|
$_esquemaTieneFirmaPaciente = true;
|
||||||
|
}
|
||||||
|
|
||||||
// La firma profesional global solo se muestra en el PRIMER campo firma_profesional.
|
// La firma profesional global solo se muestra en el PRIMER campo firma_profesional.
|
||||||
// Campos posteriores (ej. desistimiento) solo muestran su propia firma por campo.
|
// Campos posteriores (ej. desistimiento) solo muestran su propia firma por campo.
|
||||||
$fSvg = $isPro
|
$fSvg = $isPro
|
||||||
@@ -481,12 +512,10 @@ function esc2(mixed $v): string {
|
|||||||
$fLabel = htmlspecialchars($campo['label'] ?? ($isPro ? 'Firma profesional' : 'Firma paciente'));
|
$fLabel = htmlspecialchars($campo['label'] ?? ($isPro ? 'Firma profesional' : 'Firma paciente'));
|
||||||
|
|
||||||
// Campo paciente sin firma:
|
// Campo paciente sin firma:
|
||||||
// - En turnero pendiente: todos los campos firma muestran canvas (consentimiento + desistimiento).
|
// - En turnero pendiente: todos los campos firma muestran canvas.
|
||||||
// - En vista normal: omitir campos sin firma.
|
// - En vista normal: omitir campos sin firma.
|
||||||
if (!$fSvg && !$fFoto && !$isPro) {
|
if (!$fSvg && !$fFoto && !$isPro) {
|
||||||
if ($modoTurnero && $modoEditar) {
|
if (!($modoTurnero && $modoEditar)) {
|
||||||
$_esquemaTieneFirmaPaciente = true;
|
|
||||||
} else {
|
|
||||||
continue; // no-turnero: omitir campos sin firma
|
continue; // no-turnero: omitir campos sin firma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,7 +627,7 @@ function esc2(mixed $v): string {
|
|||||||
</div>
|
</div>
|
||||||
<?php continue; endif;
|
<?php continue; endif;
|
||||||
if ($tipo === 'radio'):
|
if ($tipo === 'radio'):
|
||||||
$opts = $campo['opciones'] ?? [];
|
$opts = $campo['opciones'] ?? $campo['options'] ?? [];
|
||||||
?>
|
?>
|
||||||
<div class="campo-edit">
|
<div class="campo-edit">
|
||||||
<label><?= $label ?></label>
|
<label><?= $label ?></label>
|
||||||
@@ -613,7 +642,7 @@ function esc2(mixed $v): string {
|
|||||||
</div>
|
</div>
|
||||||
<?php continue; endif;
|
<?php continue; endif;
|
||||||
if ($tipo === 'checkbox' || $tipo === 'lista_marcable'):
|
if ($tipo === 'checkbox' || $tipo === 'lista_marcable'):
|
||||||
$opts = $campo['opciones'] ?? [];
|
$opts = $campo['opciones'] ?? $campo['options'] ?? $campo['items'] ?? [];
|
||||||
$checkedArr = is_array($prefill) ? $prefill
|
$checkedArr = is_array($prefill) ? $prefill
|
||||||
: (is_string($prefill) && $prefill !== '' ? (json_decode($prefill, true) ?: [$prefill]) : []);
|
: (is_string($prefill) && $prefill !== '' ? (json_decode($prefill, true) ?: [$prefill]) : []);
|
||||||
?>
|
?>
|
||||||
@@ -630,7 +659,7 @@ function esc2(mixed $v): string {
|
|||||||
</div>
|
</div>
|
||||||
<?php continue; endif;
|
<?php continue; endif;
|
||||||
if ($tipo === 'select'):
|
if ($tipo === 'select'):
|
||||||
$opts = $campo['opciones'] ?? [];
|
$opts = $campo['opciones'] ?? $campo['options'] ?? [];
|
||||||
?>
|
?>
|
||||||
<div class="campo-edit">
|
<div class="campo-edit">
|
||||||
<label><?= $label ?></label>
|
<label><?= $label ?></label>
|
||||||
|
|||||||
Reference in New Issue
Block a user