# Code coverage report for pages/Register.jsx

# All files / pages Register.jsx

100% Statements 23/23
100% Branches 10/10
100% Functions 7/7
100% Lines 22/22

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

    22x
    22x
    22x
    22x
    22x
    22x

    22x
    22x

    22x
    3x
    3x
    3x

    3x
    3x
    1x

    2x

    3x

    22x

    3x

    3x

    3x
    1x

     import { useState } from 'react'
    import { Link, useNavigate } from 'react-router-dom'
    import { motion } from 'framer-motion'
    import { Eye, EyeOff, Sparkles } from 'lucide-react'
    import { useAuthStore } from '../store/auth'

    export default function Register() {
      const [email, setEmail] = useState('')
      const [username, setUsername] = useState('')
      const [password, setPassword] = useState('')
      const [showPassword, setShowPassword] = useState(false)
      const [error, setError] = useState('')
      const [loading, setLoading] = useState(false)

      const register = useAuthStore(s => s.register)
      const navigate = useNavigate()

      const handleSubmit = async (e) => {
        e.preventDefault()
        setError('')
        setLoading(true)

        try {
          await register(email, username, password)
          navigate('/')
        } catch (err) {
          setError(err.response?.data?.error || 'Ошибка регистрации')
        } finally {
          setLoading(false)
        }
      }

      return (
        <div className="min-h-screen flex items-center justify-center p-4 bg-gradient-to-br from-primary-50 via-white to-accent-50 dark:from-gray-950 dark:via-gray-900 dark:to-gray-950 transition-colors duration-300">
          <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="w-full max-w-md">
            <div className="text-center mb-8">
              <motion.div initial={{ scale: 0 }} animate={{ scale: 1 }} transition={{ type: 'spring', delay: 0.1 }} className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-gradient-to-br from-primary-500 to-accent-500 mb-4">
                <Sparkles className="w-8 h-8 text-white" />
              </motion.div>
              <h1 className="text-2xl font-bold text-gray-900 dark:text-white">Создай аккаунт</h1>
              <p className="text-gray-500 dark:text-gray-400 mt-1">Начни отслеживать свои привычки</p>
            </div>

            <div className="card p-6">
              <form onSubmit={handleSubmit} className="space-y-4">
                {error && (
                  <motion.div initial={{ opacity: 0, height: 0 }} animate={{ opacity: 1, height: 'auto' }} className="p-3 rounded-xl bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 text-sm">
                    {error}
                  </motion.div>
                )}

                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5">Как тебя зовут?</label>
                  <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} className="input" placeholder="Имя" required />
                </div>

                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5">Email</label>
                  <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="input" placeholder="your@email.com" required />
                </div>

                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5">Пароль</label>
                  <div className="relative">
                    <input type={showPassword ? 'text' : 'password'} value={password} onChange={(e) => setPassword(e.target.value)} className="input pr-12" placeholder="Минимум 8 символов" minLength={8} required />
                    <button type="button" onClick={() => setShowPassword(!showPassword)} className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
                      {showPassword ? <EyeOff size={20} /> : <Eye size={20} />}
                    </button>
                  </div>
                </div>

                <button type="submit" disabled={loading} className="btn btn-primary w-full">
                  {loading ? 'Создаём...' : 'Создать аккаунт'}
                </button>
              </form>

              <p className="text-center text-sm text-gray-500 dark:text-gray-400 mt-6">
                Уже есть аккаунт?{' '}<Link to="/login" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 font-medium">Войти</Link>
              </p>
            </div>
          </motion.div>
        </div>
      )
    }