All files / pages VerifyEmail.jsx

100% Statements 18/18
90% Branches 9/10
100% Functions 3/3
100% Lines 18/18

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>
  )
}