Actualizar index.html
This commit is contained in:
373
index.html
373
index.html
@@ -54,4 +54,375 @@
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Contraseña</label>
|
||||
<input type="password" id="loginPass" required class="w
|
||||
<input type="password" id="loginPass" required class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all">
|
||||
<div class="text-right mt-1">
|
||||
<button type="button" onclick="showForgotPassword()" class="text-xs text-blue-600 hover:underline">¿Olvidaste tu contraseña?</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" id="btnLogin" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 rounded-lg transition-all shadow-lg shadow-blue-500/30">
|
||||
Entrar
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="text-center mt-4">
|
||||
<p class="text-sm text-gray-600">¿No tienes cuenta? <button onclick="showRegister()" class="text-blue-600 font-bold hover:underline">Regístrate gratis</button></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="registerForm" class="hidden space-y-5">
|
||||
<h2 class="text-2xl font-bold text-gray-800">Crear Cuenta</h2>
|
||||
<p class="text-gray-500 text-sm">Prueba IntegraRepara gratis hoy mismo.</p>
|
||||
|
||||
<form onsubmit="handleRegister(event)" class="space-y-3">
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="text-xs font-bold text-gray-600">Nombre Completo</label>
|
||||
<input type="text" id="regName" required class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs font-bold text-gray-600">DNI / CIF</label>
|
||||
<input type="text" id="regDni" required class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="text-xs font-bold text-gray-600">Teléfono (WhatsApp)</label>
|
||||
<input type="tel" id="regPhone" placeholder="+34 600..." required class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
<p class="text-xs text-gray-400 mt-1">Te enviaremos un código de verificación.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="text-xs font-bold text-gray-600">Email</label>
|
||||
<input type="email" id="regEmail" required class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="text-xs font-bold text-gray-600">Dirección</label>
|
||||
<input type="text" id="regAddress" class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="text-xs font-bold text-gray-600">Contraseña</label>
|
||||
<input type="password" id="regPass" required class="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none">
|
||||
</div>
|
||||
|
||||
<button type="submit" id="btnRegister" class="w-full bg-slate-900 hover:bg-slate-800 text-white font-bold py-3 rounded-lg transition-all">
|
||||
Registrarse y Enviar Código
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="text-center mt-2">
|
||||
<p class="text-sm text-gray-600">¿Ya tienes cuenta? <button onclick="showLogin()" class="text-blue-600 font-bold hover:underline">Entrar</button></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="verifyForm" class="hidden space-y-6 text-center fade-in">
|
||||
<div class="mx-auto w-16 h-16 bg-green-100 rounded-full flex items-center justify-center text-green-600 mb-4">
|
||||
<i data-lucide="message-square" class="w-8 h-8"></i>
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Verifica tu WhatsApp</h2>
|
||||
<p class="text-gray-500 text-sm">Hemos enviado un código de 6 dígitos a tu teléfono.</p>
|
||||
|
||||
<form onsubmit="handleVerify(event)" class="space-y-4 max-w-xs mx-auto">
|
||||
<input type="text" id="verifyCode" placeholder="123456" maxlength="6" class="w-full text-center text-3xl tracking-widest px-4 py-3 border-2 border-gray-300 rounded-xl focus:border-green-500 focus:ring-green-500 outline-none transition-all font-mono">
|
||||
|
||||
<button type="submit" id="btnVerify" class="w-full bg-green-600 hover:bg-green-700 text-white font-bold py-3 rounded-lg transition-all shadow-lg shadow-green-500/30">
|
||||
Verificar y Entrar
|
||||
</button>
|
||||
</form>
|
||||
<button onclick="showRegister()" class="text-sm text-gray-400 hover:text-gray-600 mt-4">Volver / Corregir número</button>
|
||||
</div>
|
||||
|
||||
<div id="forgotPasswordForm" class="hidden space-y-6 fade-in">
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<button onclick="showLogin()" class="text-gray-500 hover:text-gray-700"><i data-lucide="arrow-left" class="w-5 h-5"></i></button>
|
||||
<h2 class="text-2xl font-bold text-gray-800">Recuperar Acceso</h2>
|
||||
</div>
|
||||
|
||||
<div id="forgotStep1">
|
||||
<p class="text-gray-500 text-sm mb-4">Introduce tu DNI y Teléfono para verificar tu identidad.</p>
|
||||
<form onsubmit="handleForgotRequest(event)" class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">DNI / CIF</label>
|
||||
<input type="text" id="forgotDni" required class="w-full px-4 py-2 border border-gray-300 rounded-lg outline-none focus:border-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Teléfono</label>
|
||||
<input type="tel" id="forgotPhone" required class="w-full px-4 py-2 border border-gray-300 rounded-lg outline-none focus:border-blue-500">
|
||||
</div>
|
||||
<button type="submit" id="btnForgotRequest" class="w-full bg-slate-900 text-white font-bold py-3 rounded-lg hover:bg-slate-800 transition-all">
|
||||
Enviar Código de Recuperación
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="forgotStep2" class="hidden">
|
||||
<p class="text-gray-500 text-sm mb-4">Introduce el código recibido y tu nueva contraseña.</p>
|
||||
<form onsubmit="handleResetConfirm(event)" class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Código WhatsApp</label>
|
||||
<input type="text" id="forgotCode" required placeholder="123456" class="w-full text-center tracking-widest px-4 py-2 border border-gray-300 rounded-lg outline-none focus:border-green-500 font-mono text-xl">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Nueva Contraseña</label>
|
||||
<input type="password" id="forgotNewPass" required class="w-full px-4 py-2 border border-gray-300 rounded-lg outline-none focus:border-blue-500">
|
||||
</div>
|
||||
<button type="submit" id="btnResetConfirm" class="w-full bg-green-600 text-white font-bold py-3 rounded-lg hover:bg-green-700 transition-all">
|
||||
Cambiar Contraseña
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="toast" class="fixed bottom-5 right-5 bg-slate-800 text-white px-6 py-3 rounded-lg shadow-2xl transform translate-y-20 opacity-0 transition-all duration-300 z-50 flex items-center gap-3">
|
||||
<span id="toastMsg">Mensaje</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// ==========================================
|
||||
// CONFIGURACIÓN (URL DE TU API)
|
||||
// ==========================================
|
||||
const API_URL = "https://integrarepara-api.integrarepara.es";
|
||||
|
||||
// Inicializar Iconos
|
||||
lucide.createIcons();
|
||||
|
||||
// Verificar si ya está logueado
|
||||
if (localStorage.getItem('token')) {
|
||||
window.location.href = "panel.html";
|
||||
}
|
||||
|
||||
// Variables de estado
|
||||
let tempPhone = "";
|
||||
let forgotPhoneTemp = "";
|
||||
|
||||
// UI Helpers
|
||||
function hideAll() {
|
||||
// AÑADIDO: Ocultamos también el formulario de recuperar
|
||||
['loginForm', 'registerForm', 'verifyForm', 'forgotPasswordForm'].forEach(id => document.getElementById(id).classList.add('hidden'));
|
||||
}
|
||||
|
||||
function showRegister() {
|
||||
hideAll();
|
||||
document.getElementById('registerForm').classList.remove('hidden');
|
||||
document.getElementById('registerForm').classList.add('fade-in');
|
||||
}
|
||||
|
||||
function showLogin() {
|
||||
hideAll();
|
||||
document.getElementById('loginForm').classList.remove('hidden');
|
||||
document.getElementById('loginForm').classList.add('fade-in');
|
||||
}
|
||||
|
||||
function showVerify() {
|
||||
hideAll();
|
||||
document.getElementById('verifyForm').classList.remove('hidden');
|
||||
}
|
||||
|
||||
// AÑADIDO: Mostrar formulario de recuperación
|
||||
function showForgotPassword() {
|
||||
hideAll();
|
||||
document.getElementById('forgotPasswordForm').classList.remove('hidden');
|
||||
document.getElementById('forgotStep1').classList.remove('hidden');
|
||||
document.getElementById('forgotStep2').classList.add('hidden');
|
||||
}
|
||||
|
||||
function showToast(msg, isError = false) {
|
||||
const toast = document.getElementById('toast');
|
||||
const toastMsg = document.getElementById('toastMsg');
|
||||
toast.className = `fixed bottom-5 right-5 px-6 py-3 rounded-lg shadow-2xl transform transition-all duration-300 z-50 flex items-center gap-3 ${isError ? 'bg-red-600' : 'bg-slate-800'} text-white`;
|
||||
toastMsg.innerText = msg;
|
||||
toast.classList.remove('translate-y-20', 'opacity-0');
|
||||
setTimeout(() => {
|
||||
toast.classList.add('translate-y-20', 'opacity-0');
|
||||
}, 4000);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// LÓGICA DE REGISTRO
|
||||
// ==========================================
|
||||
async function handleRegister(e) {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('btnRegister');
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Procesando...";
|
||||
|
||||
const data = {
|
||||
fullName: document.getElementById('regName').value,
|
||||
dni: document.getElementById('regDni').value,
|
||||
phone: document.getElementById('regPhone').value,
|
||||
email: document.getElementById('regEmail').value,
|
||||
address: document.getElementById('regAddress').value,
|
||||
password: document.getElementById('regPass').value
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/auth/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.ok && json.ok) {
|
||||
tempPhone = json.phone; // Guardar teléfono normalizado
|
||||
showToast("✅ Código enviado por WhatsApp");
|
||||
showVerify();
|
||||
} else {
|
||||
showToast("❌ " + (json.error || "Error desconocido"), true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
showToast("❌ Error de conexión con el servidor", true);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Registrarse y Enviar Código";
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// LÓGICA DE VERIFICACIÓN
|
||||
// ==========================================
|
||||
async function handleVerify(e) {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('btnVerify');
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Verificando...";
|
||||
|
||||
const code = document.getElementById('verifyCode').value;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/auth/verify`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone: tempPhone, code: code })
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.ok && json.ok) {
|
||||
showToast("🎉 ¡Cuenta verificada!");
|
||||
localStorage.setItem('token', json.token);
|
||||
// REDIRECCIÓN AL PANEL
|
||||
setTimeout(() => { window.location.href = "panel.html"; }, 1000);
|
||||
} else {
|
||||
showToast("❌ " + (json.error || "Código incorrecto"), true);
|
||||
}
|
||||
} catch (error) {
|
||||
showToast("❌ Error verificando código", true);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Verificar y Entrar";
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// LÓGICA DE LOGIN
|
||||
// ==========================================
|
||||
async function handleLogin(e) {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('btnLogin');
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Entrando...";
|
||||
|
||||
const email = document.getElementById('loginEmail').value;
|
||||
const password = document.getElementById('loginPass').value;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password })
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.ok && json.ok) {
|
||||
showToast("👋 ¡Hola de nuevo!");
|
||||
localStorage.setItem('token', json.token);
|
||||
// REDIRECCIÓN AL PANEL
|
||||
setTimeout(() => { window.location.href = "panel.html"; }, 1000);
|
||||
} else {
|
||||
showToast("❌ " + (json.error || "Credenciales incorrectas"), true);
|
||||
}
|
||||
} catch (error) {
|
||||
showToast("❌ Error de conexión", true);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Entrar";
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// AÑADIDO: LÓGICA DE RECUPERAR CONTRASEÑA
|
||||
// ==========================================
|
||||
|
||||
async function handleForgotRequest(e) {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('btnForgotRequest');
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Enviando...";
|
||||
|
||||
const dni = document.getElementById('forgotDni').value;
|
||||
const phone = document.getElementById('forgotPhone').value;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/auth/forgot-password`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({ dni, phone })
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.ok && json.ok) {
|
||||
forgotPhoneTemp = document.getElementById('forgotPhone').value;
|
||||
showToast("✅ Código enviado a tu WhatsApp");
|
||||
document.getElementById('forgotStep1').classList.add('hidden');
|
||||
document.getElementById('forgotStep2').classList.remove('hidden');
|
||||
} else {
|
||||
showToast("❌ " + (json.error || "Datos no encontrados"), true);
|
||||
}
|
||||
} catch(e) {
|
||||
showToast("Error de conexión", true);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Enviar Código de Recuperación";
|
||||
}
|
||||
}
|
||||
|
||||
async function handleResetConfirm(e) {
|
||||
e.preventDefault();
|
||||
const btn = document.getElementById('btnResetConfirm');
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Actualizando...";
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/auth/reset-password`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
phone: forgotPhoneTemp,
|
||||
code: document.getElementById('forgotCode').value,
|
||||
newPassword: document.getElementById('forgotNewPass').value
|
||||
})
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.ok && json.ok) {
|
||||
showToast("🎉 Contraseña cambiada correctamente");
|
||||
setTimeout(() => { showLogin(); }, 2000);
|
||||
} else {
|
||||
showToast("❌ " + (json.error || "Error"), true);
|
||||
}
|
||||
} catch(e) {
|
||||
showToast("Error de conexión", true);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Cambiar Contraseña";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user