dashboard/src/modules/login/Login.tsx

135 lines
4.9 KiB
TypeScript

import React, { useEffect } from 'react';
import { navigate, RouteComponentProps } from '@reach/router';
import * as yup from 'yup';
import clsx from 'clsx';
import { Controller, useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { LockClosedIcon } from '@heroicons/react/solid';
import { useAuth } from 'src/services/auth';
import { isValid } from 'src/services/api';
import { VALIDATION_MESSAGES } from 'src/common/const';
import { showToast, ToastType } from 'src/common/util/show-toast';
const validationSchema = yup.object({
email: yup.string().required(VALIDATION_MESSAGES.required('Email')),
password: yup.string().required(VALIDATION_MESSAGES.required('Password')),
});
type LoginProps = RouteComponentProps;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function Login(_: LoginProps) {
const { auth, logIn } = useAuth();
const { handleSubmit, formState, control } = useForm<{
email: string;
password: string;
remember: boolean;
}>({
resolver: yupResolver(validationSchema),
mode: 'all',
defaultValues: { email: process.env.REACT_APP_USERNAME, password: process.env.REACT_APP_PASSWORD },
});
const onSubmit = handleSubmit(async (values) => {
const res = await logIn(values.email, values.password);
// @ts-ignore
if (res.ok) {
navigate('/dashboard');
showToast('Logged in!');
} else {
showToast('Username or password incorrect', ToastType.Error);
}
});
useEffect(() => {
if (isValid(auth)) {
navigate('/dashboard');
}
}, [auth]);
if (isValid(auth)) {
return null;
}
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full space-y-8">
<div className="flex justify-center">
<img className="hidden lg:block" src="assets/logo.svg" alt="Stackspin" />
<h2 className="mt-6 text-center text-xl font-bold text-gray-900 sr-only">Sign in</h2>
</div>
<form className="mt-8 space-y-6" action="#" onSubmit={onSubmit} noValidate>
<input type="hidden" name="remember" defaultValue="true" />
<div className="rounded-md shadow-sm -space-y-px">
<div>
<Controller
control={control}
name="email"
defaultValue=""
render={({ field }) => {
return (
<>
<label htmlFor="email-address" className="sr-only">
Username
</label>
<input
{...field}
id="email-address"
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-primary-dark focus:border-primary-dark focus:z-10 sm:text-sm"
placeholder="Username"
/>
</>
);
}}
/>
</div>
<div>
<Controller
control={control}
name="password"
defaultValue=""
render={({ field }) => {
return (
<>
<label htmlFor="password" className="sr-only">
Password
</label>
<input
{...field}
id="password"
type="password"
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-primary-dark focus:border-primary-dark focus:z-10 sm:text-sm"
placeholder="Password"
/>
</>
);
}}
/>
</div>
</div>
<div>
<button
type="submit"
className={clsx(
'group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-primary-dark hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
{
'is-loading': formState.isSubmitting,
},
)}
disabled={formState.isSubmitting || !formState.isValid}
>
<span className="absolute left-0 inset-y-0 flex items-center pl-3">
<LockClosedIcon className="h-5 w-5 text-white group-hover:text-primary-light" aria-hidden="true" />
</span>
Sign in
</button>
</div>
</form>
</div>
</div>
);
}