feat(ui): rediseño integral de UI/UX de la aplicación (navbar, sidebar offcanvas, KPIs, tablas y chat de tickets)

This commit is contained in:
2026-10-20 21:04:02 -05:00
parent 2f7a2d7568
commit efe95fca54
15 changed files with 2399 additions and 709 deletions
+7 -3
View File
@@ -9,17 +9,21 @@
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
<link rel="shortcut icon" href="/favicon.ico">
<!-- Google Fonts: Plus Jakarta Sans -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link href="/css/style.css" rel="stylesheet">
</head>
<body>
<body class="<%= user ? 'app-body' : 'auth-body' %>">
<%- include('navbar') %>
<div class="container-fluid">
<div class="container-fluid app-container-fluid">
<div class="row">
<% if (user) { %>
<%- include('sidebar') %>
<main class="col-md-9 ms-sm-auto col-lg-10 px-4">
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4 main-content">
<% } else { %>
<main class="col-12 px-2 px-sm-3 px-md-4">
<% } %>
+43 -13
View File
@@ -1,17 +1,47 @@
<nav class="navbar navbar-dark bg-dark sticky-top">
<div class="container-fluid">
<a class="navbar-brand d-flex align-items-center gap-2" href="/">
<img src="/img/logo.svg" alt="Help Desk Logo" width="28" height="28" class="d-inline-block align-text-top rounded-1">
<span>Help Desk</span>
</a>
<nav class="navbar navbar-dark bg-dark sticky-top app-topbar">
<div class="container-fluid px-3">
<div class="d-flex align-items-center gap-2">
<% if (user) { %>
<button class="btn btn-sm btn-icon-glass text-white d-md-none me-1" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-label="Abrir menú">
<i class="fas fa-bars fs-5"></i>
</button>
<% } %>
<a class="navbar-brand d-flex align-items-center gap-2 m-0" href="/">
<div class="brand-logo-glow">
<img src="/img/logo.svg" alt="Help Desk Logo" width="28" height="28" class="d-inline-block align-text-top rounded-1">
</div>
<div class="d-flex flex-column">
<span class="brand-text">Help Desk <span class="brand-subtext d-none d-sm-inline">& FSM</span></span>
</div>
</a>
<% if (typeof company !== 'undefined' && company) { %>
<div class="company-nav-pill ms-2 d-none d-lg-flex align-items-center gap-1.5">
<i class="fas fa-building text-info" style="font-size: 0.75rem;"></i>
<span class="company-name-text"><%= company.name %></span>
<span class="badge company-plan-badge"><%= company.plan %></span>
</div>
<% } %>
</div>
<% if (user) { %>
<div class="d-flex align-items-center">
<span class="text-light me-3">
<i class="fas fa-user"></i> <%= user.nombre %>
<span class="badge bg-info ms-1"><%= user.rol %></span>
</span>
<a href="/logout" class="btn btn-outline-light btn-sm">
<i class="fas fa-sign-out-alt"></i> Salir
<div class="d-flex align-items-center gap-2 gap-sm-3">
<div class="user-profile-badge d-flex align-items-center gap-2">
<% if (user.avatar_url) { %>
<img src="<%= user.avatar_url %>" alt="<%= user.nombre %>" class="user-avatar-img">
<% } else { %>
<div class="user-avatar-initials">
<%= (user.nombre || 'U').charAt(0).toUpperCase() %>
</div>
<% } %>
<div class="d-none d-sm-flex flex-column text-start">
<span class="user-nav-name"><%= user.nombre %></span>
<span class="user-nav-role badge-role-<%= user.rol %>"><%= user.rol %></span>
</div>
</div>
<a href="/logout" class="btn btn-logout-glass btn-sm d-flex align-items-center gap-1.5" title="Cerrar Sesión">
<i class="fas fa-sign-out-alt"></i>
<span class="d-none d-md-inline">Salir</span>
</a>
</div>
<% } %>
+82 -38
View File
@@ -1,70 +1,114 @@
<nav class="col-md-3 col-lg-2 d-md-block bg-light sidebar">
<div class="position-sticky pt-3">
<% if (company) { %>
<div class="px-3 mb-3">
<small class="text-muted"><%= company.name %></small>
<span class="badge bg-info"><%= company.plan %></span>
<div class="offcanvas-md offcanvas-start app-sidebar col-md-3 col-lg-2" tabindex="-1" id="sidebarMenu" aria-labelledby="sidebarMenuLabel">
<!-- Header para Móvil (Offcanvas) -->
<div class="offcanvas-header d-md-none border-bottom p-3">
<div class="d-flex align-items-center gap-2">
<img src="/img/logo.svg" alt="Logo" width="24" height="24" class="rounded-1">
<h6 class="offcanvas-title mb-0 fw-bold" id="sidebarMenuLabel">Menú Principal</h6>
</div>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#sidebarMenu" aria-label="Cerrar"></button>
</div>
<div class="offcanvas-body d-flex flex-column p-3 pt-md-3 h-100">
<!-- Ficha de Organización / Tenant -->
<% if (typeof company !== 'undefined' && company) { %>
<div class="sidebar-company-card mb-3 p-2.5 rounded-3">
<div class="d-flex align-items-center justify-content-between mb-1">
<span class="company-card-title text-truncate fw-bold text-dark" style="font-size: 0.84rem;"><%= company.name %></span>
<span class="badge company-plan-badge"><%= (company.plan || 'Plan').toUpperCase() %></span>
</div>
<div class="d-flex align-items-center gap-1.5 text-muted" style="font-size: 0.72rem;">
<span class="company-status-dot"></span>
<span>Tenant <%= company.slug || 'activo' %></span>
</div>
</div>
<% } %>
<ul class="nav flex-column">
<!-- Lista de Navegación -->
<ul class="nav flex-column sidebar-nav flex-grow-1 gap-1">
<li class="sidebar-heading">OPERACIONES</li>
<% if (user.rol === 'superadmin') { %>
<li class="nav-item">
<a class="nav-link" href="/saas/companies">
<i class="fas fa-building"></i> Empresas
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/admin/dashboard">
<i class="fas fa-tachometer-alt"></i> Mi Empresa
<a class="nav-link <%= typeof title !== 'undefined' && title === 'Empresas' ? 'active' : '' %>" href="/saas/companies">
<div class="nav-icon-wrapper"><i class="fas fa-sitemap"></i></div>
<span>Empresas SaaS</span>
</a>
</li>
<% } %>
<li class="nav-item">
<a class="nav-link" href="/<%= ['superadmin','admin'].includes(user.rol) ? 'admin' : user.rol %>/dashboard">
<i class="fas fa-tachometer-alt"></i> Dashboard
<a class="nav-link <%= typeof title !== 'undefined' && (title.includes('Dashboard') || title === 'Mis Tickets') ? 'active' : '' %>" href="/<%= ['superadmin','admin'].includes(user.rol) ? 'admin' : user.rol %>/dashboard">
<div class="nav-icon-wrapper"><i class="fas fa-chart-pie"></i></div>
<span>Dashboard</span>
</a>
</li>
<% if (user.rol === 'client') { %>
<li class="nav-item">
<a class="nav-link" href="/client/new-ticket">
<i class="fas fa-plus-circle"></i> Nuevo Ticket
<a class="nav-link <%= typeof title !== 'undefined' && title === 'Nuevo Ticket' ? 'active' : '' %>" href="/client/new-ticket">
<div class="nav-icon-wrapper text-primary"><i class="fas fa-plus-circle"></i></div>
<span>Nuevo Ticket</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/client/dashboard">
<i class="fas fa-tickets"></i> Mis Tickets
<a class="nav-link <%= typeof title !== 'undefined' && title === 'Mis Tickets' ? 'active' : '' %>" href="/client/dashboard">
<div class="nav-icon-wrapper"><i class="fas fa-ticket-alt"></i></div>
<span>Mis Tickets</span>
</a>
</li>
<% } %>
<% if (['superadmin', 'admin', 'agent'].includes(user.rol)) { %>
<li class="nav-item">
<a class="nav-link" href="/agent/dashboard">
<i class="fas fa-tasks"></i> Tickets
</a>
</li>
<% } %>
<% if (['superadmin', 'admin'].includes(user.rol)) { %>
<li class="nav-item">
<a class="nav-link" href="/admin/users">
<i class="fas fa-users"></i> Usuarios
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/admin/departments">
<i class="fas fa-building"></i> Departamentos
<a class="nav-link <%= typeof title !== 'undefined' && title.includes('Agente') ? 'active' : '' %>" href="/agent/dashboard">
<div class="nav-icon-wrapper"><i class="fas fa-inbox"></i></div>
<span>Bandeja Tickets</span>
</a>
</li>
<% } %>
<% if (['superadmin', 'admin'].includes(user.rol)) { %>
<li class="sidebar-heading mt-3">ADMINISTRACIÓN</li>
<li class="nav-item">
<a class="nav-link" href="/company">
<i class="fas fa-cog"></i> Configuración
<a class="nav-link <%= typeof title !== 'undefined' && title === 'Usuarios' ? 'active' : '' %>" href="/admin/users">
<div class="nav-icon-wrapper"><i class="fas fa-users-cog"></i></div>
<span>Usuarios y Equipo</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <%= typeof title !== 'undefined' && title === 'Departamentos' ? 'active' : '' %>" href="/admin/departments">
<div class="nav-icon-wrapper"><i class="fas fa-network-wired"></i></div>
<span>Departamentos</span>
</a>
</li>
<% } %>
<li class="sidebar-heading mt-3">SISTEMA</li>
<li class="nav-item">
<a class="nav-link <%= typeof title !== 'undefined' && title === 'Configuración' ? 'active' : '' %>" href="/company">
<div class="nav-icon-wrapper"><i class="fas fa-sliders-h"></i></div>
<span>Configuración</span>
</a>
</li>
</ul>
<!-- Widget Bot de Soporte Activo en el Sidebar -->
<div class="sidebar-bot-card mt-3 p-2.5 rounded-3 border text-center">
<div class="d-flex align-items-center gap-2 justify-content-center mb-1">
<img src="/img/bot-soporte.svg" alt="Bot Soporte" width="34" height="34" class="bot-sidebar-avatar">
<div class="text-start">
<div class="fw-bold text-dark" style="font-size: 0.78rem; line-height: 1.1;">Asistente FSM</div>
<small class="text-muted" style="font-size: 0.68rem;">SIAX Core v2.0</small>
</div>
</div>
<div class="d-flex align-items-center justify-content-center gap-1.5 pt-1">
<span class="bot-status-dot" style="width: 6px; height: 6px;"></span>
<span class="text-success fw-medium" style="font-size: 0.70rem;">Monitoreo 24/7</span>
</div>
</div>
</div>
</nav>
</div>