import React, { useMemo, useState, useEffect } from 'react'; import { useAppContext } from './app'; import { flash } from './toast'; import { Link } from 'react-router-dom'; import Logo from './logo'; const ResetPassword: React.FC<{}> = () => { const [email, setEmail] = useState(''); const [code, setCode] = useState(''); const [newPassword, setNewPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [submitting, setSubmitting] = useState(false); const [step, setStep] = useState(1); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); const { request, setState, redirect, queries } = useAppContext() as any; const token: string = useMemo(() => queries['token'] || '', [queries]); const emailAddress: string = useMemo(() => queries['email'] || '', [queries]); const handleTogglePassword = () => setShowPassword(!showPassword); const handleToggleConfirmPassword = () => setShowConfirmPassword(!showConfirmPassword); const handleSubmitEmail = (event: React.FormEvent) => { event.preventDefault(); if (!email.trim()) { flash('Please enter an email address'); return; } setSubmitting(true); request('/reset-password', 'POST', { email }) .then(() => { flash('Password reset link sent to your email'); setStep(2); }) .catch((error: any) => { flash('An error occurred'); console.error(error); }) .finally(() => { setSubmitting(false); }); }; const handleVerifyCode = async (event?: React.FormEvent) => { event?.preventDefault(); if (!code.trim() && !token) { flash('Please enter the verification code'); return; } setSubmitting(true); try { const result = await request('/verify-code', 'POST', { email: emailAddress || email, code: token || code }); flash('Code verified successfully'); setCode(result.token); setStep(3); } catch (error: any) { flash('Invalid or expired code'); console.error(error); throw error; } finally { setSubmitting(false); } }; const handleResetPassword = (event: React.FormEvent) => { event.preventDefault(); if (!newPassword || !confirmPassword) { flash('Please fill in all fields'); return; } if (newPassword !== confirmPassword) { flash('Passwords do not match'); return; } if (!/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{12,}$/.test(newPassword)) { flash('Password must be at least 12 characters long and include uppercase, lowercase, number, and symbol'); return; } setSubmitting(true); request('/finalize-password', 'POST', { email: emailAddress || email, token: code, password: newPassword }) .then(({ token, key, iv }: { token: string; key: string; iv: string }) => { flash('Password has been reset successfully'); if (!token || !key || !iv) { return redirect('/login'); } localStorage.setItem('token', JSON.stringify({ token, key, iv })); setState({ token, key, iv }); redirect('/'); }) .catch((error: any) => { flash('An error occurred'); console.error(error); }) .finally(() => { setSubmitting(false); }); }; useEffect(() => { if (token) { handleVerifyCode().catch(() => { flash('Invalid or expired code'); redirect('/reset-password'); }); } }, [token]); return (