feat(ui): rediseñar pantalla de login con mascota bot de soporte animada y acceso rapido
This commit is contained in:
@@ -54,3 +54,198 @@ main {
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==============================================================================
|
||||||
|
Login Page Modern Styling & Support Bot Mascot
|
||||||
|
============================================================================== */
|
||||||
|
.login-container {
|
||||||
|
min-height: calc(100vh - 120px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2.5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card-wrapper {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.18), 0 0 0 1px rgba(226, 232, 240, 0.8);
|
||||||
|
max-width: 980px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-hero-side {
|
||||||
|
background: linear-gradient(135deg, #070e20 0%, #0f2b6b 45%, #0284c7 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 3rem 2.5rem;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-hero-side::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -20%;
|
||||||
|
left: -20%;
|
||||||
|
width: 140%;
|
||||||
|
height: 140%;
|
||||||
|
background: radial-gradient(circle at 30% 30%, rgba(56, 189, 248, 0.16) 0%, transparent 60%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-avatar-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 1.25rem 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-avatar-img {
|
||||||
|
width: 145px;
|
||||||
|
height: 145px;
|
||||||
|
filter: drop-shadow(0 16px 24px rgba(2, 6, 23, 0.5));
|
||||||
|
animation: floatBot 4s ease-in-out infinite;
|
||||||
|
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-avatar-img:hover {
|
||||||
|
transform: scale(1.08) rotate(-3deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes floatBot {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-status-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: rgba(15, 23, 42, 0.65);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
border: 1px solid rgba(56, 189, 248, 0.3);
|
||||||
|
border-radius: 9999px;
|
||||||
|
padding: 0.35rem 0.85rem;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bot-status-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #10b981;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 10px #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-feature-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #cbd5e1;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-feature-icon {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(56, 189, 248, 0.15);
|
||||||
|
border: 1px solid rgba(56, 189, 248, 0.3);
|
||||||
|
color: #38bdf8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form-side {
|
||||||
|
padding: 3.5rem 3rem;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-input-group .input-group-text {
|
||||||
|
background-color: #f8fafc;
|
||||||
|
border-color: #cbd5e1;
|
||||||
|
color: #64748b;
|
||||||
|
border-top-left-radius: 12px;
|
||||||
|
border-bottom-left-radius: 12px;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-input-group .form-control {
|
||||||
|
border-color: #cbd5e1;
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
border-bottom-right-radius: 12px;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-input-group .form-control:focus {
|
||||||
|
border-color: #0284c7;
|
||||||
|
box-shadow: 0 0 0 3px rgba(2, 132, 199, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-toggle-btn {
|
||||||
|
border-color: #cbd5e1;
|
||||||
|
background-color: #f8fafc;
|
||||||
|
color: #64748b;
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
border-bottom-right-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-toggle-btn:hover {
|
||||||
|
color: #0f172a;
|
||||||
|
background-color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-login {
|
||||||
|
background: linear-gradient(135deg, #0284c7 0%, #2563eb 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #ffffff;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-login:hover {
|
||||||
|
background: linear-gradient(135deg, #0369a1 0%, #1d4ed8 100%);
|
||||||
|
box-shadow: 0 10px 20px -5px rgba(37, 99, 235, 0.4);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-account-chip {
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.4rem 0.75rem;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #475569;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-account-chip:hover {
|
||||||
|
background: #e0f2fe;
|
||||||
|
border-color: #bae6fd;
|
||||||
|
color: #0369a1;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,165 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
|
||||||
|
<defs>
|
||||||
|
<!-- Background Soft Glow Gradient -->
|
||||||
|
<radialGradient id="haloGlow" cx="50%" cy="50%" r="50%">
|
||||||
|
<stop offset="0%" stop-color="#38bdf8" stop-opacity="0.35" />
|
||||||
|
<stop offset="60%" stop-color="#0284c7" stop-opacity="0.1" />
|
||||||
|
<stop offset="100%" stop-color="#0284c7" stop-opacity="0" />
|
||||||
|
</radialGradient>
|
||||||
|
|
||||||
|
<!-- Bot Body Platinum Gradient -->
|
||||||
|
<linearGradient id="bodyGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#ffffff" />
|
||||||
|
<stop offset="50%" stop-color="#f8fafc" />
|
||||||
|
<stop offset="100%" stop-color="#cbd5e1" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Dark Glass Visor Screen -->
|
||||||
|
<linearGradient id="visorGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#0f172a" />
|
||||||
|
<stop offset="100%" stop-color="#1e293b" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Cyan Glow Gradient for Eyes and Accents -->
|
||||||
|
<linearGradient id="cyanGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#38bdf8" />
|
||||||
|
<stop offset="100%" stop-color="#0284c7" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Headset Band Gradient (Metallic Telcotronics Blue) -->
|
||||||
|
<linearGradient id="headsetGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#1e40af" />
|
||||||
|
<stop offset="50%" stop-color="#0284c7" />
|
||||||
|
<stop offset="100%" stop-color="#0369a1" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Status LED Gradient -->
|
||||||
|
<linearGradient id="statusLed" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#4ade80" />
|
||||||
|
<stop offset="100%" stop-color="#10b981" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Universal Drop Shadow (SVG 1.1) -->
|
||||||
|
<filter id="botShadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="12" result="blur" />
|
||||||
|
<feOffset dx="0" dy="16" result="offset" />
|
||||||
|
<feComponentTransfer in="offset" result="shadowAlpha">
|
||||||
|
<feFuncA type="linear" slope="0.3" />
|
||||||
|
</feComponentTransfer>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="shadowAlpha" />
|
||||||
|
<feMergeNode in="SourceGraphic" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<!-- Neon Eyes Glow Filter -->
|
||||||
|
<filter id="neonGlow" x="-30%" y="-30%" width="160%" height="160%">
|
||||||
|
<feGaussianBlur stdDeviation="6" result="blur" />
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="blur" />
|
||||||
|
<feMergeNode in="SourceGraphic" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Ambient Backdrop Halo -->
|
||||||
|
<circle cx="256" cy="256" r="230" fill="url(#haloGlow)" />
|
||||||
|
|
||||||
|
<g filter="url(#botShadow)">
|
||||||
|
<!-- Antenna Signal Waves -->
|
||||||
|
<path d="M 230 40 C 238 32, 274 32, 282 40" fill="none" stroke="#38bdf8" stroke-width="4" stroke-linecap="round" opacity="0.6" />
|
||||||
|
<path d="M 218 26 C 232 12, 280 12, 294 26" fill="none" stroke="#38bdf8" stroke-width="4" stroke-linecap="round" opacity="0.4" />
|
||||||
|
|
||||||
|
<!-- Antenna Stem & Glowing Ball -->
|
||||||
|
<rect x="251" y="48" width="10" height="42" rx="5" fill="url(#headsetGrad)" />
|
||||||
|
<circle cx="256" cy="46" r="14" fill="url(#cyanGrad)" filter="url(#neonGlow)" />
|
||||||
|
<circle cx="256" cy="46" r="6" fill="#ffffff" />
|
||||||
|
|
||||||
|
<!-- Bot Torso / Shoulder Collar (Base) -->
|
||||||
|
<path d="M 170 380
|
||||||
|
C 170 350, 342 350, 342 380
|
||||||
|
L 375 460
|
||||||
|
C 375 480, 137 480, 137 460
|
||||||
|
Z"
|
||||||
|
fill="url(#bodyGrad)"
|
||||||
|
stroke="#cbd5e1"
|
||||||
|
stroke-width="3" />
|
||||||
|
|
||||||
|
<!-- Chest Shield / Tie Detail -->
|
||||||
|
<path d="M 236 380 L 276 380 L 268 435 L 256 448 L 244 435 Z" fill="url(#headsetGrad)" />
|
||||||
|
<circle cx="256" cy="406" r="5" fill="#38bdf8" />
|
||||||
|
|
||||||
|
<!-- Bot Head Main Chassis -->
|
||||||
|
<rect x="116" y="86" width="280" height="250" rx="90" fill="url(#bodyGrad)" stroke="#e2e8f0" stroke-width="3" />
|
||||||
|
|
||||||
|
<!-- Head Gloss Highlight (Top Reflection) -->
|
||||||
|
<path d="M 150 110 C 200 96, 312 96, 362 110 C 375 114, 380 125, 370 135 C 330 118, 182 118, 142 135 C 132 125, 137 114, 150 110 Z" fill="#ffffff" opacity="0.65" />
|
||||||
|
|
||||||
|
<!-- Visor Outer Rim -->
|
||||||
|
<rect x="144" y="126" width="224" height="156" rx="60" fill="#090d16" stroke="url(#headsetGrad)" stroke-width="4" />
|
||||||
|
|
||||||
|
<!-- Visor Inner Glass Screen -->
|
||||||
|
<rect x="150" y="132" width="212" height="144" rx="54" fill="url(#visorGrad)" />
|
||||||
|
|
||||||
|
<!-- Screen Glass Light Reflection -->
|
||||||
|
<path d="M 160 144 C 200 136, 312 136, 352 144 C 340 162, 172 162, 160 144 Z" fill="rgba(255, 255, 255, 0.12)" />
|
||||||
|
|
||||||
|
<!-- Bot Friendly Eyes (Digital Neon Glow) -->
|
||||||
|
<g filter="url(#neonGlow)">
|
||||||
|
<!-- Left Eye: Cheerful Oval -->
|
||||||
|
<ellipse cx="206" cy="195" rx="20" ry="26" fill="url(#cyanGrad)" />
|
||||||
|
<ellipse cx="202" cy="188" rx="7" ry="9" fill="#ffffff" />
|
||||||
|
<ellipse cx="212" cy="204" rx="4" ry="4" fill="#ffffff" />
|
||||||
|
|
||||||
|
<!-- Right Eye: Cheerful Oval -->
|
||||||
|
<ellipse cx="306" cy="195" rx="20" ry="26" fill="url(#cyanGrad)" />
|
||||||
|
<ellipse cx="302" cy="188" rx="7" ry="9" fill="#ffffff" />
|
||||||
|
<ellipse cx="312" cy="204" rx="4" ry="4" fill="#ffffff" />
|
||||||
|
|
||||||
|
<!-- Digital Smile Curve -->
|
||||||
|
<path d="M 232 236 C 244 250, 268 250, 280 236" fill="none" stroke="#38bdf8" stroke-width="5" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Rosy Digital Cheeks -->
|
||||||
|
<circle cx="178" cy="226" r="10" fill="#0ea5e9" opacity="0.35" />
|
||||||
|
<circle cx="334" cy="226" r="10" fill="#0ea5e9" opacity="0.35" />
|
||||||
|
|
||||||
|
<!-- Headset Over-the-Head Arch -->
|
||||||
|
<path d="M 106 200
|
||||||
|
C 106 82, 406 82, 406 200"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#headsetGrad)"
|
||||||
|
stroke-width="22"
|
||||||
|
stroke-linecap="round" />
|
||||||
|
|
||||||
|
<!-- Headset Top Cushion -->
|
||||||
|
<path d="M 180 102 C 220 86, 292 86, 332 102" fill="none" stroke="#38bdf8" stroke-width="6" stroke-linecap="round" />
|
||||||
|
|
||||||
|
<!-- Left Headphone Earpad -->
|
||||||
|
<g transform="translate(86, 175)">
|
||||||
|
<rect width="36" height="84" rx="18" fill="url(#headsetGrad)" stroke="#0284c7" stroke-width="2" />
|
||||||
|
<rect x="10" y="12" width="16" height="60" rx="8" fill="#38bdf8" opacity="0.8" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Right Headphone Earpad -->
|
||||||
|
<g transform="translate(390, 175)">
|
||||||
|
<rect width="36" height="84" rx="18" fill="url(#headsetGrad)" stroke="#0284c7" stroke-width="2" />
|
||||||
|
<rect x="10" y="12" width="16" height="60" rx="8" fill="#38bdf8" opacity="0.8" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Microphone Boom -->
|
||||||
|
<path d="M 408 240
|
||||||
|
C 408 340, 330 366, 285 366"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#headsetGrad)"
|
||||||
|
stroke-width="12"
|
||||||
|
stroke-linecap="round" />
|
||||||
|
|
||||||
|
<!-- Microphone Capsule -->
|
||||||
|
<rect x="246" y="354" width="44" height="24" rx="12" fill="url(#bodyGrad)" stroke="#94a3b8" stroke-width="2" />
|
||||||
|
<rect x="256" y="360" width="14" height="12" rx="3" fill="#0284c7" />
|
||||||
|
|
||||||
|
<!-- Online Audio Indicator LED (Green Active Pulse) -->
|
||||||
|
<circle cx="280" cy="366" r="5" fill="url(#statusLed)" filter="url(#neonGlow)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.8 KiB |
+189
-26
@@ -1,50 +1,213 @@
|
|||||||
<%- include('../partials/header') %>
|
<%- include('../partials/header') %>
|
||||||
<% title = 'Iniciar Sesión'; %>
|
<% title = 'Iniciar Sesión'; %>
|
||||||
|
|
||||||
<% if (success_msg && success_msg.length > 0) { %>
|
<div class="login-container">
|
||||||
|
<div class="login-card-wrapper row g-0">
|
||||||
|
|
||||||
|
<!-- ========================================== -->
|
||||||
|
<!-- Columna Izquierda: Hero & Bot de Soporte -->
|
||||||
|
<!-- ========================================== -->
|
||||||
|
<div class="col-lg-5 login-hero-side">
|
||||||
|
<div>
|
||||||
|
<div class="d-flex align-items-center gap-2 mb-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">
|
||||||
|
<i class="fas fa-shield-alt me-1"></i> Ecosistema Telcotronics
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="fw-bold text-white mb-2">Help Desk & FSM</h3>
|
||||||
|
<p class="text-white-50 small mb-0">Gestión inteligente de incidencias y visitas técnicas de campo en terreno.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mascota Bot de Soporte con Animación -->
|
||||||
|
<div class="bot-avatar-wrapper text-center my-4">
|
||||||
|
<img src="/img/bot-soporte.svg" alt="Bot de Soporte Help Desk" class="bot-avatar-img mb-3">
|
||||||
|
<div>
|
||||||
|
<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 -->
|
||||||
|
<div>
|
||||||
|
<div class="login-feature-item">
|
||||||
|
<div class="login-feature-icon">
|
||||||
|
<i class="fas fa-bolt"></i>
|
||||||
|
</div>
|
||||||
|
<div>Triaje digital y tickets 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>Aislamiento multi-tenant 100% seguro</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: Formulario de Login -->
|
||||||
|
<!-- ========================================== -->
|
||||||
|
<div class="col-lg-7 login-form-side">
|
||||||
|
|
||||||
|
<!-- Mensajes Flash de Notificación -->
|
||||||
|
<% if (success_msg && success_msg.length > 0) { %>
|
||||||
<% success_msg.forEach(msg => { %>
|
<% success_msg.forEach(msg => { %>
|
||||||
<div class="alert alert-success alert-dismissible fade show mt-3">
|
<div class="alert alert-success alert-dismissible fade show rounded-3 shadow-sm border-0 mb-4" role="alert">
|
||||||
<%= msg %>
|
<div class="d-flex align-items-center">
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
<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>
|
</div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (error_msg && error_msg.length > 0) { %>
|
<% if (error_msg && error_msg.length > 0) { %>
|
||||||
<% error_msg.forEach(msg => { %>
|
<% error_msg.forEach(msg => { %>
|
||||||
<div class="alert alert-danger alert-dismissible fade show mt-3">
|
<div class="alert alert-danger alert-dismissible fade show rounded-3 shadow-sm border-0 mb-4" role="alert">
|
||||||
<%= msg %>
|
<div class="d-flex align-items-center">
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
<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>
|
</div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<div class="row justify-content-center mt-5">
|
<div class="mb-4">
|
||||||
<div class="col-md-5">
|
<div class="d-flex align-items-center gap-2 mb-2">
|
||||||
<div class="card shadow">
|
<img src="/img/logo.svg" alt="Help Desk" width="32" height="32" class="rounded-2 shadow-sm">
|
||||||
<div class="card-header bg-primary text-white text-center py-3">
|
<h4 class="fw-bold text-dark mb-0">¡Bienvenido de vuelta!</h4>
|
||||||
<img src="/img/logo.svg" alt="Help Desk" width="48" height="48" class="mb-2 shadow-sm rounded-3">
|
|
||||||
<h4 class="mb-0 fw-bold">Help Desk</h4>
|
|
||||||
<small class="text-white-50">Iniciar Sesión</small>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<p class="text-muted small">Ingresa tus credenciales autorizadas para acceder a la plataforma.</p>
|
||||||
<form action="/login" method="POST">
|
</div>
|
||||||
|
|
||||||
|
<form action="/login" method="POST" id="loginForm">
|
||||||
|
|
||||||
|
<!-- Campo de Correo Electrónico -->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Email</label>
|
<label class="form-label text-secondary small fw-semibold">Correo Electrónico</label>
|
||||||
<input type="email" name="email" class="form-control" required>
|
<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="inputEmail" class="form-control" placeholder="ejemplo@helpdesk.com" required autocomplete="email">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Campo de Contraseña -->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Contraseña</label>
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<input type="password" name="password" class="form-control" required>
|
<label class="form-label text-secondary small fw-semibold">Contraseña</label>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary w-100">Ingresar</button>
|
<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="inputPassword" 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" id="togglePasswordBtn" title="Mostrar/Ocultar contraseña">
|
||||||
|
<i class="fas fa-eye" id="togglePasswordIcon"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Opciones Adicionales -->
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="rememberMe">
|
||||||
|
<label class="form-check-label text-muted small" for="rememberMe">Recordar credenciales</label>
|
||||||
|
</div>
|
||||||
|
<a href="/register" class="text-decoration-none small text-primary fw-semibold">Registrar empresa</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Botón Principal de Acceso -->
|
||||||
|
<button type="submit" class="btn btn-login w-100 d-flex justify-content-center align-items-center shadow-sm">
|
||||||
|
<span>Ingresar a la Plataforma</span>
|
||||||
|
<i class="fas fa-arrow-right ms-2"></i>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="text-center mt-3">
|
|
||||||
<a href="/register">¿No tienes cuenta? Regístrate</a>
|
<!-- Acceso Rápido / Credenciales Demo del Ecosistema -->
|
||||||
|
<div class="mt-4 pt-3 border-top">
|
||||||
|
<div class="d-flex align-items-center justify-content-between mb-2">
|
||||||
|
<span class="text-muted fw-semibold" style="font-size: 0.76rem;">
|
||||||
|
<i class="fas fa-key me-1 text-primary"></i> Acceso Rápido Demo:
|
||||||
|
</span>
|
||||||
|
<small class="text-muted" style="font-size: 0.72rem;">(1 clic para rellenar)</small>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
<span class="demo-account-chip" onclick="fillCredentials('super@helpdesk.com', '123456')">
|
||||||
|
<i class="fas fa-crown text-warning me-1"></i> Superadmin
|
||||||
|
</span>
|
||||||
|
<span class="demo-account-chip" onclick="fillCredentials('admin@helpdesk.com', '123456')">
|
||||||
|
<i class="fas fa-user-shield text-info me-1"></i> Admin
|
||||||
|
</span>
|
||||||
|
<span class="demo-account-chip" onclick="fillCredentials('agent@helpdesk.com', '123456')">
|
||||||
|
<i class="fas fa-headset text-primary me-1"></i> Agente
|
||||||
|
</span>
|
||||||
|
<span class="demo-account-chip" onclick="fillCredentials('client@helpdesk.com', '123456')">
|
||||||
|
<i class="fas fa-user text-secondary me-1"></i> Cliente
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Pie del Formulario -->
|
||||||
|
<div class="text-center mt-4">
|
||||||
|
<small class="text-muted">
|
||||||
|
¿Problemas de acceso? Contacta a <a href="mailto:soporte@telcotronics.com" class="text-decoration-none text-secondary fw-semibold">Soporte Telcotronics</a>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Toggle de visibilidad de contraseña
|
||||||
|
const togglePasswordBtn = document.getElementById('togglePasswordBtn');
|
||||||
|
const inputPassword = document.getElementById('inputPassword');
|
||||||
|
const togglePasswordIcon = document.getElementById('togglePasswordIcon');
|
||||||
|
|
||||||
|
if (togglePasswordBtn && inputPassword && togglePasswordIcon) {
|
||||||
|
togglePasswordBtn.addEventListener('click', function() {
|
||||||
|
if (inputPassword.type === 'password') {
|
||||||
|
inputPassword.type = 'text';
|
||||||
|
togglePasswordIcon.classList.remove('fa-eye');
|
||||||
|
togglePasswordIcon.classList.add('fa-eye-slash');
|
||||||
|
} else {
|
||||||
|
inputPassword.type = 'password';
|
||||||
|
togglePasswordIcon.classList.remove('fa-eye-slash');
|
||||||
|
togglePasswordIcon.classList.add('fa-eye');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para autocompletar credenciales demo
|
||||||
|
function fillCredentials(email, password) {
|
||||||
|
const emailInput = document.getElementById('inputEmail');
|
||||||
|
const passInput = document.getElementById('inputPassword');
|
||||||
|
if (emailInput && passInput) {
|
||||||
|
emailInput.value = email;
|
||||||
|
passInput.value = password;
|
||||||
|
|
||||||
|
// Efecto visual de feedback
|
||||||
|
emailInput.classList.add('is-valid');
|
||||||
|
passInput.classList.add('is-valid');
|
||||||
|
setTimeout(() => {
|
||||||
|
emailInput.classList.remove('is-valid');
|
||||||
|
passInput.classList.remove('is-valid');
|
||||||
|
}, 1200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<%- include('../partials/footer') %>
|
<%- include('../partials/footer') %>
|
||||||
|
|||||||
Reference in New Issue
Block a user