165 lines
6.7 KiB
PHP
165 lines
6.7 KiB
PHP
<?php
|
|
/**
|
|
* shared/components/sidebar.php
|
|
* Menú lateral dinámico del ERP generado desde ModuleRegistry.
|
|
*
|
|
* DEPENDENCIAS:
|
|
* - config/config.php (sesión iniciada, SYSTEM_MODULES disponible)
|
|
* - core/Rbac.php (hasModule())
|
|
* - core/ModuleRegistry.php (forSidebar())
|
|
*
|
|
* Carga ModuleRegistry si aún no está disponible (compatibilidad con
|
|
* archivos lab_*.php que incluyen este sidebar directamente).
|
|
*/
|
|
|
|
// Cargar ModuleRegistry si no está ya (cuando el sidebar se incluye desde legacy files)
|
|
if (!class_exists('ModuleRegistry', false)) {
|
|
// Asegurar APP_ROOT para que loadFromFiles() funcione
|
|
if (!defined('APP_ROOT')) {
|
|
define('APP_ROOT', realpath(__DIR__ . '/../../'));
|
|
}
|
|
$__mrFile = defined('APP_ROOT')
|
|
? APP_ROOT . '/core/ModuleRegistry.php'
|
|
: __DIR__ . '/../../core/ModuleRegistry.php';
|
|
if (file_exists($__mrFile)) {
|
|
require_once $__mrFile;
|
|
}
|
|
}
|
|
|
|
// Ruta del script que está siendo cargado actualmente
|
|
$_current_script = basename($_SERVER['PHP_SELF']);
|
|
|
|
/**
|
|
* Retorna 'active' si la URL o script actual coincide con la ruta dada.
|
|
*/
|
|
$_isActive = function (string $route) use ($_current_script): string {
|
|
if ($route === '') return '';
|
|
$parsed = parse_url($route);
|
|
$routeBase = basename($parsed['path'] ?? '');
|
|
|
|
// Rutas ERP con query params: comparar script Y cada param de la ruta
|
|
if (!empty($parsed['query'])) {
|
|
$uriParsed = parse_url($_SERVER['REQUEST_URI'] ?? '');
|
|
if ($routeBase !== basename($uriParsed['path'] ?? '')) return '';
|
|
parse_str($parsed['query'], $routeParams);
|
|
parse_str($uriParsed['query'] ?? '', $uriParams);
|
|
foreach ($routeParams as $k => $v) {
|
|
if (($uriParams[$k] ?? null) !== $v) return '';
|
|
}
|
|
return ' active';
|
|
}
|
|
|
|
// Rutas directas como /lab_domicilios.php
|
|
return $routeBase === $_current_script ? ' active' : '';
|
|
};
|
|
|
|
// Título del sidebar: prioridad al nombre definido por el módulo, luego el genérico
|
|
$_sidebar_title = $SIDEBAR_TITLE ?? $GLOBALS['_LAYOUT_TITLE'] ?? 'Panel ERP';
|
|
$_sidebar_icon = $SIDEBAR_ICON ?? $GLOBALS['_LAYOUT_ICON'] ?? 'fas fa-th-large';
|
|
|
|
// Nombre del usuario para el pie del sidebar
|
|
$_user_name = $_SESSION['admin_user']['full_name']
|
|
?? $_SESSION['admin_user']['username']
|
|
?? 'Usuario';
|
|
$_user_role = $_SESSION['admin_user']['role'] ?? 'admin';
|
|
|
|
// Mapa de roles a etiqueta legible
|
|
$_role_label = [
|
|
'superadmin' => 'Super Admin',
|
|
'admin' => 'Administrador',
|
|
'recepcionista' => 'Recepcionista',
|
|
'bacteriologo' => 'Bacteriólogo',
|
|
'enfermero' => 'Enfermero',
|
|
'supervisor' => 'Supervisor',
|
|
'operador_bot' => 'Operador Bot',
|
|
'readonly' => 'Solo Lectura',
|
|
][$_user_role] ?? ucfirst($_user_role);
|
|
|
|
// Base URL para rutas relativas
|
|
$_base = defined('APP_URL') ? rtrim(APP_URL, '/') : '';
|
|
?>
|
|
<nav class="sidebar" id="erp-sidebar">
|
|
|
|
<div class="sidebar-header">
|
|
<h4><i class="<?= htmlspecialchars($_sidebar_icon, ENT_QUOTES, 'UTF-8') ?>"></i>
|
|
<?= htmlspecialchars($_sidebar_title, ENT_QUOTES, 'UTF-8') ?></h4>
|
|
</div>
|
|
|
|
<ul class="sidebar-menu">
|
|
|
|
<?php
|
|
// ── Renderizado dinámico desde ModuleRegistry ───────────────────────────────
|
|
if (class_exists('ModuleRegistry', false)) {
|
|
$sidebarGroups = ModuleRegistry::forSidebar();
|
|
|
|
foreach ($sidebarGroups as $catKey => $catData):
|
|
if (empty($catData['modules'])) continue;
|
|
?>
|
|
<!-- ══ <?= htmlspecialchars($catData['label'], ENT_QUOTES, 'UTF-8') ?> ══ -->
|
|
<li class="sidebar-section">
|
|
<i class="<?= htmlspecialchars($catData['icon'], ENT_QUOTES, 'UTF-8') ?> me-1"></i>
|
|
<?= htmlspecialchars($catData['label'], ENT_QUOTES, 'UTF-8') ?>
|
|
</li>
|
|
|
|
<?php foreach ($catData['modules'] as $slug => $mod):
|
|
$links = $mod['links'] ?? [];
|
|
// Si el módulo declara links propios, mostrarlos todos
|
|
if (!empty($links)):
|
|
foreach ($links as $lnk):
|
|
$href = $_base . $lnk['route'];
|
|
$active = $_isActive($lnk['route']);
|
|
?>
|
|
<li><a href="<?= htmlspecialchars($href, ENT_QUOTES, 'UTF-8') ?>"
|
|
class="nav-link<?= $active ?>">
|
|
<i class="<?= htmlspecialchars($lnk['icon'], ENT_QUOTES, 'UTF-8') ?>"></i>
|
|
<?= htmlspecialchars($lnk['name'], ENT_QUOTES, 'UTF-8') ?></a></li>
|
|
<?php endforeach;
|
|
else:
|
|
// Solo la ruta principal del módulo
|
|
$route = $mod['route'] ?? '';
|
|
$href = $route ? $_base . $route : '#';
|
|
$active = $route ? $_isActive($route) : '';
|
|
?>
|
|
<li><a href="<?= htmlspecialchars($href, ENT_QUOTES, 'UTF-8') ?>"
|
|
class="nav-link<?= $active ?>">
|
|
<i class="<?= htmlspecialchars($mod['icon'], ENT_QUOTES, 'UTF-8') ?>"></i>
|
|
<?= htmlspecialchars($mod['name'], ENT_QUOTES, 'UTF-8') ?></a></li>
|
|
<?php endif;
|
|
endforeach;
|
|
endforeach;
|
|
|
|
} else {
|
|
// ── Fallback estático (cuando ModuleRegistry no está disponible) ──────────
|
|
// Solo muestra los módulos básicos de laboratorio sin lógica dinámica.
|
|
?>
|
|
<li class="sidebar-section"><i class="fas fa-house-medical me-1"></i> Domicilios</li>
|
|
<?php if (function_exists('hasModule') && hasModule('lab_dashboard')): ?>
|
|
<li><a href="lab_dashboard.php" class="nav-link"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
|
|
<?php endif; ?>
|
|
<?php if (function_exists('hasModule') && hasModule('lab_domicilios')): ?>
|
|
<li><a href="lab_domicilios.php" class="nav-link"><i class="fas fa-house-medical"></i> Domicilios</a></li>
|
|
<?php endif; ?>
|
|
<?php if (function_exists('hasModule') && hasModule('lab_pacientes')): ?>
|
|
<li><a href="lab_pacientes.php" class="nav-link"><i class="fas fa-users"></i> Pacientes</a></li>
|
|
<?php endif; ?>
|
|
<?php } ?>
|
|
|
|
<!-- ══ Pie del sidebar ══════════════════════════════════ -->
|
|
<li class="sidebar-divider"></li>
|
|
<li><a href="<?= $_base ?>/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>
|
|
|
|
<!-- Información del usuario -->
|
|
<div class="sidebar-user">
|
|
<div class="sidebar-user-name">
|
|
<i class="fas fa-user-circle me-1"></i>
|
|
<?= htmlspecialchars($_user_name, ENT_QUOTES, 'UTF-8') ?>
|
|
</div>
|
|
<div class="sidebar-user-role"><?= htmlspecialchars($_role_label, ENT_QUOTES, 'UTF-8') ?></div>
|
|
</div>
|
|
|
|
</nav>
|