Spaces:
Running
Running
| "use client"; | |
| import React, { useState, useEffect } from "react"; | |
| import { auth } from "@/lib/firebase"; | |
| import { signInWithEmailAndPassword, onAuthStateChanged } from "firebase/auth"; | |
| import { useRouter } from "next/navigation"; | |
| export default function LoginPage() { | |
| const [email, setEmail] = useState(""); | |
| const [password, setPassword] = useState(""); | |
| const [error, setError] = useState(""); | |
| const [loading, setLoading] = useState(false); | |
| const router = useRouter(); | |
| useEffect(() => { | |
| const unsub = onAuthStateChanged(auth, (user) => { | |
| if (user) router.push("/"); | |
| }); | |
| return () => unsub(); | |
| }, [router]); | |
| const handleLogin = async (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| setLoading(true); | |
| setError(""); | |
| try { | |
| await signInWithEmailAndPassword(auth, email, password); | |
| router.push("/"); | |
| } catch (err: any) { | |
| setError(err.message || "Error al iniciar sesión"); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| return ( | |
| <div className="min-h-screen bg-[#0f172a] flex items-center justify-center p-6 relative overflow-hidden"> | |
| {/* Background Decor */} | |
| <div className="absolute top-0 left-0 w-full h-full"> | |
| <div className="absolute top-[-10%] left-[-10%] w-[40%] h-[40%] bg-blue-600/20 blur-[120px] rounded-full"></div> | |
| <div className="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] bg-purple-600/20 blur-[120px] rounded-full"></div> | |
| </div> | |
| <div className="w-full max-w-md relative z-10 transition-all duration-700 animate-in fade-in slide-in-from-bottom-8"> | |
| <div className="bg-white/5 border border-white/10 p-10 rounded-[40px] backdrop-blur-3xl shadow-2xl"> | |
| <div className="text-center mb-10"> | |
| <h1 className="text-4xl font-black bg-gradient-to-r from-blue-400 to-indigo-500 bg-clip-text text-transparent mb-2"> | |
| ERP System | |
| </h1> | |
| <p className="text-gray-400 text-sm font-medium">Panel de control empresarial premium</p> | |
| </div> | |
| <form onSubmit={handleLogin} className="space-y-6"> | |
| <div> | |
| <input | |
| type="email" | |
| placeholder="Email corporativo" | |
| required | |
| value={email} | |
| onChange={(e) => setEmail(e.target.value)} | |
| className="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 outline-none focus:border-blue-500/50 focus:bg-white/10 transition-all placeholder:text-gray-600" | |
| /> | |
| </div> | |
| <div> | |
| <input | |
| type="password" | |
| placeholder="Contraseña" | |
| required | |
| value={password} | |
| onChange={(e) => setPassword(e.target.value)} | |
| className="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 outline-none focus:border-blue-500/50 focus:bg-white/10 transition-all placeholder:text-gray-600" | |
| /> | |
| </div> | |
| {error && ( | |
| <div className="bg-red-500/10 border border-red-500/20 text-red-400 text-xs p-4 rounded-xl animate-shake"> | |
| {error} | |
| </div> | |
| )} | |
| <button | |
| type="submit" | |
| disabled={loading} | |
| className="w-full bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-500 hover:to-indigo-500 text-white font-bold py-4 rounded-2xl shadow-lg shadow-blue-900/20 hover:shadow-blue-900/40 transition-all transform active:scale-95 disabled:opacity-50" | |
| > | |
| {loading ? ( | |
| <span className="flex items-center justify-center gap-2"> | |
| <svg className="animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> | |
| <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle> | |
| <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> | |
| </svg> | |
| Autenticando... | |
| </span> | |
| ) : ( | |
| "Entrar" | |
| )} | |
| </button> | |
| </form> | |
| <p className="mt-8 text-center text-xs text-gray-500 font-medium"> | |
| Acceso restringido para administradores autorizados | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |