RetinAI / web /auth-login.html
ViannyCruz's picture
Update web/auth-login.html
dddaebc verified
Raw
History Blame Contribute Delete
6.08 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="favicon.ico">
<title>Login</title>
<link rel="stylesheet" href="css/simplebar.css">
<link href="https://fonts.googleapis.com/css2?family=Overpass:ital,wght@0,100;0,200;0,300;0,400;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<link rel="stylesheet" href="css/daterangepicker.css">
<link rel="stylesheet" href="css/app-light.css" id="lightTheme">
<link rel="stylesheet" href="css/app-dark.css" id="darkTheme" disabled>
<style>
.error-message {
color: #dc3545;
font-size: 0.875rem;
margin-top: 0.25rem;
display: none;
}
.is-invalid {
border-color: #dc3545 !important;
}
#loadingIndicator {
display: none;
}
</style>
</head>
<body class="dark">
<div class="wrapper vh-100">
<div class="row align-items-center h-100">
<form class="col-lg-3 col-md-4 col-10 mx-auto text-center" id="loginForm">
<a class="navbar-brand mx-auto mt-2 flex-fill text-center">
<img src="assets/images/LOGO.png" alt="Logo">
</a>
<h1 class="h6 mb-3">Iniciar Sesión</h1>
<div id="generalError" class="alert alert-danger" role="alert" style="display: none;"></div>
<div class="form-group">
<label for="inputUsername" class="sr-only">Usuario</label>
<input type="text" id="inputUsername" class="form-control form-control-lg" placeholder="Usuario" required autofocus>
<div id="usernameError" class="error-message">Usuario requerido</div>
</div>
<div class="form-group">
<label for="inputPassword" class="sr-only">Contraseña</label>
<input type="password" id="inputPassword" class="form-control form-control-lg" placeholder="Contraseña" required>
<div id="passwordError" class="error-message">Contraseña requerida</div>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" id="loginButton">
<span id="loginText">Ingresar</span>
<span id="loadingIndicator" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
</button>
<p class="mt-5 mb-3 text-muted">Sistema de Diagnóstico asistido por Inteligencia Artificial para la detección de Retinopatía Diabética</p>
</form>
</div>
</div>
<script src="js/jquery.min.js"></script>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="api.js"></script>
<script>
$(document).ready(function() {
checkCurrentUser();
loadRememberedUser();
$('#loginForm').on('submit', handleLogin);
async function checkCurrentUser() {
try {
const r = await api.getSession();
if (r && r.success) window.location.href = 'index.html';
} catch(e) {}
}
function loadRememberedUser() {
if (localStorage.getItem('rememberMe') === 'true') {
const u = localStorage.getItem('username');
if (u) $('#inputUsername').val(u);
}
}
async function handleLogin(e) {
e.preventDefault();
$('.error-message').hide();
$('#inputUsername, #inputPassword').removeClass('is-invalid');
$('#generalError').hide().removeClass('alert-success').addClass('alert-danger');
const username = $('#inputUsername').val().trim();
const password = $('#inputPassword').val().trim();
if (!username) { $('#inputUsername').addClass('is-invalid'); $('#usernameError').show(); return; }
if (!password) { $('#inputPassword').addClass('is-invalid'); $('#passwordError').show(); return; }
$('#loginText').hide(); $('#loadingIndicator').show(); $('#loginButton').prop('disabled', true);
const response = await api.login(username, password).catch(() => null);
$('#loginText').show(); $('#loadingIndicator').hide(); $('#loginButton').prop('disabled', false);
if (response && response.success) {
if ($('#rememberMe').is(':checked')) {
localStorage.setItem('rememberMe', 'true');
localStorage.setItem('username', username);
} else {
localStorage.removeItem('rememberMe');
localStorage.removeItem('username');
}
$('#generalError').removeClass('alert-danger').addClass('alert-success')
.text('¡Bienvenido! Redirigiendo...').show();
setTimeout(() => { window.location.href = 'index.html'; }, 800);
} else {
const msg = response?.message || 'Usuario o contraseña incorrectos';
$('#generalError').text(msg).show();
$('#inputUsername, #inputPassword').addClass('is-invalid');
$('#inputPassword').val('');
}
}
});
</script>
<script>
// Feather Icons: reemplaza <i data-feather="X"> con SVG inline
// Inmune a problemas de fuentes locales
function _initFeather() {
if (typeof feather !== 'undefined') feather.replace({ 'stroke-width': 1.8 });
}
document.addEventListener('DOMContentLoaded', _initFeather);
// Re-render al inyectar HTML dinámico (modals, cards, tablas)
var _fObserver = new MutationObserver(function(mutations) {
var needsRefresh = mutations.some(function(m) {
return m.addedNodes.length > 0;
});
if (needsRefresh) _initFeather();
});
document.addEventListener('DOMContentLoaded', function() {
_fObserver.observe(document.body, { childList: true, subtree: true });
});
</script>
</body>
</html>
</html>