88 lines
3.4 KiB
JavaScript
88 lines
3.4 KiB
JavaScript
import { useState, useEffect } from 'react';
|
|
import { Link, useSearchParams } from 'react-router-dom';
|
|
import { useLanguage } from '../contexts/LanguageContext';
|
|
import { CheckCircle, XCircle, Loader2, Mail } from 'lucide-react';
|
|
import BrandLogo from '../components/BrandLogo';
|
|
import api from '../services/api';
|
|
|
|
export default function VerifyEmail() {
|
|
const [searchParams] = useSearchParams();
|
|
const token = searchParams.get('token');
|
|
const { t } = useLanguage();
|
|
|
|
const [status, setStatus] = useState('loading'); // loading | success | error
|
|
const [message, setMessage] = useState('');
|
|
|
|
useEffect(() => {
|
|
if (!token) {
|
|
setStatus('error');
|
|
setMessage(t('auth.verifyTokenMissing'));
|
|
return;
|
|
}
|
|
|
|
api.get(`/auth/verify-email?token=${token}`)
|
|
.then(() => {
|
|
setStatus('success');
|
|
setMessage(t('auth.verifySuccess'));
|
|
})
|
|
.catch(err => {
|
|
setStatus('error');
|
|
setMessage(err.response?.data?.error || t('auth.verifyFailed'));
|
|
});
|
|
}, [token]);
|
|
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center p-6 relative overflow-hidden">
|
|
{/* Animated background */}
|
|
<div className="absolute inset-0 bg-th-bg">
|
|
<div className="absolute inset-0 opacity-30">
|
|
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-th-accent rounded-full blur-[128px] animate-pulse" />
|
|
<div className="absolute bottom-1/4 right-1/4 w-80 h-80 bg-purple-500 rounded-full blur-[128px] animate-pulse" style={{ animationDelay: '2s' }} />
|
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-64 h-64 bg-pink-500 rounded-full blur-[128px] animate-pulse" style={{ animationDelay: '4s' }} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="relative w-full max-w-md">
|
|
<div className="card p-8 backdrop-blur-xl bg-th-card/80 border border-th-border shadow-2xl rounded-2xl text-center">
|
|
<div className="flex justify-center mb-8">
|
|
<BrandLogo size="lg" />
|
|
</div>
|
|
|
|
{status === 'loading' && (
|
|
<div className="space-y-4">
|
|
<Loader2 size={48} className="mx-auto animate-spin text-th-accent" />
|
|
<p className="text-th-text">{t('auth.verifying')}</p>
|
|
</div>
|
|
)}
|
|
|
|
{status === 'success' && (
|
|
<div className="space-y-4">
|
|
<CheckCircle size={48} className="mx-auto text-green-400" />
|
|
<h2 className="text-2xl font-bold text-th-text">{t('auth.verifySuccessTitle')}</h2>
|
|
<p className="text-th-text-s">{message}</p>
|
|
<Link to="/login" className="btn-primary inline-flex items-center gap-2 mt-4">
|
|
{t('auth.login')}
|
|
</Link>
|
|
</div>
|
|
)}
|
|
|
|
{status === 'error' && (
|
|
<div className="space-y-4">
|
|
<XCircle size={48} className="mx-auto text-red-400" />
|
|
<h2 className="text-2xl font-bold text-th-text">{t('auth.verifyFailedTitle')}</h2>
|
|
<p className="text-th-text-s">{message}</p>
|
|
<Link to="/register" className="btn-primary inline-flex items-center gap-2 mt-4">
|
|
{t('auth.register')}
|
|
</Link>
|
|
</div>
|
|
)}
|
|
|
|
<Link to="/" className="block mt-6 text-center text-sm text-th-text-s hover:text-th-text transition-colors">
|
|
{t('auth.backToHome')}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|