Completed Change to ReactJS
This commit is contained in:
@ -1,90 +1,130 @@
|
||||
import { useSiteContext } from '@context/SiteContext'
|
||||
import { createForm } from '@felte/solid'
|
||||
import { validator } from '@felte/validator-yup'
|
||||
import useLanguage from '@hooks/useLanguage'
|
||||
import { useNavigate } from '@solidjs/router'
|
||||
import { IconKey, IconUser } from '@tabler/icons-solidjs'
|
||||
import { onMount } from 'solid-js'
|
||||
import * as yup from 'yup'
|
||||
import './login.scss'
|
||||
|
||||
import Logo from '@assets/images/logo.svg'
|
||||
import TextInput from '@components/common/TextInput'
|
||||
import useAuth from '@hooks/useAuth'
|
||||
import useToast from '@hooks/useToast'
|
||||
|
||||
const loginSchema = (language, isRequired) =>
|
||||
yup.object({
|
||||
username: yup.string().required(isRequired(language.ui.username)),
|
||||
password: yup.string().required(isRequired(language.ui.password)),
|
||||
})
|
||||
import { errorTip, labelWithIcon } from '@components/Common'
|
||||
import { useAuth, useSignInUp } from '@hooks/useAuth'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Center,
|
||||
Container,
|
||||
Group,
|
||||
Image,
|
||||
PasswordInput,
|
||||
TextInput,
|
||||
Title,
|
||||
} from '@mantine/core'
|
||||
import { isNotEmpty, useForm } from '@mantine/form'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import {
|
||||
IconCircleCheck,
|
||||
IconCircleXFilled,
|
||||
IconKeyFilled,
|
||||
IconUserFilled,
|
||||
} from '@tabler/icons-react'
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { s_logo, s_wrapper } from './Login.module.scss'
|
||||
|
||||
export default function Login() {
|
||||
const { store, setAuth } = useSiteContext()
|
||||
const { language, isRequired } = useLanguage()
|
||||
const {
|
||||
auth: { isLogged },
|
||||
setAuth,
|
||||
} = useAuth()
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const { clickLogIn } = useAuth(setAuth)
|
||||
const notify = useToast()
|
||||
|
||||
const { form, errors } = createForm({
|
||||
extend: [validator({ schema: loginSchema(language, isRequired) })],
|
||||
onSubmit: async (values) => {
|
||||
try {
|
||||
const { username, password } = values
|
||||
return await clickLogIn(username, password)
|
||||
} catch (error) {
|
||||
notify.error({
|
||||
title: 'Login fail!',
|
||||
description: error?.data
|
||||
? language.message[error.data]
|
||||
: 'Your username or password input is wrong!',
|
||||
closable: true,
|
||||
})
|
||||
}
|
||||
const { onLogin } = useSignInUp(setAuth)
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
validate: {
|
||||
username: isNotEmpty(
|
||||
t('message_is_required', { field: t('ui_username') }),
|
||||
),
|
||||
password: isNotEmpty(
|
||||
t('message_is_required', { field: t('ui_password') }),
|
||||
),
|
||||
},
|
||||
enhanceGetInputProps: (payload) => ({
|
||||
error: errorTip(payload.inputProps.error),
|
||||
}),
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (store.auth) {
|
||||
useEffect(() => {
|
||||
if (isLogged) {
|
||||
navigate('/', { replace: true })
|
||||
}
|
||||
})
|
||||
|
||||
const onSubmitLogin = async (values) => {
|
||||
try {
|
||||
await onLogin(values)
|
||||
notifications.show({
|
||||
color: 'green.5',
|
||||
icon: <IconCircleCheck />,
|
||||
title: t('message_login_success'),
|
||||
message: t('message_welcom_back'),
|
||||
})
|
||||
} catch (error) {
|
||||
notifications.show({
|
||||
color: 'red.5',
|
||||
icon: <IconCircleXFilled />,
|
||||
title: t('message_login_fail'),
|
||||
message: error?.data ? t(error.data) : t('message_login_wrong'),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="login-page">
|
||||
<div class="card glass card-compact login-wrap shadow-xl">
|
||||
<div class="h-44">
|
||||
<picture class="logo">
|
||||
<source srcSet={Logo} type="image/png" media="(min-width: 600px)" />
|
||||
<img src={Logo} alt="logo" />
|
||||
</picture>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h1 class="card-title">{language.ui.login}</h1>
|
||||
<form autoComplete="off" use:form>
|
||||
<TextInput
|
||||
name="username"
|
||||
placeholder={language.ui.username}
|
||||
icon={IconUser}
|
||||
label={language.ui.username}
|
||||
error={errors('username')}
|
||||
/>
|
||||
<TextInput
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder={language.ui.password}
|
||||
icon={IconKey}
|
||||
label={language.ui.password}
|
||||
error={errors('password')}
|
||||
/>
|
||||
<div class="card-actions justify-end mt-2">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{language.ui.login}
|
||||
</button>
|
||||
</div>
|
||||
<Container
|
||||
fluid
|
||||
style={{
|
||||
background: '#fff url(/images/bg-login.jpg) no-repeat fixed center',
|
||||
backgroundSize: 'cover',
|
||||
}}
|
||||
h="100svh"
|
||||
>
|
||||
<Center h="100svh">
|
||||
<Card
|
||||
shadow="xl"
|
||||
radius={20}
|
||||
w="40%"
|
||||
maw={500}
|
||||
miw={320}
|
||||
className={s_wrapper}
|
||||
>
|
||||
<Card.Section>
|
||||
<Image src={Logo} className={s_logo} alt="logo" />
|
||||
</Card.Section>
|
||||
<form onSubmit={form.onSubmit(onSubmitLogin)}>
|
||||
<Box pos="relative" style={{ zIndex: 4 }}>
|
||||
<Title order={1} fz={18} mb="sm" mt="sm">
|
||||
{t('ui_login')}
|
||||
</Title>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
label={labelWithIcon(t('ui_username'), IconUserFilled)}
|
||||
placeholder={t('ui_username')}
|
||||
key={form.key('username')}
|
||||
{...form.getInputProps('username')}
|
||||
/>
|
||||
<PasswordInput
|
||||
withAsterisk
|
||||
label={labelWithIcon(t('ui_password'), IconKeyFilled)}
|
||||
placeholder={t('ui_password')}
|
||||
mt="sm"
|
||||
key={form.key('password')}
|
||||
{...form.getInputProps('password')}
|
||||
/>
|
||||
<Group justify="flex-end" mt="md">
|
||||
<Button type="submit">{t('ui_login')}</Button>
|
||||
</Group>
|
||||
</Box>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Center>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user