Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 11x 11x 11x 11x 11x 6x 1x 1x 1x 5x 5x 5x 3x 3x 1x 1x 5x 11x | import { useEffect, useState } from 'react'
import { useSearchParams, Link } from 'react-router-dom'
import { motion } from 'framer-motion'
import { CheckCircle, XCircle, Loader2, Zap } from 'lucide-react'
import api from '../api/client'
export default function VerifyEmail() {
const [searchParams] = useSearchParams()
const [status, setStatus] = useState('loading') // loading, success, error
const [message, setMessage] = useState('')
const token = searchParams.get('token')
useEffect(() => {
if (!token) {
setStatus('error')
setMessage('Токен не найден')
return
}
const verify = async () => {
try {
await api.post('/auth/verify-email', { token })
setStatus('success')
setMessage('Email успешно подтверждён!')
} catch (err) {
setStatus('error')
setMessage(err.response?.data?.error || 'Ошибка верификации')
}
}
verify()
}, [token])
return (
<div className="min-h-screen flex items-center justify-center p-4 gradient-mesh bg-surface-50">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="w-full max-w-md"
>
<div className="card p-10 text-center">
{status === 'loading' && (
<>
<div className="w-20 h-20 rounded-3xl bg-primary-100 flex items-center justify-center mx-auto mb-6">
<Loader2 className="w-10 h-10 text-primary-600 animate-spin" />
</div>
<h1 className="text-2xl font-display font-bold text-gray-900 mb-2">
Проверяем...
</h1>
<p className="text-gray-500">Подожди секунду</p>
</>
)}
{status === 'success' && (
<>
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 200 }}
className="w-20 h-20 rounded-3xl bg-green-100 flex items-center justify-center mx-auto mb-6"
>
<CheckCircle className="w-10 h-10 text-green-600" />
</motion.div>
<h1 className="text-2xl font-display font-bold text-gray-900 mb-2">
Готово! 🎉
</h1>
<p className="text-gray-500 mb-6">{message}</p>
<Link to="/login" className="btn btn-primary">
Войти в аккаунт
</Link>
</>
)}
{status === 'error' && (
<>
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 200 }}
className="w-20 h-20 rounded-3xl bg-red-100 flex items-center justify-center mx-auto mb-6"
>
<XCircle className="w-10 h-10 text-red-600" />
</motion.div>
<h1 className="text-2xl font-display font-bold text-gray-900 mb-2">
Ошибка
</h1>
<p className="text-gray-500 mb-6">{message}</p>
<Link to="/login" className="btn btn-secondary">
На главную
</Link>
</>
)}
</div>
<div className="flex items-center justify-center gap-2 mt-6 text-gray-400">
<Zap size={16} />
<span className="text-sm font-medium">Pulse</span>
</div>
</motion.div>
</div>
)
}
|