mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
✨ feat: login
:%s
This commit is contained in:
@@ -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 (
|
||||
|
@@ -63,12 +63,16 @@ const InputFiledInForm = forwardRef<Ref, Props>(({
|
||||
return <></>
|
||||
}, [icon, error, isShowIconSuccess])
|
||||
|
||||
const handleKeyDown = (e: any) => {
|
||||
if (e.key === KEY.ENTER && onEnter) {
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === KEY.ENTER) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
if (onEnter) {
|
||||
const value = inputElementRef.current?.value || ''
|
||||
onEnter(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@@ -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}
|
||||
/>
|
||||
|
@@ -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;
|
||||
|
@@ -40,7 +40,7 @@ const MessageItem = memo(
|
||||
|
||||
useEffect(() => {
|
||||
if (isHide && !isMouseOver && onRemove) {
|
||||
onRemove(id || 0)
|
||||
// onRemove(id || 0)
|
||||
}
|
||||
}, [isHide, isMouseOver, onRemove, id])
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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,30 +35,54 @@ 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}
|
||||
|
||||
{/* <Inputcommon placeholder='Email Address' type='email' ref={emailRef}
|
||||
isShowIconSuccess={true} isIconSuffix={true} /> */}
|
||||
<InputPassword
|
||||
>
|
||||
{({ 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"
|
||||
value={password}
|
||||
onChange={(val) => setPassword(val.toString())}
|
||||
error={
|
||||
touched.password && errors.password
|
||||
? errors.password.toString()
|
||||
: ''
|
||||
}
|
||||
onEnter={isValid ? submitForm : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.bottom}>
|
||||
@@ -61,10 +91,15 @@ const FormLogin = ({ onSwitch, isHide }: Props) => {
|
||||
Forgot Password?
|
||||
</a>
|
||||
</Link>
|
||||
<ButtonCommon onClick={onLogin} loading={loading} size="large">
|
||||
<ButtonCommon HTMLType='submit' loading={loading} size="large">
|
||||
Sign in
|
||||
</ButtonCommon>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
|
||||
<SocialAuthen />
|
||||
<div className={s.others}>
|
||||
<span>Don't have an account?</span>
|
||||
|
@@ -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({
|
||||
|
@@ -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))
|
||||
}
|
||||
|
||||
|
14
src/utils/errrorMapping.ts
Normal file
14
src/utils/errrorMapping.ts
Normal 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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user