actividades

This commit is contained in:
Lizandro Guarnizo
2026-04-08 09:02:32 -05:00
parent 3d252efbdd
commit d38b5936ca
12 changed files with 427 additions and 11 deletions
+18 -11
View File
@@ -6,20 +6,27 @@ requireMethod('GET');
try {
$log = new ActividadAdmin();
$modulo = $_GET['modulo'] ?? '';
$adminFilt = (int)($_GET['admin_id'] ?? 0);
$entidad = (int)($_GET['entidad_id'] ?? 0);
$limit = max(1, min(200, (int)($_GET['limit'] ?? 50)));
if ($adminFilt) {
$data = $log->porAdmin($adminFilt, $limit);
} elseif ($entidad && $modulo) {
// Caso especial: historial de una entidad concreta
$entidad = (int)($_GET['entidad_id'] ?? 0);
$modulo = $_GET['modulo'] ?? '';
if ($entidad && $modulo) {
$data = $log->porEntidad($modulo, $entidad);
} else {
$data = $log->reciente($limit, $modulo);
jsonOk(['data' => $data, 'total' => count($data), 'paginas' => 1, 'pagina' => 1]);
exit;
}
jsonOk(['data' => $data, 'total' => count($data)]);
$result = $log->filtrar([
'desde' => $_GET['desde'] ?? '',
'hasta' => $_GET['hasta'] ?? '',
'modulo' => $modulo,
'accion' => $_GET['accion'] ?? '',
'admin_id' => (int)($_GET['admin_id'] ?? 0) ?: null,
'buscar' => $_GET['buscar'] ?? '',
'page' => max(1, (int)($_GET['page'] ?? 1)),
'per_page' => max(1, min(200, (int)($_GET['limit'] ?? 50))),
]);
jsonOk($result);
} catch (Exception $e) {
jsonError($e->getMessage(), 500);
}
+71
View File
@@ -129,4 +129,75 @@ class ActividadAdmin {
ORDER BY modulo, total DESC
", [$desde, $hasta]);
}
/**
* Filtrado avanzado con paginación.
*
* @param array $opts {desde, hasta, modulo, accion, admin_id, buscar, page, per_page}
* @return array {data, total, paginas, pagina}
*/
public function filtrar(array $opts = []): array {
$where = [];
$params = [];
if (!empty($opts['desde'])) {
$where[] = 'DATE(a.created_at) >= ?';
$params[] = $opts['desde'];
}
if (!empty($opts['hasta'])) {
$where[] = 'DATE(a.created_at) <= ?';
$params[] = $opts['hasta'];
}
if (!empty($opts['modulo'])) {
$where[] = 'a.modulo = ?';
$params[] = $opts['modulo'];
}
if (!empty($opts['accion'])) {
$where[] = 'a.accion = ?';
$params[] = $opts['accion'];
}
if (!empty($opts['admin_id'])) {
$where[] = 'a.admin_id = ?';
$params[] = (int)$opts['admin_id'];
}
if (!empty($opts['buscar'])) {
$where[] = '(a.admin_nombre LIKE ? OR a.detalle LIKE ?)';
$like = '%' . $opts['buscar'] . '%';
$params[] = $like;
$params[] = $like;
}
$whereStr = $where ? 'WHERE ' . implode(' AND ', $where) : '';
$total = (int)($this->db->fetch(
"SELECT COUNT(*) AS n FROM lab_actividad_admin a $whereStr",
$params
)['n'] ?? 0);
$pp = max(1, (int)($opts['per_page'] ?? 50));
$pag = max(1, (int)($opts['page'] ?? 1));
$off = ($pag - 1) * $pp;
$pParams = $params;
$pParams[] = $pp;
$pParams[] = $off;
$data = $this->db->fetchAll("
SELECT
a.*,
u.username AS admin_username
FROM lab_actividad_admin a
LEFT JOIN admin_users u ON u.id = a.admin_id
$whereStr
ORDER BY a.created_at DESC
LIMIT ? OFFSET ?
", $pParams);
return [
'data' => $data,
'total' => $total,
'paginas' => (int)ceil($total / $pp),
'pagina' => $pag,
];
}
}
+329
View File
@@ -0,0 +1,329 @@
<?php
/**
* Log de Actividad — Trazabilidad del Módulo Administrativo de Laboratorio
*/
require_once 'config/config.php';
if (!isUserLoggedIn()) { header('Location: login.php'); exit; }
if (isEnfermero()) { header('Location: enfermero_portal.php'); exit; }
$adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['username'] ?? 'Admin';
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Log de Actividad — Módulo 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>
.log-row td { font-size: .85rem; vertical-align: middle; }
.detalle-cell { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.detalle-cell:hover { text-decoration: underline dotted; color: #0d6efd; }
.badge-accion { font-size: .72rem; }
.ctrl { height: 31px; }
</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 active"><i class="fas fa-history"></i> Actividad</a></li>
<li><a href="lab_configuracion.php" class="nav-link"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li><a href="lab_usuarios.php" class="nav-link"><i class="fas fa-users-cog"></i> Usuarios</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 logout-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-history text-primary"></i> Log de Actividad</h1>
<small class="text-muted"><?= htmlspecialchars($adminNombre) ?></small>
</div>
<button class="btn btn-success btn-sm" onclick="exportarCSV()">
<i class="fas fa-file-csv me-1"></i> Exportar CSV
</button>
</header>
<div class="container-fluid py-3">
<!-- Filtros -->
<div class="card border-0 shadow-sm mb-3">
<div class="card-body py-2">
<div class="row g-2 align-items-end">
<div class="col-auto">
<label class="form-label mb-0 small fw-semibold">Desde</label>
<input type="date" id="act-desde" class="form-control form-control-sm ctrl">
</div>
<div class="col-auto">
<label class="form-label mb-0 small fw-semibold">Hasta</label>
<input type="date" id="act-hasta" class="form-control form-control-sm ctrl">
</div>
<div class="col-auto">
<label class="form-label mb-0 small fw-semibold">Módulo</label>
<select id="act-modulo" class="form-select form-select-sm ctrl">
<option value="">Todos</option>
<option value="ordenes">Órdenes</option>
<option value="domicilios">Domicilios</option>
<option value="pacientes">Pacientes</option>
<option value="enfermeras">Enfermeras</option>
<option value="formularios">Formularios</option>
<option value="asignaciones">Asignaciones</option>
</select>
</div>
<div class="col-auto">
<label class="form-label mb-0 small fw-semibold">Acción</label>
<select id="act-accion" class="form-select form-select-sm ctrl">
<option value="">Todas</option>
<option value="crear">crear</option>
<option value="editar">editar</option>
<option value="eliminar">eliminar</option>
<option value="autorizar">autorizar</option>
<option value="rechazar">rechazar</option>
<option value="asignar">asignar</option>
<option value="enviar">enviar</option>
<option value="reprogramar">reprogramar</option>
<option value="cambiar_estado">cambiar_estado</option>
</select>
</div>
<div class="col">
<label class="form-label mb-0 small fw-semibold">Buscar</label>
<input type="text" id="act-buscar" class="form-control form-control-sm ctrl" placeholder="Usuario o detalle…">
</div>
<div class="col-auto d-flex gap-2">
<button class="btn btn-primary btn-sm ctrl" onclick="cargar(1)">
<i class="fas fa-search"></i>
</button>
<button class="btn btn-outline-secondary btn-sm ctrl" onclick="limpiar()">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Tabla -->
<div class="card border-0 shadow-sm">
<div class="card-body p-0">
<div id="act-spinner" class="text-center py-5 text-muted">
<i class="fas fa-spinner fa-spin fa-2x"></i>
</div>
<div id="act-wrap" class="d-none">
<table class="table table-hover table-sm mb-0">
<thead class="table-light">
<tr>
<th style="width:145px">Fecha / Hora</th>
<th>Usuario</th>
<th style="width:110px">Módulo</th>
<th style="width:120px">Acción</th>
<th style="width:70px" class="text-center">Entidad</th>
<th>Detalle</th>
<th style="width:105px">IP</th>
</tr>
</thead>
<tbody id="act-tbody"></tbody>
</table>
</div>
<div id="act-empty" class="d-none text-center py-5 text-muted">
<i class="fas fa-history fa-2x mb-2 d-block opacity-25"></i>
Sin actividad para los filtros seleccionados
</div>
</div>
<div class="card-footer bg-white" id="act-footer"></div>
</div>
</div><!-- /container -->
</main>
<!-- Modal detalle -->
<div class="modal fade" id="modalDetalle" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-info-circle me-2 text-primary"></i>Detalle del evento</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<pre id="modal-detalle-pre" class="bg-light p-3 rounded small mb-0" style="white-space:pre-wrap;word-break:break-all;max-height:420px;overflow-y:auto"></pre>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const MODULO_COLOR = {
ordenes:'warning', domicilios:'success', pacientes:'primary',
enfermeras:'info', formularios:'secondary', asignaciones:'dark',
};
const ACCION_COLOR = {
crear:'success', editar:'primary', eliminar:'danger',
autorizar:'success', rechazar:'danger', asignar:'info',
enviar:'secondary', reprogramar:'warning', cambiar_estado:'primary',
};
let _actPag = 1;
let _actData = [];
let _debounce;
document.addEventListener('DOMContentLoaded', () => {
const hoy = new Date().toISOString().slice(0,10);
document.getElementById('act-desde').value = hoy.slice(0,7) + '-01';
document.getElementById('act-hasta').value = hoy;
['act-desde','act-hasta','act-modulo','act-accion'].forEach(id =>
document.getElementById(id).addEventListener('change', () => cargar(1))
);
document.getElementById('act-buscar').addEventListener('input', () => {
clearTimeout(_debounce);
_debounce = setTimeout(() => cargar(1), 400);
});
cargar(1);
});
async function cargar(pag = 1) {
_actPag = pag;
document.getElementById('act-spinner').classList.remove('d-none');
document.getElementById('act-wrap').classList.add('d-none');
document.getElementById('act-empty').classList.add('d-none');
const params = new URLSearchParams({
desde: document.getElementById('act-desde').value,
hasta: document.getElementById('act-hasta').value,
modulo: document.getElementById('act-modulo').value,
accion: document.getElementById('act-accion').value,
buscar: document.getElementById('act-buscar').value,
page: pag,
limit: 50,
});
try {
const r = await fetch(`api/lab/get_actividad.php?${params}`);
const d = await r.json();
document.getElementById('act-spinner').classList.add('d-none');
if (!d.data?.length) {
document.getElementById('act-empty').classList.remove('d-none');
document.getElementById('act-footer').innerHTML = '';
return;
}
_actData = d.data;
renderTabla(d.data);
renderPaginacion(d.total, d.paginas, pag);
} catch(e) {
document.getElementById('act-spinner').classList.add('d-none');
document.getElementById('act-empty').classList.remove('d-none');
}
}
function renderTabla(rows) {
document.getElementById('act-wrap').classList.remove('d-none');
document.getElementById('act-tbody').innerHTML = rows.map((a, i) => {
const det = a.detalle || '';
const detShort = det.length > 70 ? det.slice(0,70) + '…' : det;
const mColor = MODULO_COLOR[a.modulo] || 'secondary';
const aColor = ACCION_COLOR[a.accion] || 'secondary';
const usuario = esc(a.admin_nombre || a.admin_username || 'Sistema');
const sub = (a.admin_username && a.admin_nombre)
? `<div class="text-muted" style="font-size:.74rem">@${esc(a.admin_username)}</div>` : '';
return `<tr class="log-row">
<td class="text-muted text-nowrap">${formatFecha(a.created_at)}</td>
<td><span class="fw-semibold">${usuario}</span>${sub}</td>
<td><span class="badge bg-${mColor} badge-accion">${esc(a.modulo)}</span></td>
<td><span class="badge bg-${aColor} bg-opacity-75 badge-accion text-dark">${esc(a.accion)}</span></td>
<td class="text-center text-muted">${a.entidad_id ? '#' + a.entidad_id : '—'}</td>
<td class="detalle-cell" onclick="verDetalle(${i})" title="Click para ver detalle completo">${esc(detShort) || '<span class="text-muted">—</span>'}</td>
<td class="text-muted small">${esc(a.ip_address || '—')}</td>
</tr>`;
}).join('');
}
function renderPaginacion(total, paginas, pag) {
const el = document.getElementById('act-footer');
if (paginas <= 1) {
el.innerHTML = `<small class="text-muted">${total} evento(s)</small>`;
return;
}
const pages = [];
for (let p = Math.max(1, pag - 2); p <= Math.min(paginas, pag + 2); p++) pages.push(p);
el.innerHTML = `
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2">
<small class="text-muted">${total} evento(s) — página ${pag} de ${paginas}</small>
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-secondary" onclick="cargar(1)" ${pag===1?'disabled':''}>«</button>
<button class="btn btn-outline-secondary" onclick="cargar(${pag-1})" ${pag===1?'disabled':''}></button>
${pages.map(p => `<button class="btn ${p===pag?'btn-primary':'btn-outline-secondary'}" onclick="cargar(${p})">${p}</button>`).join('')}
<button class="btn btn-outline-secondary" onclick="cargar(${pag+1})" ${pag>=paginas?'disabled':''}></button>
<button class="btn btn-outline-secondary" onclick="cargar(${paginas})" ${pag>=paginas?'disabled':''}>»</button>
</div>
</div>`;
}
function verDetalle(i) {
const a = _actData[i];
let det = a.detalle || '(sin detalle)';
try { det = JSON.stringify(JSON.parse(det), null, 2); } catch(e) {}
document.getElementById('modal-detalle-pre').textContent =
`Módulo: ${a.modulo}\nAcción: ${a.accion}\nEntidad: ${a.entidad_id ? '#' + a.entidad_id : '—'}\nUsuario: ${a.admin_nombre || a.admin_username || 'Sistema'}\nFecha: ${a.created_at}\nIP: ${a.ip_address || '—'}\n\nDetalle:\n${det}`;
new bootstrap.Modal(document.getElementById('modalDetalle')).show();
}
async function exportarCSV() {
const params = new URLSearchParams({
desde: document.getElementById('act-desde').value,
hasta: document.getElementById('act-hasta').value,
modulo: document.getElementById('act-modulo').value,
accion: document.getElementById('act-accion').value,
buscar: document.getElementById('act-buscar').value,
page: 1,
limit: 2000,
});
const r = await fetch(`api/lab/get_actividad.php?${params}`);
const d = await r.json();
if (!d.data?.length) { alert('Sin datos para exportar'); return; }
const cols = ['id','created_at','admin_nombre','admin_username','modulo','accion','entidad_id','detalle','ip_address'];
const rows = d.data.map(a =>
cols.map(c => '"' + String(a[c] ?? '').replace(/"/g, '""') + '"').join(',')
);
const csv = '\uFEFF' + [cols.join(','), ...rows].join('\r\n');
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `actividad_${new Date().toISOString().slice(0,10)}.csv`;
a.click();
URL.revokeObjectURL(url);
}
function limpiar() {
const hoy = new Date().toISOString().slice(0,10);
document.getElementById('act-desde').value = hoy.slice(0,7) + '-01';
document.getElementById('act-hasta').value = hoy;
document.getElementById('act-modulo').value = '';
document.getElementById('act-accion').value = '';
document.getElementById('act-buscar').value = '';
cargar(1);
}
const esc = s => String(s||'').replace(/[<>&"]/g, c => ({'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c]));
const formatFecha = s => s ? new Date(s).toLocaleString('es-CO', {day:'2-digit',month:'short',year:'numeric',hour:'2-digit',minute:'2-digit'}) : '—';
</script>
</body>
</html>
+1
View File
@@ -51,6 +51,7 @@ foreach ($rows as $r) { $cfg[$r['clave']] = $r['valor']; }
<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>
+1
View File
@@ -59,6 +59,7 @@ $adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['
<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"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li><a href="lab_usuarios.php" class="nav-link"><i class="fas fa-users-cog"></i> Usuarios</a></li>
<li class="sidebar-divider"></li>
+1
View File
@@ -59,6 +59,7 @@ $domIdParam = (int)($_GET['id'] ?? 0);
<?php if (hasModule('lab_reportes')): ?>
<li><a href="lab_reportes.php" class="nav-link"><i class="fas fa-chart-bar"></i> Reportes</a></li>
<?php endif; ?>
<li><a href="lab_actividad.php" class="nav-link"><i class="fas fa-history"></i> Actividad</a></li>
<?php if (hasModule('lab_configuracion')): ?>
<li><a href="lab_configuracion.php" class="nav-link"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<?php endif; ?>
+1
View File
@@ -42,6 +42,7 @@ $adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['
<li><a href="lab_enfermeras.php" class="nav-link active"><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"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li><a href="lab_usuarios.php" class="nav-link"><i class="fas fa-users-cog"></i> Usuarios</a></li>
<li class="sidebar-divider"></li>
+1
View File
@@ -71,6 +71,7 @@ $puedeEscribir = $esAdmin && hasModuleWrite('lab_formularios');
<?php if (hasModule('lab_reportes')): ?>
<li><a href="lab_reportes.php" class="nav-link"><i class="fas fa-chart-bar"></i> Reportes</a></li>
<?php endif; ?>
<li><a href="lab_actividad.php" class="nav-link"><i class="fas fa-history"></i> Actividad</a></li>
<?php if (hasModule('lab_configuracion')): ?>
<li><a href="lab_configuracion.php" class="nav-link"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<?php endif; ?>
+1
View File
@@ -58,6 +58,7 @@ $estadoParam = $_GET['estado'] ?? '';
<?php if (hasModule('lab_reportes')): ?>
<li><a href="lab_reportes.php" class="nav-link"><i class="fas fa-chart-bar"></i> Reportes</a></li>
<?php endif; ?>
<li><a href="lab_actividad.php" class="nav-link"><i class="fas fa-history"></i> Actividad</a></li>
<?php if (hasModule('lab_configuracion')): ?>
<li><a href="lab_configuracion.php" class="nav-link"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<?php endif; ?>
+1
View File
@@ -38,6 +38,7 @@ $adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['
<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"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li><a href="lab_usuarios.php" class="nav-link"><i class="fas fa-users-cog"></i> Usuarios</a></li>
<li class="sidebar-divider"></li>
+1
View File
@@ -197,6 +197,7 @@ $adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['
<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 active"><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"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li><a href="lab_usuarios.php" class="nav-link"><i class="fas fa-users-cog"></i> Usuarios</a></li>
<li class="sidebar-divider"></li>
+1
View File
@@ -47,6 +47,7 @@ $systemModules = SYSTEM_MODULES;
<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"><i class="fas fa-sliders-h"></i> Configuración</a></li>
<li><a href="lab_usuarios.php" class="nav-link active"><i class="fas fa-users-cog"></i> Usuarios</a></li>
<li class="sidebar-divider"></li>