333 lines
17 KiB
PHP
333 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_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>
|
|
</body>
|
|
</html>
|