File size: 4,445 Bytes
aa2e6af | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | import { useSearchParams, useNavigate } from 'react-router-dom';
import { useState, useEffect, useMemo, useCallback } from 'react';
import { useVerifyEmailMutation, useResendVerificationEmail } from '~/data-provider';
import { ThemeSelector } from '~/components/ui';
import { Spinner } from '~/components/svg';
import { useLocalize } from '~/hooks';
function RequestPasswordReset() {
const navigate = useNavigate();
const localize = useLocalize();
const [params] = useSearchParams();
const [countdown, setCountdown] = useState<number>(3);
const [headerText, setHeaderText] = useState<string>('');
const [showResendLink, setShowResendLink] = useState<boolean>(false);
const [verificationStatus, setVerificationStatus] = useState<boolean>(false);
const token = useMemo(() => params.get('token') || '', [params]);
const email = useMemo(() => params.get('email') || '', [params]);
const countdownRedirect = useCallback(() => {
setCountdown(3);
const timer = setInterval(() => {
setCountdown((prevCountdown) => {
if (prevCountdown <= 1) {
clearInterval(timer);
navigate('/c/new', { replace: true });
return 0;
} else {
return prevCountdown - 1;
}
});
}, 1000);
}, [navigate]);
const verifyEmailMutation = useVerifyEmailMutation({
onSuccess: () => {
setHeaderText(localize('com_auth_email_verification_success') + ' 🎉');
setVerificationStatus(true);
countdownRedirect();
},
onError: () => {
setShowResendLink(true);
setVerificationStatus(true);
setHeaderText(localize('com_auth_email_verification_failed') + ' 😢');
setCountdown(0);
},
});
const resendEmailMutation = useResendVerificationEmail({
onSuccess: () => {
setHeaderText(localize('com_auth_email_resent_success') + ' 📧');
countdownRedirect();
},
onError: () => {
setHeaderText(localize('com_auth_email_resent_failed') + ' 😢');
countdownRedirect();
},
onMutate: () => setShowResendLink(false),
});
const handleResendEmail = () => {
resendEmailMutation.mutate({ email });
};
useEffect(() => {
if (verifyEmailMutation.isLoading || verificationStatus) {
return;
}
if (token && email) {
verifyEmailMutation.mutate({
email,
token,
});
return;
} else if (email) {
setHeaderText(localize('com_auth_email_verification_failed_token_missing') + ' 😢');
} else {
setHeaderText(localize('com_auth_email_verification_invalid') + ' 🤨');
}
setShowResendLink(true);
setVerificationStatus(true);
setCountdown(0);
}, [localize, token, email, verificationStatus, verifyEmailMutation]);
const VerificationSuccess = () => (
<div className="flex flex-col items-center justify-center">
<h1 className="mb-4 text-center text-3xl font-semibold text-black dark:text-white">
{headerText}
</h1>
{countdown > 0 && (
<p className="text-center text-lg text-gray-600 dark:text-gray-400">
{localize('com_auth_email_verification_redirecting', countdown.toString())}
</p>
)}
{showResendLink && countdown === 0 && (
<p className="text-center text-lg text-gray-600 dark:text-gray-400">
{localize('com_auth_email_verification_resend_prompt')}
<button
className="ml-2 text-blue-600 hover:underline"
onClick={handleResendEmail}
disabled={resendEmailMutation.isLoading}
>
{localize('com_auth_email_resend_link')}
</button>
</p>
)}
</div>
);
const VerificationInProgress = () => (
<div className="flex flex-col items-center justify-center">
<h1 className="mb-4 text-center text-3xl font-semibold text-black dark:text-white">
{localize('com_auth_email_verification_in_progress')}
</h1>
<div className="mt-4 flex justify-center">
<Spinner className="h-8 w-8 text-green-500" />
</div>
</div>
);
return (
<div className="flex min-h-screen flex-col items-center justify-center bg-white pt-6 dark:bg-gray-900 sm:pt-0">
<div className="absolute bottom-0 left-0 m-4">
<ThemeSelector />
</div>
{verificationStatus ? <VerificationSuccess /> : <VerificationInProgress />}
</div>
);
}
export default RequestPasswordReset;
|