tahamajs/IE / Projects /front /src /components /auth /ForgotPasswordWindow.tsx
tahamajs's picture
download
raw
7.22 kB
import { Link } from "react-router-dom";
import { usePasswordReset } from "@/hooks/usePasswordReset";
import { GlassCard } from "@/components/ui/GlassCard";
import { motion, AnimatePresence } from "framer-motion";
import { Mail, Shield, Lock, CheckCircle, AlertCircle, ArrowLeft } from "lucide-react";
export function ForgotPasswordWindow() {
const {
step,
username,
setUsername,
question,
answer,
setAnswer,
newPassword,
setNewPassword,
confirmPassword,
setConfirmPassword,
error,
success,
loading,
requestSecurityQuestion,
submitAnswer,
resetPassword,
goBack,
} = usePasswordReset();
return (
<GlassCard className="p-6 w-full max-w-md mx-auto">
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
>
<h2 className="text-xl font-bold text-center mb-4 text-gray-900 dark:text-white">
Reset Password
</h2>
<AnimatePresence mode="wait">
{success ? (
<motion.div
key="success"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
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">Password reset successful!</p>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
You can now log in with your new password.
</p>
</div>
<Link to="/login" className="inline-block text-primary hover:underline">
Go to login →
</Link>
</motion.div>
) : (
<motion.div
key={step}
initial={{ opacity: 0, x: step === "ask" ? 0 : 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
className="space-y-4"
>
{step === "ask" && (
<>
<div className="relative">
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type="text"
placeholder="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="w-full pl-9 pr-3 py-2 glass-card rounded-lg focus:ring-2 focus:ring-primary"
required
disabled={loading}
autoFocus
/>
</div>
</>
)}
{step === "question" && (
<>
<div className="bg-gray-50 dark:bg-gray-700/50 p-4 rounded-xl">
<p className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Security question:
</p>
<p className="text-gray-900 dark:text-white font-mono text-sm break-words">
{question}
</p>
</div>
<div className="relative">
<Shield className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type="text"
placeholder="Your answer"
value={answer}
onChange={(e) => setAnswer(e.target.value)}
className="w-full pl-9 pr-3 py-2 glass-card rounded-lg"
required
autoFocus
/>
</div>
</>
)}
{step === "reset" && (
<div className="space-y-4">
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type="password"
placeholder="New password (min 6 chars)"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
className="w-full pl-9 pr-3 py-2 glass-card rounded-lg"
required
autoFocus
/>
</div>
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type="password"
placeholder="Confirm password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full pl-9 pr-3 py-2 glass-card rounded-lg"
required
/>
</div>
</div>
)}
{error && (
<div className="flex items-center gap-2 p-2 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm">
<AlertCircle className="w-4 h-4" />
<span>{error}</span>
</div>
)}
<div className="flex gap-3 pt-2">
{step !== "ask" && (
<button
type="button"
onClick={goBack}
disabled={loading}
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition flex items-center justify-center gap-2"
>
<ArrowLeft className="w-4 h-4" /> Back
</button>
)}
<button
onClick={
step === "ask"
? requestSecurityQuestion
: step === "question"
? submitAnswer
: resetPassword
}
disabled={loading}
className={`${step === "ask" ? "flex-1" : "flex-1"} py-2 rounded-lg bg-gradient-to-r from-primary to-secondary text-white font-semibold hover:opacity-90 transition disabled:opacity-50 flex items-center justify-center gap-2`}
>
{loading ? (
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
) : step === "reset" ? (
"Reset Password"
) : (
"Next"
)}
</button>
</div>
<div className="text-center text-sm">
<Link to="/login" className="text-primary hover:underline">Back to login</Link>
</div>
</motion.div>
)}
</AnimatePresence>
</motion.div>
</GlassCard>
);
}

Xet Storage Details

Size:
7.22 kB
·
Xet hash:
e243a706fd2b24b52b57b163314d8bcd7875fd8f40c652d26982249a28f37527

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