tahamajs/IE / Projects /front /src /components /auth /ForgotPasswordForm.tsx
tahamajs's picture
download
raw
3.59 kB
import { useState, FormEvent } from "react";
import { Link } from "react-router-dom";
import api from "@/lib/api";
import { toast } from "react-toastify";
import { motion } from "framer-motion";
import { User, ArrowRight, Loader2, CheckCircle } from "lucide-react";
export function ForgotPasswordForm() {
const [username, setUsername] = useState("");
const [loading, setLoading] = useState(false);
const [submitted, setSubmitted] = useState(false);
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (!username.trim()) {
toast.warning("Please enter your username");
return;
}
setLoading(true);
try {
await api.post("/auth/forgot-password", { username: username.trim() });
setSubmitted(true);
toast.success("Security question loaded. Continue with reset.");
} catch (err: any) {
toast.error(err.response?.data?.error || "Something went wrong. Please try again.");
} finally {
setLoading(false);
}
};
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="w-full max-w-md mx-auto"
>
<div className="bg-white dark:bg-gray-800 rounded-2xl shadow-2xl p-8">
<div className="text-center mb-6">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">Forgot password?</h2>
<p className="text-gray-500 dark:text-gray-400 mt-1">
Enter your username to load your security question.
</p>
</div>
{submitted ? (
<div className="text-center space-y-4">
<div className="bg-green-50 dark:bg-green-900/20 p-4 rounded-xl">
<CheckCircle className="w-12 h-12 text-green-500 mx-auto mb-2" />
<p className="text-green-700 dark:text-green-400 font-medium">Security question loaded!</p>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
If an account exists for {username}, you can continue with the reset flow.
</p>
</div>
<Link to="/login" className="text-primary hover:underline text-sm">
Return to login
</Link>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-4">
<div className="relative">
<User className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
type="text"
className="w-full pl-10 pr-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent transition"
placeholder="your username"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
disabled={loading}
/>
</div>
<button
type="submit"
disabled={loading}
className="w-full bg-primary hover:bg-primary/90 text-white font-semibold py-2 rounded-lg transition disabled:opacity-50 flex items-center justify-center gap-2"
>
{loading ? <Loader2 className="animate-spin w-5 h-5" /> : <ArrowRight className="w-5 h-5" />}
{loading ? "Loading..." : "Load security question"}
</button>
<div className="text-center text-sm">
<Link to="/login" className="text-primary hover:underline">Back to login</Link>
</div>
</form>
)}
</div>
</motion.div>
);
}

Xet Storage Details

Size:
3.59 kB
·
Xet hash:
89464d003fc356391d7eb6cc01fc449944d092d98a21a39fec45f5e5920a7c25

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.