Spaces:
Sleeping
Sleeping
| 'use client'; | |
| import { useState } from 'react'; | |
| import { useRouter } from 'next/navigation'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { Eye, EyeOff, Loader2, Mail, Lock, Check, ChevronRight, CheckCircle } from 'lucide-react'; | |
| import { resetPassword } from '@/lib/api'; | |
| import { showToast } from '@/lib/toast'; | |
| export default function ResetPasswordForm() { | |
| const [email, setEmail] = useState(''); | |
| const [password, setPassword] = useState(''); | |
| const [confirmPassword, setConfirmPassword] = useState(''); | |
| const [showPassword, setShowPassword] = useState(false); | |
| const [showConfirmPassword, setShowConfirmPassword] = useState(false); | |
| const [error, setError] = useState(''); | |
| const [success, setSuccess] = useState(false); | |
| const [loading, setLoading] = useState(false); | |
| const router = useRouter(); | |
| const handleSubmit = async (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| setError(''); | |
| setLoading(true); | |
| if (!email || !email.includes('@')) { | |
| setError('Invalid identity mail provided.'); | |
| setLoading(false); | |
| return; | |
| } | |
| if (password.length < 8) { | |
| setError('Cipher must be at least 8 characters.'); | |
| setLoading(false); | |
| return; | |
| } | |
| if (password !== confirmPassword) { | |
| setError('Cipher mismatch detected.'); | |
| setLoading(false); | |
| return; | |
| } | |
| try { | |
| await resetPassword(email, password); | |
| setSuccess(true); | |
| showToast.success('Cipher Override Complete'); | |
| setTimeout(() => { | |
| router.push('/login'); | |
| }, 2000); | |
| } catch (err: any) { | |
| setError(err.message || 'Override failed. Access denied.'); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| return ( | |
| <form className="space-y-6" onSubmit={handleSubmit}> | |
| <AnimatePresence mode="wait"> | |
| {error && ( | |
| <motion.div | |
| initial={{ opacity: 0, y: -10 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| exit={{ opacity: 0, y: -10 }} | |
| className="p-4 rounded-2xl bg-red-500/10 border border-red-500/20 flex items-center gap-3" | |
| > | |
| <div className="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulse" /> | |
| <p className="text-xs font-bold text-red-400 uppercase tracking-widest">{error}</p> | |
| </motion.div> | |
| )} | |
| {success && ( | |
| <motion.div | |
| initial={{ opacity: 0, scale: 0.9 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| className="p-8 rounded-[32px] bg-emerald-500/10 border border-emerald-500/20 text-center space-y-6" | |
| > | |
| <div className="w-16 h-16 rounded-2xl bg-emerald-500/20 flex items-center justify-center mx-auto border border-emerald-500/30"> | |
| <CheckCircle className="w-8 h-8 text-emerald-400" /> | |
| </div> | |
| <div className="space-y-2"> | |
| <h3 className="text-xl font-black text-white uppercase tracking-tight">Override Complete</h3> | |
| <p className="text-sm text-slate-400 font-medium">Identity secure. Redirecting to access hub.</p> | |
| </div> | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| {!success && ( | |
| <> | |
| <div className="space-y-4"> | |
| <div className="space-y-2"> | |
| <label className="text-[10px] font-black text-white/40 uppercase tracking-[0.2em] ml-1">Identity Mail</label> | |
| <div className="relative group/input"> | |
| <div className="absolute inset-y-0 left-4 flex items-center pointer-events-none text-slate-500 group-focus-within/input:text-indigo-400 transition-colors"> | |
| <Mail className="h-4 w-4" /> | |
| </div> | |
| <input | |
| type="email" | |
| required | |
| value={email} | |
| onChange={(e) => setEmail(e.target.value)} | |
| className="w-full bg-white/[0.03] border border-white/5 rounded-2xl py-4 pl-12 pr-4 text-white placeholder-white/10 focus:outline-none focus:border-indigo-500/50 focus:bg-white/[0.05] transition-all font-bold" | |
| placeholder="operator@matrix.net" | |
| /> | |
| </div> | |
| </div> | |
| <div className="space-y-2"> | |
| <label className="text-[10px] font-black text-white/40 uppercase tracking-[0.2em] ml-1">New Genesis Cipher</label> | |
| <div className="relative group/input"> | |
| <div className="absolute inset-y-0 left-4 flex items-center pointer-events-none text-slate-500 group-focus-within/input:text-indigo-400 transition-colors"> | |
| <Lock className="h-4 w-4" /> | |
| </div> | |
| <input | |
| type={showPassword ? "text" : "password"} | |
| required | |
| value={password} | |
| onChange={(e) => setPassword(e.target.value)} | |
| className="w-full bg-white/[0.03] border border-white/5 rounded-2xl py-4 pl-12 pr-12 text-white placeholder-white/10 focus:outline-none focus:border-indigo-500/50 focus:bg-white/[0.05] transition-all font-bold" | |
| placeholder="••••••••" | |
| /> | |
| <button | |
| type="button" | |
| onClick={() => setShowPassword(!showPassword)} | |
| className="absolute inset-y-0 right-4 flex items-center text-slate-500 hover:text-white transition-colors" | |
| > | |
| {showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />} | |
| </button> | |
| </div> | |
| </div> | |
| <div className="space-y-2"> | |
| <label className="text-[10px] font-black text-white/40 uppercase tracking-[0.2em] ml-1">Confirm Cipher</label> | |
| <div className="relative group/input"> | |
| <div className="absolute inset-y-0 left-4 flex items-center pointer-events-none text-slate-500 group-focus-within/input:text-indigo-400 transition-colors"> | |
| <Check className="h-4 w-4" /> | |
| </div> | |
| <input | |
| type={showConfirmPassword ? "text" : "password"} | |
| required | |
| value={confirmPassword} | |
| onChange={(e) => setConfirmPassword(e.target.value)} | |
| className="w-full bg-white/[0.03] border border-white/5 rounded-2xl py-4 pl-12 pr-12 text-white placeholder-white/10 focus:outline-none focus:border-indigo-500/50 focus:bg-white/[0.05] transition-all font-bold" | |
| placeholder="••••••••" | |
| /> | |
| <button | |
| type="button" | |
| onClick={() => setShowConfirmPassword(!showConfirmPassword)} | |
| className="absolute inset-y-0 right-4 flex items-center text-slate-500 hover:text-white transition-colors" | |
| > | |
| {showConfirmPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />} | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <motion.button | |
| whileHover={{ scale: 1.02 }} | |
| whileTap={{ scale: 0.98 }} | |
| disabled={loading} | |
| className="w-full py-5 bg-white text-black font-black rounded-2xl shadow-[0_20px_40px_-15px_rgba(255,255,255,0.3)] hover:bg-indigo-50 transition-all flex items-center justify-center gap-3 disabled:opacity-50 group uppercase tracking-widest text-xs" | |
| > | |
| {loading ? ( | |
| <Loader2 className="h-5 w-5 animate-spin" /> | |
| ) : ( | |
| <> | |
| Execute Override | |
| <ChevronRight className="h-4 w-4 group-hover:translate-x-1 transition-transform" /> | |
| </> | |
| )} | |
| </motion.button> | |
| </> | |
| )} | |
| </form> | |
| ); | |
| } | |