email verfication after account creation, password component, added password special characters
This commit is contained in:
145
frontend/src/pages/VerifyEmail.tsx
Normal file
145
frontend/src/pages/VerifyEmail.tsx
Normal file
@@ -0,0 +1,145 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useNavigate, useSearchParams, Link } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { authAPI } from '../services/api';
|
||||
|
||||
const VerifyEmail: React.FC = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
const { checkAuth, user } = useAuth();
|
||||
const [error, setError] = useState<string>('');
|
||||
const [success, setSuccess] = useState(false);
|
||||
const [processing, setProcessing] = useState(true);
|
||||
const [resending, setResending] = useState(false);
|
||||
const hasProcessed = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleVerification = async () => {
|
||||
// Prevent double execution in React StrictMode
|
||||
if (hasProcessed.current) {
|
||||
return;
|
||||
}
|
||||
hasProcessed.current = true;
|
||||
|
||||
try {
|
||||
const token = searchParams.get('token');
|
||||
|
||||
if (!token) {
|
||||
setError('No verification token provided.');
|
||||
setProcessing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the email with the token
|
||||
await authAPI.verifyEmail(token);
|
||||
|
||||
setSuccess(true);
|
||||
setProcessing(false);
|
||||
|
||||
// Refresh user data to update isVerified status
|
||||
await checkAuth();
|
||||
|
||||
// Redirect to home after 3 seconds
|
||||
setTimeout(() => {
|
||||
navigate('/', { replace: true });
|
||||
}, 3000);
|
||||
} catch (err: any) {
|
||||
console.error('Email verification error:', err);
|
||||
const errorData = err.response?.data;
|
||||
|
||||
if (errorData?.code === 'VERIFICATION_TOKEN_EXPIRED') {
|
||||
setError('Your verification link has expired. Please request a new one.');
|
||||
} else if (errorData?.code === 'VERIFICATION_TOKEN_INVALID') {
|
||||
setError('Invalid verification link. The link may have already been used or is incorrect.');
|
||||
} else if (errorData?.code === 'ALREADY_VERIFIED') {
|
||||
setError('Your email is already verified.');
|
||||
} else {
|
||||
setError(errorData?.error || 'Failed to verify email. Please try again.');
|
||||
}
|
||||
|
||||
setProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
handleVerification();
|
||||
}, [searchParams, navigate, checkAuth]);
|
||||
|
||||
const handleResendVerification = async () => {
|
||||
setResending(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
await authAPI.resendVerification();
|
||||
setError('');
|
||||
alert('Verification email sent! Please check your inbox.');
|
||||
} catch (err: any) {
|
||||
console.error('Resend verification error:', err);
|
||||
const errorData = err.response?.data;
|
||||
|
||||
if (errorData?.code === 'ALREADY_VERIFIED') {
|
||||
setError('Your email is already verified.');
|
||||
} else if (errorData?.code === 'NO_TOKEN') {
|
||||
setError('You must be logged in to resend the verification email.');
|
||||
} else {
|
||||
setError(errorData?.error || 'Failed to resend verification email. Please try again.');
|
||||
}
|
||||
} finally {
|
||||
setResending(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row justify-content-center mt-5">
|
||||
<div className="col-md-6">
|
||||
<div className="card">
|
||||
<div className="card-body text-center py-5">
|
||||
{processing ? (
|
||||
<>
|
||||
<div className="spinner-border text-primary mb-3" role="status">
|
||||
<span className="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<h5>Verifying Your Email...</h5>
|
||||
<p className="text-muted">Please wait while we verify your email address.</p>
|
||||
</>
|
||||
) : success ? (
|
||||
<>
|
||||
<i className="bi bi-check-circle text-success" style={{ fontSize: '3rem' }}></i>
|
||||
<h5 className="mt-3">Email Verified Successfully!</h5>
|
||||
<p className="text-muted">
|
||||
Your email has been verified. You will be redirected to the home page shortly.
|
||||
</p>
|
||||
<Link to="/" className="btn btn-primary mt-3">
|
||||
Go to Home
|
||||
</Link>
|
||||
</>
|
||||
) : error ? (
|
||||
<>
|
||||
<i className="bi bi-exclamation-circle text-danger" style={{ fontSize: '3rem' }}></i>
|
||||
<h5 className="mt-3">Verification Failed</h5>
|
||||
<p className="text-danger">{error}</p>
|
||||
<div className="mt-3">
|
||||
{user && !error.includes('already verified') && (
|
||||
<button
|
||||
className="btn btn-primary me-2"
|
||||
onClick={handleResendVerification}
|
||||
disabled={resending}
|
||||
>
|
||||
{resending ? 'Sending...' : 'Resend Verification Email'}
|
||||
</button>
|
||||
)}
|
||||
<Link to="/" className="btn btn-outline-secondary">
|
||||
Return to Home
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerifyEmail;
|
||||
Reference in New Issue
Block a user