Feat/login
This commit is contained in:
parent
4803c4d8b6
commit
3361d4c043
7 changed files with 91 additions and 167 deletions
|
|
@ -1,133 +1,65 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { navigate, RouteComponentProps } from '@reach/router';
|
||||
import * as yup from 'yup';
|
||||
import React from 'react';
|
||||
import { RouteComponentProps } from '@reach/router';
|
||||
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')),
|
||||
});
|
||||
import { performApiCall } from 'src/services/api';
|
||||
|
||||
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 handleSubmit = async () => {
|
||||
try {
|
||||
const { data } = await performApiCall({
|
||||
path: '/login',
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
const res = await logIn(values.email, values.password);
|
||||
if (data.authorizationUrl) {
|
||||
window.location.href = data.authorizationUrl;
|
||||
}
|
||||
} catch (e: any) {
|
||||
// continue
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (res.ok) {
|
||||
navigate('/dashboard');
|
||||
showToast('Logged in!');
|
||||
} else {
|
||||
showToast('Username or password incorrect', ToastType.Error);
|
||||
}
|
||||
});
|
||||
// if (res.ok) {
|
||||
// showToast('Logged in!');
|
||||
// } else {
|
||||
// showToast('Username or password incorrect', ToastType.Error);
|
||||
// }
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isValid(auth)) {
|
||||
navigate('/dashboard');
|
||||
}
|
||||
}, [auth]);
|
||||
// useEffect(() => {
|
||||
// if (isValid(auth)) {
|
||||
// navigate('/dashboard');
|
||||
// }
|
||||
// }, [auth]);
|
||||
|
||||
if (isValid(auth)) {
|
||||
return null;
|
||||
}
|
||||
// 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" />
|
||||
<img className="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>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
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',
|
||||
)}
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
31
src/modules/login/LoginCallback.tsx
Normal file
31
src/modules/login/LoginCallback.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { RouteComponentProps } from '@reach/router';
|
||||
import { useAuth } from 'src/services/auth';
|
||||
import { showToast, ToastType } from 'src/common/util/show-toast';
|
||||
|
||||
type LoginCallbackProps = RouteComponentProps;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function LoginCallback(_: LoginCallbackProps) {
|
||||
const { logIn } = useAuth();
|
||||
|
||||
useEffect(() => {
|
||||
const res = logIn();
|
||||
|
||||
// @ts-ignore
|
||||
if (res.ok) {
|
||||
showToast('Logged in');
|
||||
} else {
|
||||
showToast('Something went wrong', ToastType.Error);
|
||||
// navigate('/login');
|
||||
}
|
||||
}, [logIn]);
|
||||
|
||||
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">Loading . . .</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in a new issue