feat: inicializacion de Help Desk segun estandar Telcotronics con bitacora de errores e integracion MCP

This commit is contained in:
2026-10-16 23:29:32 -05:00
commit 0f2708462e
54 changed files with 7590 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
<%- include('../partials/header') %>
<% title = 'Mis Tickets'; %>
<% if (success_msg && success_msg.length > 0) { %>
<% success_msg.forEach(msg => { %>
<div class="alert alert-success alert-dismissible fade show mt-3"><%= msg %><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>
<% }) %>
<% } %>
<% if (error_msg && error_msg.length > 0) { %>
<% error_msg.forEach(msg => { %>
<div class="alert alert-danger alert-dismissible fade show mt-3"><%= msg %><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>
<% }) %>
<% } %>
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Mis Tickets</h1>
<a href="/client/new-ticket" class="btn btn-primary">
<i class="fas fa-plus"></i> Nuevo Ticket
</a>
</div>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th>#</th>
<th>Asunto</th>
<th>Departamento</th>
<th>Prioridad</th>
<th>Estado</th>
<th>Asignado</th>
<th>Fecha</th>
<th>Acción</th>
</tr>
</thead>
<tbody>
<% if (tickets.length === 0) { %>
<tr><td colspan="8" class="text-center">No tienes tickets aún</td></tr>
<% } %>
<% tickets.forEach(ticket => { %>
<tr>
<td>#<%= ticket.id %></td>
<td><%= ticket.asunto %></td>
<td><%= ticket.departamento_nombre || 'Sin departamento' %></td>
<td>
<span class="badge bg-<%= ticket.prioridad === 'alta' ? 'danger' : ticket.prioridad === 'critica' ? 'dark' : ticket.prioridad === 'media' ? 'warning' : 'info' %>">
<%= ticket.prioridad %>
</span>
</td>
<td>
<span class="badge bg-<%= ticket.status === 'abierto' ? 'success' : ticket.status === 'en_progreso' ? 'primary' : 'secondary' %>">
<%= ticket.status %>
</span>
</td>
<td><%= ticket.asignado_nombre || 'Sin asignar' %></td>
<td><%= ticket.created_at %></td>
<td>
<a href="/client/ticket/<%= ticket.id %>" class="btn btn-sm btn-info">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<%- include('../partials/footer') %>
+59
View File
@@ -0,0 +1,59 @@
<%- include('../partials/header') %>
<% title = 'Nuevo Ticket'; %>
<% if (success_msg && success_msg.length > 0) { %>
<% success_msg.forEach(msg => { %>
<div class="alert alert-success alert-dismissible fade show mt-3"><%= msg %><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>
<% }) %>
<% } %>
<% if (error_msg && error_msg.length > 0) { %>
<% error_msg.forEach(msg => { %>
<div class="alert alert-danger alert-dismissible fade show mt-3"><%= msg %><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>
<% }) %>
<% } %>
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Nuevo Ticket</h1>
</div>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<form action="/client/new-ticket" method="POST">
<div class="mb-3">
<label class="form-label">Asunto</label>
<input type="text" name="asunto" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Departamento</label>
<select name="department_id" class="form-select">
<option value="">Sin departamento</option>
<% departments.forEach(dept => { %>
<option value="<%= dept.id %>"><%= dept.nombre %></option>
<% }) %>
</select>
</div>
<div class="mb-3">
<label class="form-label">Prioridad</label>
<select name="prioridad" class="form-select">
<option value="baja">Baja</option>
<option value="media" selected>Media</option>
<option value="alta">Alta</option>
<option value="critica">Crítica</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Mensaje</label>
<textarea name="mensaje" class="form-control" rows="6" required></textarea>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-paper-plane"></i> Enviar Ticket
</button>
</form>
</div>
</div>
</div>
</div>
<%- include('../partials/footer') %>
+88
View File
@@ -0,0 +1,88 @@
<%- include('../partials/header') %>
<% title = 'Ticket #' + ticket.id; %>
<% if (success_msg && success_msg.length > 0) { %>
<% success_msg.forEach(msg => { %>
<div class="alert alert-success alert-dismissible fade show mt-3"><%= msg %><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>
<% }) %>
<% } %>
<% if (error_msg && error_msg.length > 0) { %>
<% error_msg.forEach(msg => { %>
<div class="alert alert-danger alert-dismissible fade show mt-3"><%= msg %><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>
<% }) %>
<% } %>
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Ticket #<%= ticket.id %>: <%= ticket.asunto %></h1>
<div>
<form action="/client/ticket/<%= ticket.id %>/close" method="POST" style="display:inline">
<button type="submit" class="btn btn-warning" onclick="return confirm('¿Cerrar este ticket?')">
<i class="fas fa-times"></i> Cerrar Ticket
</button>
</form>
<a href="/client/dashboard" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Volver
</a>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="card mb-3">
<div class="card-header"><h6 class="mb-0">Información</h6></div>
<div class="card-body">
<p><strong>Estado:</strong>
<span class="badge bg-<%= ticket.status === 'abierto' ? 'success' : ticket.status === 'en_progreso' ? 'primary' : 'secondary' %>"><%= ticket.status %></span>
</p>
<p><strong>Prioridad:</strong>
<span class="badge bg-<%= ticket.prioridad === 'alta' ? 'danger' : ticket.prioridad === 'critica' ? 'dark' : ticket.prioridad === 'media' ? 'warning' : 'info' %>"><%= ticket.prioridad %></span>
</p>
<p><strong>Departamento:</strong> <%= ticket.departamento_nombre || 'Sin departamento' %></p>
<p><strong>Asignado:</strong> <%= ticket.asignado_nombre || 'Sin asignar' %></p>
<p><strong>Creado:</strong> <%= ticket.created_at %></p>
</div>
</div>
</div>
<div class="col-md-9">
<div class="card mb-3">
<div class="card-header">
<strong><%= ticket.usuario_nombre %></strong>
<span class="text-muted">- <%= ticket.created_at %></span>
</div>
<div class="card-body">
<p><%= ticket.mensaje %></p>
</div>
</div>
<h5>Respuestas</h5>
<% if (respuestas.length === 0) { %>
<p class="text-muted">No hay respuestas aún</p>
<% } %>
<% respuestas.forEach(r => { %>
<div class="card mb-2 <%= r.usuario_rol === 'agent' || r.usuario_rol === 'admin' ? 'border-primary' : '' %>">
<div class="card-header">
<strong><%= r.usuario_nombre %></strong>
<span class="badge bg-<%= r.usuario_rol === 'admin' ? 'danger' : r.usuario_rol === 'agent' ? 'info' : 'secondary' %> ms-1"><%= r.usuario_rol %></span>
<span class="text-muted float-end"><%= r.created_at %></span>
</div>
<div class="card-body">
<p class="mb-0"><%= r.mensaje %></p>
</div>
</div>
<% }) %>
<div class="card mt-3">
<div class="card-header"><strong>Responder</strong></div>
<div class="card-body">
<form action="/client/ticket/<%= ticket.id %>/respond" method="POST">
<div class="mb-3">
<textarea name="mensaje" class="form-control" rows="3" required></textarea>
</div>
<button type="submit" class="btn btn-primary"><i class="fas fa-reply"></i> Responder</button>
</form>
</div>
</div>
</div>
</div>
<%- include('../partials/footer') %>