Files
whatsapp/lab_configuracion.php
T
2026-04-08 09:02:32 -05:00

335 lines
17 KiB
PHP

<?php
/**
* lab_configuracion.php — Configuración global del laboratorio
* Solo admin.
*/
require_once 'config/config.php';
if (!isUserLoggedIn()) { header('Location: login.php'); exit; }
if (isEnfermero()) { header('Location: lab_dashboard.php'); exit; }
$adminNombre = $_SESSION['admin_user']['full_name'] ?? 'Admin';
// Cargar config actual
$db = Database::getInstance();
$rows= $db->fetchAll('SELECT clave, valor FROM lab_config ORDER BY clave');
$cfg = [];
foreach ($rows as $r) { $cfg[$r['clave']] = $r['valor']; }
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configuración Lab</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="./assets/css/styles.css?v=12" rel="stylesheet">
<style>
.preview-header {
border-radius: 10px; color: #fff;
padding: 20px 24px; margin-top: 16px;
}
.preview-header h4 { margin: 0 0 2px; font-size: 15px; font-weight: 700; }
.preview-header .sub { font-size: 12px; opacity: .8; }
.preview-logo { max-height: 60px; max-width: 100px;
border-radius: 6px; background: rgba(255,255,255,.2); padding: 3px; }
.section-card { border-radius: 10px; border: 1px solid #dee2e6;
background: #fff; padding: 20px 24px; margin-bottom: 20px; }
.section-card h6 { border-bottom: 2px solid #0d6efd; padding-bottom: 8px;
margin-bottom: 16px; font-weight: 700; color: #1565c0; }
</style>
</head>
<body>
<nav class="sidebar">
<div class="sidebar-header"><h4><i class="fas fa-flask"></i> Módulo Lab</h4></div>
<ul class="sidebar-menu">
<li><a href="lab_dashboard.php" class="nav-link"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
<li><a href="lab_ordenes.php" class="nav-link"><i class="fas fa-file-medical"></i> Órdenes</a></li>
<li><a href="lab_pacientes.php" class="nav-link"><i class="fas fa-users"></i> Pacientes</a></li>
<li><a href="lab_domicilios.php" class="nav-link"><i class="fas fa-house-medical"></i> Domicilios</a></li>
<li><a href="lab_enfermeras.php" class="nav-link"><i class="fas fa-user-nurse"></i> Enfermeras</a></li>
<li><a href="lab_formularios.php" class="nav-link"><i class="fas fa-wpforms"></i> Formularios</a></li>
<li><a href="lab_reportes.php" class="nav-link"><i class="fas fa-chart-bar"></i> Reportes</a></li>
<li><a href="lab_actividad.php" class="nav-link"><i class="fas fa-history"></i> Actividad</a></li>
<li><a href="lab_configuracion.php" class="nav-link active"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li class="sidebar-divider"></li>
<li><a href="index.php" class="nav-link"><i class="fas fa-arrow-left"></i> Volver al Bot</a></li>
<li><a href="logout.php" class="nav-link" onclick="return confirm('¿Cerrar sesión?')"><i class="fas fa-sign-out-alt"></i> Cerrar Sesión</a></li>
</ul>
</nav>
<main class="main-content">
<header class="content-header d-flex align-items-center justify-content-between">
<div>
<h1><i class="fas fa-sliders-h text-primary"></i> Configuración del Laboratorio</h1>
<small class="text-muted">Personaliza el encabezado, logo y datos que aparecen en los documentos PDF</small>
</div>
</header>
<div class="container-fluid py-3" style="max-width:860px">
<div id="toast-ok" class="alert alert-success" style="display:none;position:fixed;top:70px;right:20px;z-index:9999;min-width:260px">
<i class="fas fa-check-circle me-2"></i>Configuración guardada correctamente
</div>
<div class="row g-3">
<div class="col-lg-7">
<!-- ── Datos de la empresa ─────────────────────────── -->
<div class="section-card">
<h6><i class="fas fa-building me-1"></i>Datos de la empresa / laboratorio</h6>
<div class="mb-3">
<label class="form-label fw-semibold small">Nombre del laboratorio <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="c-empresa-nombre"
value="<?= htmlspecialchars($cfg['empresa_nombre'] ?? '') ?>"
placeholder="Ej: Laboratorio Clínico Ximena">
</div>
<div class="mb-3">
<label class="form-label fw-semibold small">Subtítulo</label>
<input type="text" class="form-control" id="c-empresa-subtitulo"
value="<?= htmlspecialchars($cfg['empresa_subtitulo'] ?? '') ?>"
placeholder="Ej: Análisis Clínicos Especializados">
</div>
<div class="row g-2 mb-3">
<div class="col-6">
<label class="form-label fw-semibold small">Teléfono</label>
<input type="text" class="form-control" id="c-empresa-telefono"
value="<?= htmlspecialchars($cfg['empresa_telefono'] ?? '') ?>"
placeholder="+57 300 000 0000">
</div>
<div class="col-6">
<label class="form-label fw-semibold small">Ciudad</label>
<input type="text" class="form-control" id="c-empresa-ciudad"
value="<?= htmlspecialchars($cfg['empresa_ciudad'] ?? '') ?>"
placeholder="Bogotá, Colombia">
</div>
</div>
<div class="row g-2 mb-3">
<div class="col-6">
<label class="form-label fw-semibold small">Email</label>
<input type="email" class="form-control" id="c-empresa-email"
value="<?= htmlspecialchars($cfg['empresa_email'] ?? '') ?>"
placeholder="info@laboratorio.com">
</div>
<div class="col-6">
<label class="form-label fw-semibold small">Dirección</label>
<input type="text" class="form-control" id="c-empresa-direccion"
value="<?= htmlspecialchars($cfg['empresa_direccion'] ?? '') ?>"
placeholder="Calle 10 #20-30">
</div>
</div>
</div>
<!-- ── Diseño del documento ────────────────────────── -->
<div class="section-card">
<h6><i class="fas fa-paint-brush me-1"></i>Diseño del encabezado del documento</h6>
<div class="row g-3 mb-3">
<div class="col-4">
<label class="form-label fw-semibold small">Color del encabezado</label>
<input type="color" class="form-control form-control-color w-100"
id="c-doc-color"
value="<?= htmlspecialchars($cfg['doc_color'] ?? '#1565c0') ?>"
oninput="actualizarPreview()">
</div>
<div class="col-8">
<label class="form-label fw-semibold small">Logo del laboratorio</label>
<input type="file" class="form-control form-control-sm" id="c-logo-file"
accept="image/png,image/jpeg,image/gif,image/svg+xml"
onchange="cargarLogo(this)">
<div class="form-text">PNG, JPG o SVG recomendado. Máx. 200px de alto.</div>
</div>
</div>
<?php if (!empty($cfg['doc_logo_base64'])): ?>
<div class="mb-3">
<label class="form-label small fw-semibold">Logo actual:</label>
<div class="d-flex align-items-center gap-3">
<img id="c-logo-preview" src="<?= htmlspecialchars($cfg['doc_logo_base64']) ?>"
alt="Logo" style="max-height:60px;border:1px solid #dee2e6;border-radius:6px;padding:4px">
<button class="btn btn-outline-danger btn-sm" onclick="quitarLogo()">
<i class="fas fa-trash me-1"></i>Quitar logo
</button>
</div>
</div>
<?php else: ?>
<div class="mb-3" id="logo-preview-wrap" style="display:none">
<label class="form-label small fw-semibold">Vista previa del logo:</label>
<div class="d-flex align-items-center gap-3">
<img id="c-logo-preview" src="" alt="Logo"
style="max-height:60px;border:1px solid #dee2e6;border-radius:6px;padding:4px">
<button class="btn btn-outline-danger btn-sm" onclick="quitarLogo()">
<i class="fas fa-trash me-1"></i>Quitar logo
</button>
</div>
</div>
<?php endif; ?>
<input type="hidden" id="c-logo-base64" value="<?= htmlspecialchars($cfg['doc_logo_base64'] ?? '') ?>">
<div class="mb-3">
<label class="form-label fw-semibold small">Pie de página del documento</label>
<input type="text" class="form-control" id="c-doc-pie"
value="<?= htmlspecialchars($cfg['doc_pie_pagina'] ?? '') ?>"
placeholder="Ej: Documento de uso confidencial. Prohibida su reproducción.">
</div>
</div>
<button class="btn btn-primary btn-lg w-100" onclick="guardar()">
<i class="fas fa-save me-2"></i>Guardar configuración
</button>
</div>
<!-- ── Vista previa ──────────────────────────────── -->
<div class="col-lg-5">
<div class="section-card" style="position:sticky;top:80px">
<h6><i class="fas fa-eye me-1"></i>Vista previa del encabezado</h6>
<div id="preview-box" class="preview-header"
style="background: <?= htmlspecialchars($cfg['doc_color'] ?? '#1565c0') ?>">
<div style="display:flex;align-items:flex-start;gap:12px">
<div id="preview-logo-wrap" style="display:<?= !empty($cfg['doc_logo_base64']) ? '' : 'none' ?>">
<img id="preview-logo" src="<?= htmlspecialchars($cfg['doc_logo_base64'] ?? '') ?>"
class="preview-logo" alt="Logo">
</div>
<div style="flex:1">
<h4 id="preview-nombre"><?= htmlspecialchars($cfg['empresa_nombre'] ?? 'Nombre del laboratorio') ?></h4>
<div class="sub" id="preview-subtitulo"><?= htmlspecialchars($cfg['empresa_subtitulo'] ?? 'Subtítulo') ?></div>
<div class="sub" style="margin-top:2px" id="preview-contacto">
<?php
$c = array_filter([
$cfg['empresa_direccion'] ?? '',
$cfg['empresa_ciudad'] ?? '',
$cfg['empresa_telefono'] ?? '',
]);
echo htmlspecialchars(implode(' · ', $c));
?>
</div>
<h5 style="margin:8px 0 0;border-top:1px solid rgba(255,255,255,.3);padding-top:8px;font-size:14px">
Nombre del formulario
</h5>
</div>
</div>
</div>
<div class="mt-3 p-3 bg-light rounded small text-muted">
<i class="fas fa-info-circle me-1"></i>
Este encabezado aparecerá en todos los documentos PDF generados.
Cada formulario puede tener su propio encabezado desde el editor de formularios.
</div>
<div class="mt-3">
<a href="ver_formulario_enviado.php?id=<?php
$uno = $db->fetch('SELECT id FROM lab_form_envios WHERE estado IN (\'firmado\',\'completado\') ORDER BY id DESC LIMIT 1');
echo $uno ? (int)$uno['id'] : '0';
?>" target="_blank" class="btn btn-outline-primary btn-sm w-100">
<i class="fas fa-external-link-alt me-1"></i>Ver ejemplo de documento
</a>
</div>
</div>
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const $ = id => document.getElementById(id);
function actualizarPreview() {
const color = $('c-doc-color').value;
const nombre = $('c-empresa-nombre').value || 'Nombre del laboratorio';
const sub = $('c-empresa-subtitulo').value || 'Subtítulo';
const tel = $('c-empresa-telefono').value;
const dir = $('c-empresa-direccion').value;
const ciudad = $('c-empresa-ciudad').value;
$('preview-box').style.background = color;
$('preview-nombre').textContent = nombre;
$('preview-subtitulo').textContent = sub;
const ctc = [dir, ciudad, tel].filter(Boolean).join(' · ');
$('preview-contacto').textContent = ctc;
}
// Actualizar preview al escribir
['c-empresa-nombre','c-empresa-subtitulo','c-empresa-telefono',
'c-empresa-direccion','c-empresa-ciudad'].forEach(id => {
$(id)?.addEventListener('input', actualizarPreview);
});
function cargarLogo(input) {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = e => {
const b64 = e.target.result;
$('c-logo-base64').value = b64;
$('c-logo-preview').src = b64;
$('preview-logo').src = b64;
const wrap = $('logo-preview-wrap') || $('c-logo-preview').parentElement;
if (wrap) wrap.style.display = '';
$('preview-logo-wrap').style.display = '';
};
reader.readAsDataURL(file);
}
function quitarLogo() {
$('c-logo-base64').value = '';
$('c-logo-preview').src = '';
$('preview-logo').src = '';
$('preview-logo-wrap').style.display = 'none';
const wrap = $('logo-preview-wrap');
if (wrap) wrap.style.display = 'none';
$('c-logo-file').value = '';
}
async function guardar() {
const payload = {
empresa_nombre: $('c-empresa-nombre').value.trim(),
empresa_subtitulo: $('c-empresa-subtitulo').value.trim(),
empresa_telefono: $('c-empresa-telefono').value.trim(),
empresa_email: $('c-empresa-email').value.trim(),
empresa_direccion: $('c-empresa-direccion').value.trim(),
empresa_ciudad: $('c-empresa-ciudad').value.trim(),
doc_color: $('c-doc-color').value,
doc_logo_base64: $('c-logo-base64').value,
doc_pie_pagina: $('c-doc-pie').value.trim(),
};
if (!payload.empresa_nombre) {
$('c-empresa-nombre').focus();
$('c-empresa-nombre').classList.add('is-invalid');
return;
}
const btn = document.querySelector('button[onclick="guardar()"]');
btn.disabled = true;
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Guardando…';
try {
const r = await fetch('api/lab/save_config.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const d = await r.json();
if (d.success) {
const t = $('toast-ok');
t.style.display = 'block';
setTimeout(() => { t.style.display = 'none'; }, 3500);
} else {
alert(d.error || 'Error al guardar');
}
} finally {
btn.disabled = false;
btn.innerHTML = '<i class="fas fa-save me-2"></i>Guardar configuración';
}
}
</script>
<script src="assets/js/lab-sidebar.js"></script>
</body>
</html>