224 lines
6.5 KiB
JavaScript

import { useSiteContext } from '@context/SiteContext'
import useLanguage from '@hooks/useLanguage'
import { useNavigate } from '@solidjs/router'
import { Field, useFormHandler } from 'solid-form-handler'
import { yupSchema } from 'solid-form-handler/yup'
import { Show, onMount } from 'solid-js'
import { styled } from 'solid-styled-components'
import * as yup from 'yup'
import logo from '@assets/logo-fuware.svg'
import useAuth from '@hooks/useAuth'
import useToast from '@hooks/useToast'
const LoginPage = styled('div')`
width: 100%;
height: 100svh;
display: flex;
padding-left: 15px;
padding-right: 15px;
background: #fff url('/images/bg-login.jpg') no-repeat fixed center;
background-size: cover;
place-items: center;
.login-wrap {
width: 40%;
max-width: 500px;
min-width: 320px;
margin: 0 auto;
overflow: hidden;
position: relative;
&:after {
content: '';
display: block;
width: 500px;
height: 500px;
border-radius: 15px;
position: absolute;
z-index: 2;
top: -120px;
left: -285px;
background: #10b981;
transform: rotate(45deg);
}
&:before {
content: '';
display: block;
width: 500px;
height: 500px;
border-radius: 15px;
position: absolute;
z-index: 2;
top: -40px;
left: -130px;
background: #ff6600;
transform: rotate(20deg);
}
.card-body {
position: relative;
z-index: 4;
}
.logo {
position: relative;
z-index: 4;
display: block;
width: 40%;
max-width: 150px;
min-width: 100px;
margin: 0 auto;
margin-top: 15px;
}
.login-box {
box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.25);
border-radius: 5px;
padding: 1rem;
}
}
`
const loginSchema = yup.object({
username: yup.string().required('Username is required'),
password: yup.string().required('Password is required'),
})
const language = useLanguage()
export default function Login() {
const { store, setAuth } = useSiteContext()
const navigate = useNavigate()
const { clickLogIn } = useAuth(setAuth)
const notify = useToast()
const formHandler = useFormHandler(yupSchema(loginSchema))
const { formData } = formHandler
onMount(() => {
if (store.auth) {
navigate('/', { replace: true })
}
})
const submit = async (event) => {
event.preventDefault()
await formHandler.validateForm()
try {
const { username, password } = formData()
await clickLogIn(username, password, formHandler.resetForm)
notify.success({
title: 'Login success!',
description: 'Welcome back!',
closable: true,
})
} catch (error) {
notify.error({
title: 'Login fail!',
description: error?.data
? language.message[error.data]
: 'Your username or password input is wrong!',
closable: true,
})
}
}
return (
<LoginPage>
<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" onSubmit={submit}>
<Field
mode="input"
name="username"
formHandler={formHandler}
render={(field) => (
<label class="form-control w-full pb-5">
<label
class="input input-bordered flex items-center gap-2 w-full"
classList={{ 'input-error': field.helpers.error }}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4 opacity-70"
>
<path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z" />
</svg>
<input
id="username"
type="text"
class="grow w-full"
placeholder="Username"
{...field.props}
/>
</label>
<Show when={field.helpers.error}>
<div class="label">
<span class="label-text-alt text-red-600">
{field.helpers.errorMessage}
</span>
</div>
</Show>
</label>
)}
/>
<Field
mode="input"
name="password"
formHandler={formHandler}
render={(field) => (
<label class="form-control w-full">
<label
class="input input-bordered flex items-center gap-2 w-full"
classList={{ 'input-error': field.helpers.error }}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4 opacity-70"
>
<path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z" />
</svg>
<input
id="password"
type="password"
class="grow w-full"
placeholder="Password"
{...field.props}
/>
</label>
<Show when={field.helpers.error}>
<div class="label">
<span class="label-text-alt text-red-600">
{field.helpers.errorMessage}
</span>
</div>
</Show>
</label>
)}
/>
<div class="card-actions justify-end mt-5">
<button type="submit" class="btn btn-primary">
{language.ui.login}
</button>
</div>
</form>
</div>
</div>
</LoginPage>
)
}