Carpeta js

This commit is contained in:
Axel Axt
2026-08-04 19:45:50 -03:00
parent 8bd815f888
commit 15281e9244
34 changed files with 4417 additions and 0 deletions
+204
View File
@@ -0,0 +1,204 @@
document.addEventListener("DOMContentLoaded", () => {
// Mostrar errores del servidor si existen
if (serverErrors.length > 0) mostrarErrores(serverErrors);
if (serverSuccess.length > 0) mostrarSuccess(serverSuccess);
const form = document.getElementById("form-login");
const usuarioInput = document.querySelector("input[name='usuario']");
const passInput = document.querySelector("input[name='password']");
if (!form || !usuarioInput || !passInput) return;
// Protección básica de intentos (localStorage)
function verificarIntentos() {
const ahora = Date.now();
const intentosData = JSON.parse(localStorage.getItem("login_intentos")) || { c: 0, t: ahora };
if (ahora - intentosData.t > 60000) {
intentosData.c = 0;
intentosData.t = ahora;
}
localStorage.setItem("login_intentos", JSON.stringify(intentosData));
return intentosData;
}
// Funciones utilitarias
function isEmpty(value) {
return !value || value.trim() === '';
}
function hasNoSpaces(value) {
return !value.includes(' ');
}
function isValidUsername(value) {
return /^(?=.*[a-zA-Z])(?!.*[._]{2})[a-zA-Z0-9._]{5,30}$/.test(value);
}
function isValidPassword(value) {
return /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,}$/.test(value);
}
form.addEventListener("submit", (e) => {
let errores = [];
const usuario = usuarioInput.value.trim();
const password = passInput.value.trim();
const intentos = verificarIntentos();
usuarioInput.classList.remove("is-invalid");
passInput.classList.remove("is-invalid");
// INTENTOS (se verifica primero para cortar rápido)
if (intentos.c >= 3) {
e.preventDefault();
mostrarErrores(["Demasiados intentos. Espere 1 minuto antes de volver a intentar."]);
return;
}
// USUARIO
if (isEmpty(usuario)) {
errores.push("El usuario es obligatorio.");
usuarioInput.classList.add("is-invalid");
} else if (!isValidUsername(usuario)) {
errores.push("El usuario debe tener 530 caracteres, incluir al menos una letra y solo usar letras, números, puntos o guiónes bajos no consecutivos.");
usuarioInput.classList.add("is-invalid");
}
// PASSWORD
if (isEmpty(password)) {
errores.push("La contraseña es obligatoria.");
passInput.classList.add("is-invalid");
} else if (!hasNoSpaces(password)) {
errores.push("La contraseña no puede contener espacios.");
passInput.classList.add("is-invalid");
} else if (!isValidPassword(password)) {
errores.push("La contraseña debe tener al menos una mayúscula, una minúscula y un número, y mínimo 6 caracteres.");
passInput.classList.add("is-invalid");
}
if (errores.length > 0) {
e.preventDefault();
mostrarErrores(errores);
intentos.c++;
localStorage.setItem("login_intentos", JSON.stringify(intentos));
return;
}
localStorage.removeItem("login_intentos");
});
// FUNCIÓN PARA MOSTRAR ERRORES
function mostrarErrores(errores) {
// Buscar si hay un toast previo
const viejo = document.getElementById("toastErrores");
// Si existe, se elimina (evita duplicados)
if (viejo) viejo.remove();
// Crea el contenedor del toast
const toast = document.createElement("div");
// Se le asigna ID para identificarlo
toast.id = "toastErrores";
// Clases de estilo (Bootstrap + CSS)
toast.className = "toast-flotante alert alert-danger";
// Inserta el contenido dinámico (lista de errores)
toast.innerHTML = `
<strong>Se encontraron errores:</strong>
<ul class="mb-0 mt-2">
${errores.map(e => `<li>${e}</li>`).join("")} <!-- convierte array a <li> -->
</ul>
`;
// Agrega el toast al body (lo hace visible)
document.body.appendChild(toast);
// Auto-cierre
setTimeout(() => {
// Agrega clase para animación de salida (CSS)
toast.classList.add("toast-out");
// Elimina el elemento después de la animación
setTimeout(() => {
toast.remove(); // Elimina el DOM
}, 350);
}, 5000); // Visible durante 5 segundos
}
// FUNCIÓN PARA MOSTRAR SUCCESS
function mostrarSuccess(mensajes) {
// Elimina toast previo de éxito si existe
const viejo = document.getElementById("toastSuccess");
if (viejo) viejo.remove();
// Crea el contenedor del toast
const toast = document.createElement("div");
// Se le asigna ID único
toast.id = "toastSuccess";
// Estilo
toast.className = "toast-flotante alert alert-success";
// Inserta mensajes dinámicos
toast.innerHTML = `
<strong>Mensajes de éxito:</strong>
<ul class="mb-0 mt-2">
${mensajes.map(m => `<li>${m}</li>`).join("")}
</ul>
`;
// Agrega al DOM
document.body.appendChild(toast);
// Auto-cierre a los 5 segundos
setTimeout(() => {
// Animación de salida
toast.classList.add("toast-out");
// Eliminación final
setTimeout(() => {
toast.remove();
}, 350);
}, 5000);
}
});