100 lines
4.3 KiB
TypeScript
100 lines
4.3 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { useAuthContext } from '../AuthContext';
|
|
import { Loader2, AlertCircle, ArrowRight } from 'lucide-react';
|
|
|
|
interface LoginPageProps {
|
|
onSuccess: () => void;
|
|
onRegister: () => void;
|
|
}
|
|
|
|
const LoginPage: React.FC<LoginPageProps> = ({ onSuccess, onRegister }) => {
|
|
const [email, setEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [error, setError] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
// Use the global auth context
|
|
const { login } = useAuthContext();
|
|
|
|
async function handleSubmit(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
setError("");
|
|
setLoading(true);
|
|
|
|
try {
|
|
await login(email, password);
|
|
onSuccess();
|
|
} catch (err: any) {
|
|
setError(err.message || "Une erreur inattendue est survenue.");
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-slate-50 flex overflow-hidden font-sans text-slate-900 items-center justify-center p-4">
|
|
{/* Using styles similar to AuthPage for consistency */}
|
|
<div className="w-full max-w-md bg-white rounded-2xl shadow-xl overflow-hidden p-8 animate-in fade-in zoom-in duration-300">
|
|
<div className="text-center mb-8">
|
|
<h1 className="text-3xl font-black text-slate-900 mb-2">Connexion</h1>
|
|
<p className="text-slate-500">Bienvenue ! Connectez-vous à votre compte</p>
|
|
</div>
|
|
|
|
{error && (
|
|
<div className="mb-6 p-4 bg-red-50 border border-red-100 text-red-600 text-sm font-medium rounded-xl flex items-center gap-2 animate-in shake duration-300">
|
|
<AlertCircle size={18} />
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
<div className="space-y-1">
|
|
<label className="text-xs font-black text-slate-500 uppercase tracking-widest ml-1" htmlFor="email">Email</label>
|
|
<input
|
|
id="email"
|
|
type="email"
|
|
className="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl outline-none focus:ring-2 focus:ring-blue-500 font-medium transition-all"
|
|
placeholder="votre@email.com"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<label className="text-xs font-black text-slate-500 uppercase tracking-widest ml-1" htmlFor="password">Mot de passe</label>
|
|
<input
|
|
id="password"
|
|
type="password"
|
|
className="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl outline-none focus:ring-2 focus:ring-blue-500 font-medium transition-all"
|
|
placeholder="••••••••"
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
className="w-full bg-slate-900 text-white py-4 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-blue-600 transition-all shadow-xl disabled:opacity-50 mt-6"
|
|
disabled={loading}
|
|
>
|
|
{loading ? <Loader2 className="animate-spin" /> : "Se connecter"} <ArrowRight size={18} />
|
|
</button>
|
|
</form>
|
|
|
|
<div className="mt-8 text-center text-sm text-slate-500">
|
|
Pas encore de compte ?{" "}
|
|
<button
|
|
onClick={onRegister}
|
|
className="font-bold text-blue-600 hover:text-blue-800 transition-colors ml-1"
|
|
>
|
|
Créer un compte
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default LoginPage;
|