479 lines
23 KiB
PHP
479 lines
23 KiB
PHP
<?php
|
|
include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|
|
|
$dos_factores_estado = obtenerEstadoDosFactores();
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>👮 Opciones de Seguridad</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/2.1.2/sweetalert.min.js"></script>
|
|
<!-- SweetAlert2 -->
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
<!-- Font Awesome -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
|
<!-- Animate.css para animaciones adicionales -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
|
|
<style>
|
|
body { font-family: 'Segoe UI', sans-serif; background-color: #f4f6f9; }
|
|
.sidebar { width: 220px; height: 100vh; background-color: #343a40; position: fixed; top: 0; left: 0; padding-top: 56px; z-index: 1040; }
|
|
.sidebar .nav-link { font-weight: bold; color: white; transition: all 0.3s ease; }
|
|
.sidebar .nav-link:hover,
|
|
.sidebar .nav-link.active { background-color: #495057; color: #fff; }
|
|
.content { margin-top: 56px; padding: 40px 20px; position: relative; z-index: 1; background-color: #f4f6f9; transition: margin-left 0.3s ease; }
|
|
.navbar { position: fixed; top: 0; width: 100%; z-index: 1050; }
|
|
/* A partir de dispositivos medianos (>=768px), deja espacio lateral */
|
|
@media (min-width: 768px) { .content { margin-left: 250px; /* Ancho del sidebar */ } }
|
|
/* En móviles, sin margen lateral */
|
|
@media (max-width: 767.98px) {
|
|
.content { margin-left: 0; }
|
|
.sidebar .nav-link { font-weight: normal; color: #343a40; background-color: transparent; }
|
|
.sidebar .nav-link:hover,
|
|
.sidebar .nav-link.active { background-color: #e9ecef; color: #212529; }
|
|
}
|
|
.hide { display: none !important; }
|
|
.card { border-radius: 12px; }
|
|
.btn i { font-family: "Font Awesome 6 Free", sans-serif; margin-right: 0.5rem; }
|
|
.btn { font-family: 'Segoe UI', sans-serif; }
|
|
/* Fix para z-index del modal */
|
|
.modal { z-index: 9999 !important; }
|
|
.modal-backdrop { z-index: 9998 !important; }
|
|
/* Estilos adicionales para mejorar la apariencia del modal */
|
|
.modal-content { border: none; border-radius: 15px; overflow: hidden; }
|
|
.modal-header { border-bottom: none; padding: 20px 25px 15px; }
|
|
.modal-body { padding: 25px; }
|
|
.modal-footer { border-top: none; padding: 15px 25px 25px; }
|
|
.btn { border-radius: 8px; padding: 10px 20px; font-weight: 500; }
|
|
.alert-info { background-color: #e3f2fd; border-color: #bbdefb; color: #1565c0; border-radius: 8px; }
|
|
/* Animación suave para el modal */
|
|
.modal.fade .modal-dialog { transform: translate(0, -50px); transition: transform 0.3s ease-out; }
|
|
.modal.show .modal-dialog { transform: translate(0, 0); }
|
|
/* Animaciones personalizadas */
|
|
.card-hover { transition: all 0.3s ease; cursor: pointer; }
|
|
.card-hover:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15) !important; }
|
|
.btn-pulse { animation: pulse 2s infinite; }
|
|
@keyframes pulse {
|
|
0% { transform: scale(1); }
|
|
50% { transform: scale(1.05); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
.fade-in-up { animation: fadeInUp 0.8s ease-out; }
|
|
@keyframes fadeInUp {
|
|
from { opacity: 0; transform: translateY(30px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
/* Responsive animations */
|
|
@media (max-width: 768px) { .card-hover:hover { transform: translateY(-4px) scale(1.01); } }
|
|
/* Efecto de glow para elementos activos */
|
|
.btn.active { box-shadow: 0 0 20px rgba(var(--bs-primary-rgb), 0.5); }
|
|
/* Animación para el título */
|
|
.title-glow { text-shadow: 0 0 10px rgba(0, 123, 255, 0.3); }
|
|
/* Efecto para botones */
|
|
.btn-animated { transition: all 0.3s ease; position: relative; overflow: hidden; }
|
|
.btn-animated:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); }
|
|
.btn-animated::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
|
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; }
|
|
.btn-animated:hover::before { left: 100%; }
|
|
/* ========== ANIMACIONES PARA INPUTS ========== */
|
|
/* 1. Animación al hacer focus */
|
|
.form-control { transition: all 0.3s ease; border: 2px solid #dee2e6; position: relative; }
|
|
.form-control:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25), 0 0 20px rgba(13, 110, 253, 0.3); transform: translateY(-2px); }
|
|
/* 2. Animación al escribir */
|
|
.form-control:not(:placeholder-shown) { border-color: #198754; background-color: #f8fff9; }
|
|
/* 3. Efecto de shake en validación */
|
|
.form-control.shake { animation: shake 0.5s ease-in-out; }
|
|
@keyframes shake {
|
|
0%, 100% { transform: translateX(0); }
|
|
25% { transform: translateX(-5px); }
|
|
75% { transform: translateX(5px); }
|
|
}
|
|
/* 4. Floating labels con animación */
|
|
.form-floating-custom { position: relative; margin-bottom: 1.5rem; }
|
|
.form-floating-custom .form-control { padding: 1rem 0.75rem 0.5rem 0.75rem; height: auto; }
|
|
.form-floating-custom .form-label { position: absolute; top: 0.75rem; left: 0.75rem; transition: all 0.3s ease; pointer-events: none; color: #6c757d; z-index: 2; }
|
|
.form-floating-custom .form-control:focus ~ .form-label,
|
|
.form-floating-custom .form-control:not(:placeholder-shown) ~ .form-label { top: 0.25rem; font-size: 0.75rem; color: #0d6efd; font-weight: 600; }
|
|
/* 5. Efecto de pulso en hover */
|
|
.input-pulse:hover { animation: inputPulse 0.6s ease-in-out; }
|
|
@keyframes inputPulse {
|
|
0% { transform: scale(1); }
|
|
50% { transform: scale(1.02); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
/* 6. Gradiente animado en el borde */
|
|
.input-gradient { position: relative; overflow: hidden; }
|
|
.input-gradient::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
|
|
background: linear-gradient(90deg, transparent, rgba(13, 110, 253, 0.3), transparent); transition: left 0.5s; pointer-events: none; z-index: 1; }
|
|
.input-gradient:focus::before { left: 100%; }
|
|
/* 7. Efecto de brillo en validación exitosa */
|
|
.form-control.valid { border-color: #198754; background: linear-gradient(45deg, #fff, #f8fff9); animation: successGlow 1s ease-in-out; }
|
|
@keyframes successGlow {
|
|
0% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
|
|
50% { box-shadow: 0 0 20px rgba(25, 135, 84, 0.8); }
|
|
100% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
|
|
}
|
|
/* 8. Typing effect simulation */
|
|
.input-typing { position: relative; }
|
|
.input-typing::after { content: '|'; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); opacity: 0; animation: blink 1s infinite; color: #0d6efd; }
|
|
.input-typing:focus::after { opacity: 1; }
|
|
@keyframes blink {
|
|
0%, 50% { opacity: 1; }
|
|
51%, 100% { opacity: 0; }
|
|
}
|
|
/* 9. Efecto de ondas */
|
|
.input-ripple { position: relative; overflow: hidden; }
|
|
.input-ripple::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(13, 110, 253, 0.2);
|
|
border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; pointer-events: none; }
|
|
.input-ripple:focus::before { width: 300px; height: 300px; }
|
|
/* 10. Slide-up animation para los campos */
|
|
.form-group-animated { opacity: 0; transform: translateY(20px); animation: slideUp 0.6s ease-out forwards; }
|
|
.form-group-animated:nth-child(1) { animation-delay: 0.1s; }
|
|
.form-group-animated:nth-child(2) { animation-delay: 0.2s; }
|
|
.form-group-animated:nth-child(3) { animation-delay: 0.3s; }
|
|
.form-group-animated:nth-child(4) { animation-delay: 0.4s; }
|
|
.form-group-animated:nth-child(5) { animation-delay: 0.5s; }
|
|
.form-group-animated:nth-child(6) { animation-delay: 0.6s; }
|
|
.form-group-animated:nth-child(7) { animation-delay: 0.7s; }
|
|
.form-group-animated:nth-child(8) { animation-delay: 0.8s; }
|
|
@keyframes slideUp { to { opacity: 1; transform: translateY(0); } }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="content">
|
|
<h4 class="mb-4 animate__animated animate__fadeInDown title-glow">👮 Opciones de Seguridad</h4>
|
|
<div class="row g-3">
|
|
|
|
<!-- Autenticacin de dos factores -->
|
|
<div class="col-md-6 animate__animated animate__fadeInUp" style="animation-delay: 0.1s;">
|
|
<div class="card shadow-sm p-3 card-hover position-relative h-100">
|
|
<div class="card-body p-0 d-flex flex-column">
|
|
<h4 class="mb-4 text-dark">Autenticación de dos factores</h4>
|
|
<p class="text-muted small flex-grow-1 mb-4">Al activar esta funcionalidad, blindas el acceso a tu cuenta, recibiras un código de acceso a tu correo electrónico para confirmar identidad.</p>
|
|
<form method="post" action="/IMPORTADORES/seguridad/autenticacionDosFactores">
|
|
<div class="form-check form-switch mb-3">
|
|
<input type="checkbox" name="dos_factores" id="dos_factores" class="form-check-input"
|
|
<?php echo ($dos_factores_estado == 1) ? "checked" : ""; ?>>
|
|
<label class="form-check-label" for="dos_factores">
|
|
<?php echo ($dos_factores_estado == 1) ? "Activo" : "Inactivo"; ?>
|
|
</label>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-floppy-disk"></i>Guardar configuración</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Cambiar contraseña -->
|
|
<div class="col-md-6 animate__animated animate__fadeInUp" style="animation-delay: 0.1s;">
|
|
<div class="card shadow-sm p-3 card-hover position-relative h-100">
|
|
<div class="card-body p-0 d-flex flex-column">
|
|
<h4 class="mb-4 text-dark">Cambiar contraseña</h4>
|
|
<p class="text-muted small flex-grow-1 mb-4">Al actualizar tu contraseña, refuerzas la seguridad de tu cuenta. Te recomendamos usar una combinación de letras, números y símbolos para mayor seguridad.</p><br>
|
|
<form>
|
|
<button type="button" class="btn btn-primary btn-sm mt-2 w-40 btn-animated" data-bs-toggle="modal" data-bs-target="#modalConfirmarCambio">
|
|
<i class="fas fa-key"></i>Cambiar contraseña
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Correo adicional (extra) -->
|
|
<div class="col-md-6 animate__animated animate__fadeInUp" style="animation-delay: 0.1s;">
|
|
<div class="card shadow-sm p-3 card-hover position-relative h-100">
|
|
<div class="card-body p-0 d-flex flex-column">
|
|
<h4 class="mb-4 text-dark">Recibe notificaciones</h4>
|
|
<p class="text-muted small flex-grow-1 mb-4">Agrega un correo adicional para recibir notificaciones.</p>
|
|
<?php if (!empty($correos['correo_extra'])): ?>
|
|
<p><code><?= htmlspecialchars($correos['correo_extra']) ?></code></p>
|
|
<!-- Formulario para eliminar -->
|
|
<form method="POST" action="/IMPORTADORES/seguridad/eliminarCorreoExtra" id="form-eliminar-extra" class="mt-2 hide"></form>
|
|
<form method="POST" action="/IMPORTADORES/seguridad/modificarCorreoExtra" id="formCorreoExtra">
|
|
<div class="mb-3 form-group-animated">
|
|
<div class="form-floating-custom">
|
|
<input type="email" name="email-extra" id="email_extra" class="form-control input-pulse input-typing" placeholder=" " required>
|
|
<label for="email_extra" class="form-label">Correo adicional *</label>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex gap-2 form-group-animated">
|
|
<button type="submit" class="btn btn-success btn-sm mt-2 w-40 btn-animated">
|
|
<i class="fas fa-edit"></i>Actualizar
|
|
</button>
|
|
<button type="button" class="btn btn-danger btn-sm mt-2 w-40 btn-animated" onclick="confirmarEliminacion('extra')">
|
|
<i class="fas fa-trash"></i> Eliminar correo
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<?php else: ?>
|
|
<form method="POST" action="/IMPORTADORES/seguridad/correoExtra" id="formCorreoExtra">
|
|
<div class="mb-3 form-group-animated">
|
|
<div class="form-floating-custom">
|
|
<input type="email" name="email-extra" id="email_extra" class="form-control input-pulse input-typing" placeholder=" " required>
|
|
<label for="email_extra" class="form-label">Correo adicional *</label>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3 form-group-animated">
|
|
<button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-envelope"></i>Registrar</button>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Correo de Respaldo -->
|
|
<div class="col-md-6 animate__animated animate__fadeInUp" style="animation-delay: 0.1s;">
|
|
<div class="card shadow-sm p-3 card-hover position-relative h-100">
|
|
<div class="card-body p-0 d-flex flex-column">
|
|
<h4 class="mb-4 text-dark">Correo de respaldo</h4>
|
|
<p class="text-muted small flex-grow-1 mb-4">Agrega un correo de respaldo para reuperación de tu cuenta.</p>
|
|
<?php if (!empty($correos['correo_respaldo'])): ?>
|
|
<p><code><?= htmlspecialchars($correos['correo_respaldo']) ?></code></p>
|
|
<!-- Formulario para eliminar -->
|
|
<form method="POST" action="/IMPORTADORES/seguridad/eliminarCorreoRespaldo" id="form-eliminar-respaldo" class="mt-2 hide"></form>
|
|
<form method="POST" action="/IMPORTADORES/seguridad/modificarCorreoRespaldo" id="formCorreoRespaldo">
|
|
<div class="mb-3 form-group-animated">
|
|
<div class="form-floating-custom">
|
|
<input type="email" name="email-respaldo" id="email_respaldo" class="form-control input-pulse input-typing" value="" placeholder=" " required>
|
|
<label for="email_respaldo" class="form-label">Correo de respaldo *</label>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex gap-2 form-group-animated">
|
|
<button type="submit" class="btn btn-success btn-sm mt-2 w-40 btn-animated">
|
|
<i class="fas fa-edit"></i>Actualizar
|
|
</button>
|
|
<button type="button" class="btn btn-danger btn-sm mt-2 w-40 btn-animated" onclick="confirmarEliminacion('respaldo')">
|
|
<i class="fas fa-trash"></i> Eliminar correo
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<?php else: ?>
|
|
<form method="POST" action="/IMPORTADORES/seguridad/correoRespaldo" id="formCorreoRespaldo">
|
|
<div class="mb-3 form-group-animated">
|
|
<div class="form-floating-custom">
|
|
<input type="email" name="email-respaldo" id="email_respaldo" class="form-control input-pulse input-typing" placeholder=" " required>
|
|
<label for="email_respaldo" class="form-label">Correo de respaldo *</label>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3 form-group-animated">
|
|
<button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-envelope"></i>Registrar</button>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal de confirmación -->
|
|
<div class="modal fade" id="modalConfirmarCambio" tabindex="-1" aria-labelledby="modalConfirmarCambioLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title" id="modalConfirmarCambioLabel">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
Confirmar cambio de contraseña
|
|
</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body text-center">
|
|
<div class="mb-3">
|
|
<i class="fas fa-shield-alt text-warning" style="font-size: 3rem;"></i>
|
|
</div>
|
|
<h5 class="mb-3">¿Estás seguro de cambiar tu contraseña?</h5>
|
|
<p class="text-muted">
|
|
Se enviará un código de verificación a tu correo electrónico para confirmar el cambio de contraseña.
|
|
</p>
|
|
<div class="alert alert-info">
|
|
<small>
|
|
<i class="fas fa-info-circle me-1"></i>
|
|
El código expirará en 10 minutos
|
|
</small>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer justify-content-center">
|
|
<button type="button" class="btn btn-secondary btn-sm mt-2 w-40 btn-animated" data-bs-dismiss="modal">
|
|
<i class="fas fa-times me-1"></i>
|
|
Cancelar
|
|
</button>
|
|
<form method="POST" action="/IMPORTADORES/reset/enviarCodigoInterno" style="display: inline;">
|
|
<button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated">
|
|
<i class="fas fa-check me-1"></i>
|
|
Sí, estoy seguro
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const chk = document.getElementById('dos_factores');
|
|
const label = document.querySelector('label[for="dos_factores"]');
|
|
|
|
chk.addEventListener('change', () => { label.textContent = chk.checked ? 'Activo' : 'Inactivo'; });
|
|
|
|
// Función para confirmar eliminación con SweetAlert2
|
|
function confirmarEliminacion(tipo) {
|
|
const mensajes = {
|
|
'extra': {
|
|
titulo: '¿Eliminar correo adicional?',
|
|
texto: 'No podrás recibir notificaciones en este correo.',
|
|
confirmado: 'Correo adicional eliminado',
|
|
form: 'form-eliminar-extra'
|
|
},
|
|
'respaldo': {
|
|
titulo: '¿Eliminar correo de respaldo?',
|
|
texto: 'No podrás recuperar tu cuenta con este correo.',
|
|
confirmado: 'Correo de respaldo eliminado',
|
|
form: 'form-eliminar-respaldo'
|
|
}
|
|
};
|
|
|
|
const config = mensajes[tipo];
|
|
|
|
Swal.fire({
|
|
title: config.titulo,
|
|
text: config.texto,
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#dc3545',
|
|
cancelButtonColor: '#6c757d',
|
|
confirmButtonText: 'Sí, eliminar',
|
|
cancelButtonText: 'Cancelar',
|
|
reverseButtons: true
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// Mostrar mensaje de éxito
|
|
Swal.fire({
|
|
title: '¡Eliminado!',
|
|
text: config.confirmado,
|
|
icon: 'success',
|
|
timer: 1500,
|
|
showConfirmButton: false
|
|
}).then(() => {
|
|
// Enviar el formulario después del mensaje
|
|
document.getElementById(config.form).submit();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Versión simplificada sin el mensaje de confirmación extra
|
|
function confirmarEliminacionSimple(tipo) {
|
|
const mensajes = {
|
|
'extra': {
|
|
titulo: '¿Eliminar correo adicional?',
|
|
texto: 'No podrás recibir notificaciones en este correo.',
|
|
form: 'form-eliminar-extra'
|
|
},
|
|
'respaldo': {
|
|
titulo: '¿Eliminar correo de respaldo?',
|
|
texto: 'No podrás recuperar tu cuenta con este correo.',
|
|
form: 'form-eliminar-respaldo'
|
|
}
|
|
};
|
|
|
|
const config = mensajes[tipo];
|
|
|
|
Swal.fire({
|
|
title: config.titulo,
|
|
text: config.texto,
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#dc3545',
|
|
cancelButtonColor: '#6c757d',
|
|
confirmButtonText: 'Sí, eliminar',
|
|
cancelButtonText: 'Cancelar',
|
|
reverseButtons: true
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// Enviar el formulario directamente
|
|
document.getElementById(config.form).submit();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Limpiar y consolidar los event listeners
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Event listener único para correo extra
|
|
const formCorreoExtra = document.getElementById('formCorreoExtra');
|
|
if (formCorreoExtra) {
|
|
formCorreoExtra.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const correo_extra = document.getElementById('email_extra').value.trim();
|
|
const correoRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
|
|
if (!correoRegex.test(correo_extra)) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Correo inválido',
|
|
text: 'No es una dirección de correo válida.',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
document.getElementById('email_extra').focus();
|
|
return;
|
|
}
|
|
|
|
// Si la validación pasa, enviar el formulario
|
|
this.submit();
|
|
});
|
|
}
|
|
|
|
// Event listener único para correo de respaldo
|
|
const formCorreoRespaldo = document.getElementById('formCorreoRespaldo');
|
|
if (formCorreoRespaldo) {
|
|
formCorreoRespaldo.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const correo_respaldo = document.getElementById('email_respaldo').value.trim();
|
|
const correoRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
|
|
if (!correoRegex.test(correo_respaldo)) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Correo inválido',
|
|
text: 'No es una dirección de correo válida.',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
document.getElementById('email_respaldo').focus();
|
|
return;
|
|
}
|
|
|
|
// Si la validación pasa, enviar el formulario
|
|
this.submit();
|
|
});
|
|
}
|
|
|
|
// Animaciones de validación
|
|
const inputs = document.querySelectorAll('.form-control');
|
|
inputs.forEach(input => {
|
|
input.addEventListener('input', function() {
|
|
if (this.checkValidity()) {
|
|
this.classList.remove('shake');
|
|
this.classList.add('valid');
|
|
} else {
|
|
this.classList.remove('valid');
|
|
}
|
|
});
|
|
|
|
input.addEventListener('invalid', function() {
|
|
this.classList.add('shake');
|
|
setTimeout(() => {
|
|
this.classList.remove('shake');
|
|
}, 500);
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|