feat: login

:%s
This commit is contained in:
lytrankieio123
2021-09-29 17:56:41 +07:00
parent 1383d66832
commit aa32d6fe27
10 changed files with 114 additions and 60 deletions

View File

@@ -2,10 +2,10 @@ import { Layout } from 'src/components/common'
import { useMessage } from 'src/components/contexts'
export default function Test() {
const { showMessageSuccess } = useMessage()
const { showMessageError } = useMessage()
const handleClick = () => {
showMessageSuccess("Create account successfully")
showMessageError("Create account successfully")
}
return (

View File

@@ -63,10 +63,14 @@ const InputFiledInForm = forwardRef<Ref, Props>(({
return <></>
}, [icon, error, isShowIconSuccess])
const handleKeyDown = (e: any) => {
if (e.key === KEY.ENTER && onEnter) {
const value = inputElementRef.current?.value || ''
onEnter(value)
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === KEY.ENTER) {
e.stopPropagation()
e.preventDefault()
if (onEnter) {
const value = inputElementRef.current?.value || ''
onEnter(value)
}
}
}

View File

@@ -14,6 +14,7 @@ const MessageCommon = memo(({ messages, onRemove }: Props) => {
<MessageItem
key={item.id}
id={item.id}
type={item.type}
content={item.content}
onRemove={onRemove}
/>

View File

@@ -4,12 +4,11 @@
@apply shadow-sm flex justify-center items-center cursor-default;
width: fit-content;
padding: 0.8rem 2.4rem;
margin-bottom: .8rem;
margin: 0 auto .8rem;
border-radius: 0.8rem;
transition: all .5s;
animation: showMessage .5s;
width: max-content;
margin: 0 1.6rem;
&.hide {
display: none;

View File

@@ -40,7 +40,7 @@ const MessageItem = memo(
useEffect(() => {
if (isHide && !isMouseOver && onRemove) {
onRemove(id || 0)
// onRemove(id || 0)
}
}, [isHide, isMouseOver, onRemove, id])

View File

@@ -1,7 +1,7 @@
@import '../../../../styles/utilities';
.formAuthen {
@apply bg-white w-full u-form;
@apply bg-white w-full;
.inner {
@screen md {
width: 60rem;

View File

@@ -1,9 +1,13 @@
import { Form, Formik } from 'formik'
import Link from 'next/link'
import React, { useEffect, useRef, useState } from 'react'
import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
import { ROUTE } from 'src/utils/constanst.utils'
import { CustomInputCommon } from 'src/utils/type.utils'
import { ButtonCommon, Inputcommon, InputFiledInForm, InputPassword, InputPasswordFiledInForm } from 'src/components/common'
import { useMessage } from 'src/components/contexts'
import useLogin from 'src/components/hooks/useLogin'
import { ROUTE } from 'src/utils/constanst.utils'
import { LANGUAGE } from 'src/utils/language.utils'
import { CustomInputCommon } from 'src/utils/type.utils'
import * as Yup from 'yup'
import s from '../FormAuthen.module.scss'
import SocialAuthen from '../SocialAuthen/SocialAuthen'
import styles from './FormLogin.module.scss'
@@ -13,15 +17,17 @@ interface Props {
onSwitch: () => void
}
const DisplayingErrorMessagesSchema = Yup.object().shape({
email: Yup.string().email('Your email was wrong').required('Required'),
password: Yup.string()
.max(30, 'Password is too long')
.required('Required'),
})
const FormLogin = ({ onSwitch, isHide }: Props) => {
const emailRef = useRef<CustomInputCommon>(null)
const { loading, login, error } = useLogin()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const onLogin = () => {
login({ username: email, password })
}
const { loading, login } = useLogin()
const { showMessageSuccess, showMessageError } = useMessage()
useEffect(() => {
if (!isHide) {
@@ -29,42 +35,71 @@ const FormLogin = ({ onSwitch, isHide }: Props) => {
}
}, [isHide])
useEffect(() => {
if (error) {
alert(error.message)
const onLogin = (values: { email: string; password: string }) => {
login({ username: values.email, password: values.password }, onLoginCallBack)
}
const onLoginCallBack = (isSuccess: boolean, message?: string) => {
if (isSuccess) {
showMessageSuccess("Login successfully!", 4000)
} else {
showMessageError(message || LANGUAGE.MESSAGE.ERROR)
}
}, [error])
}
return (
<section className={s.formAuthen}>
<div className={s.inner}>
<div className={s.body}>
<Inputcommon
placeholder="Email Address"
value={email}
onChange={(val) => setEmail(val.toString())}
type="email"
ref={emailRef}
/>
<Formik
initialValues={{
password: '',
email: '',
}}
validationSchema={DisplayingErrorMessagesSchema}
onSubmit={onLogin}
>
{({ errors, touched, isValid, submitForm }) => (
<Form className="u-form">
<div className="body">
<InputFiledInForm
name="email"
placeholder="Email Address"
ref={emailRef}
error={
touched.email && errors.email
? errors.email.toString()
: ''
}
isShowIconSuccess={touched.email && !errors.email}
/>
<InputPasswordFiledInForm
name="password"
placeholder="Password"
error={
touched.password && errors.password
? errors.password.toString()
: ''
}
onEnter={isValid ? submitForm : undefined}
/>
</div>
<div className={styles.bottom}>
<Link href={ROUTE.FORGOT_PASSWORD}>
<a href="" className={styles.forgotPassword}>
Forgot Password?
</a>
</Link>
<ButtonCommon HTMLType='submit' loading={loading} size="large">
Sign in
</ButtonCommon>
</div>
</Form>
)}
</Formik>
</div>
{/* <Inputcommon placeholder='Email Address' type='email' ref={emailRef}
isShowIconSuccess={true} isIconSuffix={true} /> */}
<InputPassword
placeholder="Password"
value={password}
onChange={(val) => setPassword(val.toString())}
/>
</div>
<div className={styles.bottom}>
<Link href={ROUTE.FORGOT_PASSWORD}>
<a href="" className={styles.forgotPassword}>
Forgot Password?
</a>
</Link>
<ButtonCommon onClick={onLogin} loading={loading} size="large">
Sign in
</ButtonCommon>
</div>
<SocialAuthen />
<div className={s.others}>
<span>Don't have an account?</span>

View File

@@ -33,7 +33,7 @@ const DisplayingErrorMessagesSchema = Yup.object().shape({
const FormRegister = ({ onSwitch, isHide }: Props) => {
const emailRef = useRef<CustomInputCommon>(null)
const { loading, signup, error } = useSignup()
const { loading, signup } = useSignup()
const { showMessageSuccess, showMessageError } = useMessage()
useEffect(() => {
@@ -54,12 +54,6 @@ const FormRegister = ({ onSwitch, isHide }: Props) => {
}
}
useEffect(() => {
if (error) {
alert(error.message)
}
}, [error])
return (
<section
className={classNames({

View File

@@ -5,6 +5,7 @@ import { CommonError } from 'src/domains/interfaces/CommonError'
import rawFetcher from 'src/utils/rawFetcher'
import { LoginMutation } from '@framework/schema'
import { LOCAL_STORAGE_KEY } from 'src/utils/constanst.utils'
import { errorMapping } from 'src/utils/errrorMapping'
const query = gql`
mutation login($username: String!, $password: String!) {
@@ -31,7 +32,9 @@ const useLogin = () => {
const [error, setError] = useState<CommonError | null>(null)
const { mutate } = useActiveCustomer()
const login = (options: LoginInput) => {
const login = (options: LoginInput,
fCallBack: (isSuccess: boolean, message?: string) => void
) => {
setError(null)
setLoading(true)
rawFetcher<LoginMutation>({
@@ -40,15 +43,19 @@ const useLogin = () => {
})
.then(({ data, headers }) => {
if (data.login.__typename !== 'CurrentUser') {
throw CommonError.create(data.login.message, data.login.errorCode)
throw CommonError.create(errorMapping(data.login.message), data.login.errorCode)
}
const authToken = headers.get('vendure-auth-token')
if (authToken != null) {
localStorage.setItem(LOCAL_STORAGE_KEY.TOKEN, authToken)
return mutate()
mutate()
}
fCallBack(true)
})
.catch((error) => {
setError(error)
fCallBack(false, error.message)
})
.catch(setError)
.finally(() => setLoading(false))
}

View File

@@ -0,0 +1,14 @@
import { LANGUAGE } from "./language.utils";
export function errorMapping(message?: string) {
if (!message) {
return LANGUAGE.MESSAGE.ERROR
}
switch (message) {
case 'The provided credentials are invalid':
return 'The email address or password is incorrect!'
default:
return LANGUAGE.MESSAGE.ERROR
}
}