All files / features/auth/pages LoginPage.tsx

100% Statements 16/16
81.25% Branches 13/16
100% Functions 3/3
100% Lines 16/16

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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146                                      1x 12x 12x 12x   12x 5x 5x 5x 2x 2x 2x 2x                     12x       12x 1x     12x                                                                                                                                                                                              
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { Button } from '@core/components/ui/button'
import { Input } from '@core/components/ui/input'
import {
    Card,
    CardHeader,
    CardTitle,
    CardContent,
    CardDescription,
    CardFooter,
} from '@core/components/ui/card'
import { Label } from '@core/components/ui/label'
import { useTranslation } from 'react-i18next'
import { useLogin } from '../hooks/useLogin'
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { loginSchema, type LoginFormValues } from '../schemas/login.schema'
 
export const LoginPage = () => {
    const { t } = useTranslation('common')
    const navigate = useNavigate()
    const { login, error, isLoading } = useLogin()
 
    useEffect(() => {
        const token = localStorage.getItem('token')
        const userStr = localStorage.getItem('user')
        if (token && userStr) {
            try {
                const user = JSON.parse(userStr)
                Eif (user.role === 'ADMIN' || user.role === 'STAFF') {
                    navigate('/admin')
                }
            } catch {
                // Ignore parse error
            }
        }
    }, [navigate])
    const {
        register,
        handleSubmit,
        formState: { errors },
    } = useForm<LoginFormValues>({
        resolver: zodResolver(loginSchema),
    })
 
    const onSubmit = async (data: LoginFormValues) => {
        await login(data)
    }
 
    return (
        <div
            className="flex items-center justify-center min-h-screen p-4"
            style={{ backgroundColor: 'var(--auth-page-bg)' }}
        >
            <Card
                className="w-full max-w-md backdrop-blur-md border-t overflow-hidden"
                style={{
                    boxShadow: 'var(--auth-card-shadow)',
                    borderRadius: 'var(--auth-card-radius)',
                    borderColor: 'var(--auth-input-border)',
                }}
            >
                <CardHeader>
                    <CardTitle
                        className="text-2xl text-center"
                        style={{ color: 'var(--auth-title-color)' }}
                    >
                        {t('login.title')}
                    </CardTitle>
                    <CardDescription
                        className="text-center"
                        style={{ color: 'var(--auth-subtitle-color)' }}
                    >
                        {t('login.subtitle')}
                    </CardDescription>
                </CardHeader>
                <CardContent>
                    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
                        <div className="space-y-2">
                            <Label htmlFor="email" style={{ color: 'var(--auth-label-color)' }}>
                                {t('login.email')}
                            </Label>
                            <Input
                                id="email"
                                type="email"
                                placeholder={t('login.email_placeholder')}
                                {...register('email')}
                                style={{
                                    backgroundColor: 'var(--auth-input-bg)',
                                    color: 'var(--auth-input-text)',
                                    borderColor: 'var(--auth-input-border)',
                                }}
                            />
                            {errors.email && (
                                <p className="text-sm text-red-500">{errors.email.message}</p>
                            )}
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="password" style={{ color: 'var(--auth-label-color)' }}>
                                {t('login.password')}
                            </Label>
                            <Input
                                id="password"
                                type="password"
                                {...register('password')}
                                style={{
                                    backgroundColor: 'var(--auth-input-bg)',
                                    color: 'var(--auth-input-text)',
                                    borderColor: 'var(--auth-input-border)',
                                }}
                            />
                            {errors.password && (
                                <p className="text-sm text-red-500">{errors.password.message}</p>
                            )}
                        </div>
 
                        {error && <p className="text-sm text-red-500 text-center">{error}</p>}
 
                        <Button
                            type="submit"
                            className="w-full"
                            disabled={isLoading}
                            style={{
                                backgroundColor: 'var(--auth-button-bg)',
                                color: 'var(--auth-button-text)',
                            }}
                        >
                            {isLoading ? t('login.loading') : t('login.submit')}
                        </Button>
                    </form>
                </CardContent>
                <CardFooter className="flex justify-center">
                    <a
                        href="/auth/google"
                        className="text-sm hover:underline"
                        style={{ color: 'var(--auth-link-color)' }}
                    >
                        {t('login.google')}
                    </a>
                </CardFooter>
            </Card>
        </div>
    )
}