Files
help_desk/views/auth/login.ejs
T

377 lines
20 KiB
Plaintext

<%- include('../partials/header') %>
<% title = 'Iniciar Sesión'; %>
<!-- SDK de Google Identity Services -->
<script src="https://accounts.google.com/gsi/client" async defer></script>
<div class="login-container">
<div class="login-card-wrapper row g-0">
<!-- ========================================== -->
<!-- Columna Izquierda: Hero & Bot de Soporte -->
<!-- En Desktop: Panel lateral vertical con robot y features -->
<!-- En Móvil: Header banner compacto y estilizado -->
<!-- ========================================== -->
<div class="col-lg-5 login-hero-side">
<div class="login-hero-brand">
<div class="d-flex align-items-center gap-2 mb-2 mb-lg-3">
<span class="badge bg-primary bg-opacity-25 text-info border border-info border-opacity-25 px-2.5 py-1.5 rounded-pill hero-badge">
<i class="fas fa-shield-alt me-1"></i> Ecosistema Telcotronics
</span>
</div>
<h3 class="fw-bold text-white mb-1 mb-lg-2 hero-title">Help Desk & FSM</h3>
<p class="text-white-50 small mb-0 d-none d-sm-block hero-desc">Gestión centralizada de soporte, incidencias y operaciones de campo.</p>
</div>
<!-- Mascota Bot de Soporte con Animación Flotante -->
<div class="bot-avatar-wrapper text-center my-2 my-lg-4">
<img src="/img/bot-soporte.svg" alt="Bot de Soporte Help Desk" class="bot-avatar-img mb-1 mb-lg-3">
<div class="d-none d-lg-block">
<div class="bot-status-pill">
<span class="bot-status-dot"></span>
<span>Asistente Activo • 24/7 en línea</span>
</div>
</div>
</div>
<!-- Características Clave del Sistema (visibles en desktop >= lg) -->
<div class="d-none d-lg-block">
<div class="login-feature-item">
<div class="login-feature-icon">
<i class="fas fa-bolt"></i>
</div>
<div>Tickets y triaje inteligente en tiempo real</div>
</div>
<div class="login-feature-item">
<div class="login-feature-icon">
<i class="fas fa-map-marked-alt"></i>
</div>
<div>Despacho FSM con GPS, evidencias y firma</div>
</div>
<div class="login-feature-item">
<div class="login-feature-icon">
<i class="fas fa-building"></i>
</div>
<div>Integración nativa con SIGMA WebControl</div>
</div>
<div class="mt-4 pt-3 border-top border-white border-opacity-10 d-flex justify-content-between align-items-center text-white-50" style="font-size: 0.75rem;">
<span>soporte.sigmac.app</span>
<span>v2.0 • SIGMA Cloud</span>
</div>
</div>
</div>
<!-- ========================================== -->
<!-- Columna Derecha: Selector y Formularios -->
<!-- ========================================== -->
<div class="col-lg-7 login-form-side">
<!-- Mensajes Flash de Notificación -->
<% if (success_msg && success_msg.length > 0) { %>
<% success_msg.forEach(msg => { %>
<div class="alert alert-success alert-dismissible fade show rounded-3 shadow-sm border-0 mb-3" role="alert">
<div class="d-flex align-items-center">
<i class="fas fa-check-circle me-2 fs-5"></i>
<div><%= msg %></div>
</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<% }) %>
<% } %>
<% if (error_msg && error_msg.length > 0) { %>
<% error_msg.forEach(msg => { %>
<div class="alert alert-danger alert-dismissible fade show rounded-3 shadow-sm border-0 mb-3" role="alert">
<div class="d-flex align-items-center">
<i class="fas fa-exclamation-triangle me-2 fs-5"></i>
<div><%= msg %></div>
</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<% }) %>
<% } %>
<!-- Cabecera de Bienvenida -->
<div class="mb-3">
<div class="d-flex align-items-center gap-2 mb-1">
<img src="/img/logo.svg" alt="Help Desk" width="28" height="28" class="rounded-2 shadow-sm">
<h4 class="fw-bold text-dark mb-0 form-title">Acceso al Sistema</h4>
</div>
<p class="text-muted small mb-0 form-subtitle">Selecciona tu perfil de usuario para ingresar.</p>
</div>
<!-- Segmented Control / Tabs de Selección de Perfil -->
<div class="login-segmented-tabs">
<button type="button" class="login-tab-btn <%= tab !== 'staff' ? 'active' : '' %>" id="tabBtnClient" onclick="switchLoginTab('client')">
<i class="fas fa-user-tag text-primary"></i>
<span class="tab-label-text">Clientes SIGMA</span>
</button>
<button type="button" class="login-tab-btn <%= tab === 'staff' ? 'active staff-active' : '' %>" id="tabBtnStaff" onclick="switchLoginTab('staff')">
<i class="fas fa-user-shield text-indigo" style="color: #4f46e5;"></i>
<span class="tab-label-text">Personal Técnico</span>
</button>
</div>
<!-- ============================================================= -->
<!-- PESTAÑA 1: CLIENTES & EMPRESAS (WebControl + Redes Sociales) -->
<!-- ============================================================= -->
<div id="sectionClient" style="<%= tab === 'staff' ? 'display: none;' : '' %>">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-3 p-2 rounded-3 bg-light border border-slate-200">
<div class="client-badge-pill">
<i class="fas fa-building"></i> Clientes SIGMA
</div>
<small class="text-muted" style="font-size: 0.73rem;">Vía <strong>SIGMA WebControl</strong></small>
</div>
<form action="/login" method="POST" id="clientLoginForm">
<input type="hidden" name="login_type" value="client">
<div class="mb-3">
<label class="form-label text-secondary small fw-semibold">Correo de Cliente / Empresa</label>
<div class="input-group login-input-group">
<span class="input-group-text"><i class="fas fa-envelope"></i></span>
<input type="email" name="email" id="clientEmail" class="form-control" placeholder="tu-correo@empresa.com" required autocomplete="email">
</div>
</div>
<div class="mb-3">
<label class="form-label text-secondary small fw-semibold">Contraseña WebControl</label>
<div class="input-group login-input-group">
<span class="input-group-text"><i class="fas fa-lock"></i></span>
<input type="password" name="password" id="clientPassword" class="form-control" placeholder="••••••••" required autocomplete="current-password" style="border-top-right-radius: 0; border-bottom-right-radius: 0;">
<button class="btn btn-outline-secondary password-toggle-btn px-3" type="button" onclick="togglePassVisibility('clientPassword', 'clientPassIcon')" title="Mostrar/Ocultar contraseña">
<i class="fas fa-eye" id="clientPassIcon"></i>
</button>
</div>
</div>
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="clientRememberMe">
<label class="form-check-label text-muted small" for="clientRememberMe">Recordarme</label>
</div>
<a href="https://siax-system.net" target="_blank" class="text-decoration-none small text-primary fw-semibold">
¿Olvidaste tu contraseña?
</a>
</div>
<button type="submit" class="btn btn-login w-100 d-flex justify-content-center align-items-center shadow-sm">
<span>Ingresar con Cuenta SIGMA</span>
<i class="fas fa-arrow-right ms-2"></i>
</button>
</form>
<!-- Divisor de Social Auth -->
<div class="login-divider">
<span>O regístrate / accede con</span>
</div>
<!-- Social Auth: horizontal en tablet y desktop, vertical en móvil -->
<div class="social-auth-wrapper">
<div id="g_id_onload"
data-client_id="<%= googleClientId %>"
data-context="signin"
data-ux_mode="popup"
data-callback="handleGoogleCredentialResponse"
data-auto_prompt="false">
</div>
<div class="social-buttons-grid">
<div class="social-btn-box social-google-box">
<div class="g_id_signin w-100 d-flex justify-content-center"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="continue_with"
data-size="large"
data-logo_alignment="left">
</div>
</div>
<!-- Botón de Facebook OAuth -->
<div class="social-btn-box social-fb-box">
<button type="button" class="btn btn-social-fb d-flex align-items-center justify-content-center gap-2 shadow-sm" onclick="handleFacebookLogin()">
<i class="fab fa-facebook fs-5"></i>
<span>Continuar con Facebook</span>
</button>
</div>
</div>
</div>
<div class="text-center mt-3 pt-2">
<span class="text-muted small">¿Nueva empresa o sucursal?</span>
<a href="/register" class="text-decoration-none small text-primary fw-semibold ms-1">Crear registro institucional</a>
</div>
</div>
<!-- ============================================================= -->
<!-- PESTAÑA 2: PERSONAL TÉCNICO & STAFF (Consola Local MariaDB) -->
<!-- ============================================================= -->
<div id="sectionStaff" style="<%= tab !== 'staff' ? 'display: none;' : '' %>">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-3 p-2 rounded-3 bg-light border border-slate-200">
<div class="staff-badge-pill">
<i class="fas fa-shield-alt"></i> Consola Operativa
</div>
<small class="text-muted" style="font-size: 0.73rem;">Exclusivo <strong>Agentes & Staff</strong></small>
</div>
<form action="/login" method="POST" id="staffLoginForm">
<input type="hidden" name="login_type" value="staff">
<div class="mb-3">
<label class="form-label text-secondary small fw-semibold">Correo de Operaciones</label>
<div class="input-group login-input-group">
<span class="input-group-text"><i class="fas fa-id-badge"></i></span>
<input type="email" name="email" id="staffEmail" class="form-control" placeholder="agente@helpdesk.com" required autocomplete="email">
</div>
</div>
<div class="mb-3">
<label class="form-label text-secondary small fw-semibold">Contraseña Interna</label>
<div class="input-group login-input-group">
<span class="input-group-text"><i class="fas fa-key"></i></span>
<input type="password" name="password" id="staffPassword" class="form-control" placeholder="••••••••" required autocomplete="current-password" style="border-top-right-radius: 0; border-bottom-right-radius: 0;">
<button class="btn btn-outline-secondary password-toggle-btn px-3" type="button" onclick="togglePassVisibility('staffPassword', 'staffPassIcon')" title="Mostrar/Ocultar contraseña">
<i class="fas fa-eye" id="staffPassIcon"></i>
</button>
</div>
</div>
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="staffRememberMe">
<label class="form-check-label text-muted small" for="staffRememberMe">Recordarme</label>
</div>
<span class="text-muted small" style="font-size: 0.75rem;">help_desk.users DB</span>
</div>
<button type="submit" class="btn btn-login w-100 d-flex justify-content-center align-items-center shadow-sm" style="background: linear-gradient(135deg, #4f46e5 0%, #2563eb 100%);">
<span>Acceder a Consola Técnica</span>
<i class="fas fa-shield-alt ms-2"></i>
</button>
</form>
</div>
<!-- Pie de Soporte -->
<div class="text-center mt-3 pt-2">
<small class="text-muted" style="font-size: 0.78rem;">
¿Problemas de conectividad? <a href="mailto:soporte@telcotronics.com" class="text-decoration-none text-secondary fw-semibold">NOC Telcotronics</a>
</small>
</div>
</div>
</div>
</div>
<script>
// Conmutador interactivo de pestañas
function switchLoginTab(tab) {
const btnClient = document.getElementById('tabBtnClient');
const btnStaff = document.getElementById('tabBtnStaff');
const secClient = document.getElementById('sectionClient');
const secStaff = document.getElementById('sectionStaff');
if (tab === 'staff') {
btnClient.classList.remove('active');
btnStaff.classList.add('active', 'staff-active');
secClient.style.display = 'none';
secStaff.style.display = 'block';
window.history.replaceState(null, null, '/login?tab=staff');
} else {
btnStaff.classList.remove('active', 'staff-active');
btnClient.classList.add('active');
secStaff.style.display = 'none';
secClient.style.display = 'block';
window.history.replaceState(null, null, '/login?tab=client');
}
}
// Toggle de visibilidad para contraseña
function togglePassVisibility(inputId, iconId) {
const input = document.getElementById(inputId);
const icon = document.getElementById(iconId);
if (input && icon) {
if (input.type === 'password') {
input.type = 'text';
icon.classList.remove('fa-eye');
icon.classList.add('fa-eye-slash');
} else {
input.type = 'password';
icon.classList.remove('fa-eye-slash');
icon.classList.add('fa-eye');
}
}
}
// Callback de Google Identity Services
window.handleGoogleCredentialResponse = async function(response) {
if (!response || !response.credential) return;
try {
const res = await fetch('/auth/google', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ credential: response.credential })
});
const data = await res.json();
if (data.success) {
window.location.href = data.redirect || '/client/dashboard';
} else {
alert(data.message || 'No fue posible iniciar sesión con Google');
}
} catch (err) {
console.error('Error Google Sign-In:', err);
alert('Error al conectar con el servidor de autenticación');
}
};
// Callback de Facebook Login
window.handleFacebookLogin = function() {
if (typeof FB !== 'undefined') {
FB.login(function(response) {
if (response.authResponse && response.authResponse.accessToken) {
fetch('/auth/facebook', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ accessToken: response.authResponse.accessToken })
})
.then(r => r.json())
.then(data => {
if (data.success) {
window.location.href = data.redirect || '/client/dashboard';
} else {
alert(data.message || 'Error con Facebook Login');
}
})
.catch(err => {
console.error('Error FB:', err);
alert('Error al verificar credenciales con Facebook');
});
}
}, { scope: 'public_profile,email' });
} else {
const email = prompt('Inicio con Facebook:\nIngresa tu correo para simular el acceso social o usa Google Sign-In:');
if (email && email.includes('@')) {
fetch('/auth/facebook', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ accessToken: 'mock_fb_token_' + btoa(email) })
})
.then(r => r.json())
.then(data => {
if (data.success) {
window.location.href = data.redirect || '/client/dashboard';
} else {
alert('Para inicio social directo en este entorno, por favor utiliza "Continuar con Google".');
}
})
.catch(() => {
alert('Por favor utiliza el botón de "Continuar con Google" o tus credenciales WebControl.');
});
}
}
};
</script>
<%- include('../partials/footer') %>