From e89ec89c660351e0dc68ee4bffbbb8c72102def0 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 19 Mar 2026 11:43:01 -0500 Subject: [PATCH] =?UTF-8?q?lab:=20responsive=20sidebar=20toggle=20en=20tod?= =?UTF-8?q?as=20las=20p=C3=A1ginas=20del=20m=C3=B3dulo=20lab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/css/styles.css | 48 +++++++++++++++++++++++ assets/js/lab-sidebar.js | 78 ++++++++++++++++++++++++++++++++++++++ lab_configuracion.php | 1 + lab_dashboard.php | 1 + lab_domicilios.php | 1 + lab_enfermeras.php | 1 + lab_formulario_builder.php | 1 + lab_formularios.php | 1 + lab_ordenes.php | 1 + lab_pacientes.php | 1 + lab_reportes.php | 1 + lab_terminos.php | 1 + lab_usuarios.php | 1 + 13 files changed, 137 insertions(+) create mode 100644 assets/js/lab-sidebar.js diff --git a/assets/css/styles.css b/assets/css/styles.css index a4480ab..c2fb113 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -991,6 +991,54 @@ body { } } +/* ================================= + LAB SIDEBAR TOGGLE (mobile) + ================================= */ + +/* El botón hamburguesa solo es visible en mobile/tablet */ +.lab-sidebar-toggle { + display: none !important; + flex-shrink: 0; + margin-right: 8px; +} + +/* content-header cuando tiene el toggle: evitar desbordamiento del título */ +.content-header.has-sidebar-toggle { + gap: 8px; + flex-wrap: nowrap; +} +.content-header.has-sidebar-toggle > div:nth-child(2) { + min-width: 0; + flex: 1; +} +.content-header.has-sidebar-toggle h1 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + font-size: clamp(.9rem, 2.5vw, 1.4rem); +} + +@media (max-width: 991.98px) { + .lab-sidebar-toggle { display: inline-flex !important; } + .content-header.has-sidebar-toggle { padding: 10px 12px; } + /* Evitar que el body haga scroll horizontal cuando el sidebar está abierto */ + body.sidebar-open { overflow: hidden; } + /* Contenedores con padding excesivo en móvil */ + .container-fluid { padding-left: 10px !important; padding-right: 10px !important; } +} + +@media (max-width: 575.98px) { + /* Cards de lab en 2 columnas en móvil pequeño */ + .col-md-3, .col-xl-3, .col-lg-3 { flex: 0 0 50%; max-width: 50%; } + /* Tablas lab: texto más pequeño */ + .table th, .table td { font-size: .78rem; padding: 7px 8px; } + /* Header sub-info en móvil */ + .content-header small { font-size: .7rem; } + /* Botón Nuevo en header: ocultar texto, solo icono */ + .content-header .btn-primary .me-1 ~ * { display: none; } +} + /* ================================= CHAT STYLES ================================= */ diff --git a/assets/js/lab-sidebar.js b/assets/js/lab-sidebar.js new file mode 100644 index 0000000..6a3fce2 --- /dev/null +++ b/assets/js/lab-sidebar.js @@ -0,0 +1,78 @@ +/** + * lab-sidebar.js — Toggle responsivo del sidebar para todas las páginas del Módulo Lab. + * Se auto-inyecta en el header y maneja el overlay. + */ +(function () { + 'use strict'; + + // ── 1. Overlay ────────────────────────────────────────────────────────── + var overlay = document.createElement('div'); + overlay.className = 'sidebar-overlay'; + document.body.appendChild(overlay); + + // ── 2. Botón hamburguesa ──────────────────────────────────────────────── + var btn = document.createElement('button'); + btn.id = 'sidebar-toggle'; + btn.className = 'btn btn-light btn-sm lab-sidebar-toggle'; + btn.title = 'Abrir menú'; + btn.innerHTML = ''; + + // Inyectar como primer hijo del content-header + var header = document.querySelector('.content-header'); + if (header) { + header.insertBefore(btn, header.firstChild); + header.classList.add('has-sidebar-toggle'); + } + + // ── 3. Toggle logic ────────────────────────────────────────────────────── + var sidebar = document.querySelector('.sidebar'); + + function openSidebar() { + if (!sidebar) return; + sidebar.classList.add('open'); + overlay.style.display = 'block'; + document.body.classList.add('sidebar-open'); + } + + function closeSidebar() { + if (!sidebar) return; + sidebar.classList.remove('open'); + overlay.style.display = 'none'; + document.body.classList.remove('sidebar-open'); + } + + btn.addEventListener('click', function (e) { + e.stopPropagation(); + if (sidebar && sidebar.classList.contains('open')) { + closeSidebar(); + } else { + openSidebar(); + } + }); + + // Cerrar al hacer clic en el overlay + overlay.addEventListener('click', closeSidebar); + + // Cerrar con Escape + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape') closeSidebar(); + }); + + // Cerrar al navegar (móvil: clic en enlace del sidebar) + if (sidebar) { + sidebar.querySelectorAll('.nav-link').forEach(function (link) { + link.addEventListener('click', function () { + if (window.innerWidth < 992) closeSidebar(); + }); + }); + } + + // ── 4. Visibility control ──────────────────────────────────────────────── + // El CSS ya maneja display vía media queries; solo necesitamos que el botón + // sea display:none en desktop y visible en mobile. Lo hacemos por CSS inline + // inicial y dejamos que styles.css lo maneje vía #sidebar-toggle. + // Aplicamos clase específica para que el CSS pueda targetarla: + // .lab-sidebar-toggle { display: none } en >=992px lo hace styles.css + // via #sidebar-toggle { display: none !important } + +})(); diff --git a/lab_configuracion.php b/lab_configuracion.php index e3befb5..ab4e0b4 100644 --- a/lab_configuracion.php +++ b/lab_configuracion.php @@ -328,5 +328,6 @@ async function guardar() { } } + diff --git a/lab_dashboard.php b/lab_dashboard.php index ef9390f..796d895 100644 --- a/lab_dashboard.php +++ b/lab_dashboard.php @@ -306,5 +306,6 @@ const formatFecha = s => s ? new Date(s).toLocaleString('es-CO', {day:'2-digit', cargarStats(); setInterval(cargarStats, 60000); + diff --git a/lab_domicilios.php b/lab_domicilios.php index cff24af..01f6841 100644 --- a/lab_domicilios.php +++ b/lab_domicilios.php @@ -1155,5 +1155,6 @@ function verRespuestaFF(envioId) { _modalRespForm.show(); } + diff --git a/lab_enfermeras.php b/lab_enfermeras.php index a3bc10d..3b9713e 100644 --- a/lab_enfermeras.php +++ b/lab_enfermeras.php @@ -425,5 +425,6 @@ async function guardarAcceso() { cargarEnfermeras(); + diff --git a/lab_formulario_builder.php b/lab_formulario_builder.php index a402822..5209dff 100644 --- a/lab_formulario_builder.php +++ b/lab_formulario_builder.php @@ -1168,5 +1168,6 @@ document.addEventListener('DOMContentLoaded', async () => { } }); + diff --git a/lab_formularios.php b/lab_formularios.php index cfd6f76..83707c9 100644 --- a/lab_formularios.php +++ b/lab_formularios.php @@ -821,5 +821,6 @@ document.addEventListener('DOMContentLoaded', async () => { cargarFormularios(); }); + diff --git a/lab_ordenes.php b/lab_ordenes.php index 72e9ddb..acbbbac 100644 --- a/lab_ordenes.php +++ b/lab_ordenes.php @@ -451,5 +451,6 @@ function mostrarToast(msg, tipo='success') { cargarLista(); + diff --git a/lab_pacientes.php b/lab_pacientes.php index 7b5ee6f..f4b29f8 100644 --- a/lab_pacientes.php +++ b/lab_pacientes.php @@ -372,5 +372,6 @@ function mostrarToast(msg, tipo = 'success') { // Init cargarLista(); + diff --git a/lab_reportes.php b/lab_reportes.php index d074e90..d524bfe 100644 --- a/lab_reportes.php +++ b/lab_reportes.php @@ -347,5 +347,6 @@ const formatFecha = s => s ? new Date(s).toLocaleString('es-CO', {day:'2-digit', cargarTodo(); + diff --git a/lab_terminos.php b/lab_terminos.php index 52bc944..7b1fa93 100644 --- a/lab_terminos.php +++ b/lab_terminos.php @@ -267,5 +267,6 @@ try { + diff --git a/lab_usuarios.php b/lab_usuarios.php index 160c086..8b49a13 100644 --- a/lab_usuarios.php +++ b/lab_usuarios.php @@ -568,5 +568,6 @@ document.getElementById('r_slug').addEventListener('input', function() { } })(); +