From e64d1727911e054216fdb067f8dac355e5db8498 Mon Sep 17 00:00:00 2001 From: useonglee Date: Mon, 13 Jun 2022 21:54:11 +0900 Subject: [PATCH 1/3] =?UTF-8?q?#125=20feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20v2=20api=20=EB=AA=A8=EB=93=88=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/index.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/api/index.ts b/src/api/index.ts index 65e3a4b..c87e3c0 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -14,8 +14,8 @@ const createAxios = (): AxiosInstance => { return axios.create({ baseURL: `${BASE_URL}/api/v1`, headers: HEADERS }); }; -const createAxiosWithToken = (): AxiosInstance => { - const requestHTTP = axios.create({ baseURL: `${BASE_URL}/api/v1`, headers: HEADERS }); +const createAxiosWithToken = (version: string): AxiosInstance => { + const requestHTTP = axios.create({ baseURL: `${BASE_URL}/api/${version}`, headers: HEADERS, withCredentials: true }); return interceptors(requestHTTP); }; @@ -33,7 +33,25 @@ const createAxiosWithTokenInUpload = (): AxiosInstance => { export const axiosService = createAxios(); // With token -export const axiosWithToken = createAxiosWithToken(); +export const axiosWithToken = createAxiosWithToken('v1'); // With token export const axiosWithTokenInUpload = createAxiosWithTokenInUpload(); + +interface ApisType { + url: string; +} + +class Apis implements ApisType { + constructor(public url: string) { + this.url = url; + } + + async fetchUser(bodyData: bodyDataType) { + await createAxiosWithToken('v2').post(`/users/${this.url}`, bodyData); + } +} + +const api = (url: string) => new Apis(url); + +export default api; From c637201820f7ec908ee93ad94fefab04e89bd14b Mon Sep 17 00:00:00 2001 From: useonglee Date: Mon, 13 Jun 2022 21:55:30 +0900 Subject: [PATCH 2/3] =?UTF-8?q?#125=20feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20useLogin=20hook=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Login/useLogin.ts | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/components/Login/useLogin.ts diff --git a/src/components/Login/useLogin.ts b/src/components/Login/useLogin.ts new file mode 100644 index 0000000..5ebac93 --- /dev/null +++ b/src/components/Login/useLogin.ts @@ -0,0 +1,38 @@ +import { useState } from 'react'; +import { useRouter } from 'next/router'; + +import { LoginRequestDataType } from '@/types/login'; +import { FetchDataType } from '@/types/fetchData'; + +import api from '@api'; +import { useMutation } from 'react-query'; +import { AxiosError } from 'axios'; + +export default function useLogin() { + const router = useRouter(); + const [loginErrorMessage, setLoginErrorMessage] = useState(''); + + const { mutate: userLogin } = useMutation((loginData: LoginRequestDataType) => api('login').fetchUser(loginData), { + onMutate: () => { + setLoginErrorMessage(''); + }, + onSuccess: () => { + router.push('/'); + }, + onError: (error: AxiosError) => { + if (error.response) { + const { code, status, detail } = error.response.data; + + if (status === 404) { + setLoginErrorMessage(detail); + } + + if (code === 400) { + setLoginErrorMessage('아이디 또는 비밀번호가 올바르지 않습니다.'); + } + } + }, + }); + + return { userLogin, loginErrorMessage }; +} From da767e18f6a73d15bcfd94fbdd2663a3fa7a6aac Mon Sep 17 00:00:00 2001 From: useonglee Date: Mon, 13 Jun 2022 21:55:49 +0900 Subject: [PATCH 3/3] =?UTF-8?q?#125=20feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/login/index.tsx | 60 +++++++++++++-------------------------- 1 file changed, 19 insertions(+), 41 deletions(-) diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index a42c3bb..25ea33b 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -6,15 +6,14 @@ import { useRouter } from 'next/router'; import { Button, Input, Title, Text } from '@components/Common'; import Layout from '@components/Layout/Layout'; +import useLogin from '@components/Login/useLogin'; + import * as Styled from '@components/Layout/LayoutStyle'; -import * as SignupStyle from '@components/Signup/SignupPageStyle'; import { EMAIL_VALIDATION } from '@constants/validation'; import { LoginRequestDataType } from '@/types/login'; import { FormRegisterType } from '@/types/signup'; -import { useLoginMutation } from '@api/queries/users'; - function LoginPage() { const router = useRouter(); @@ -26,36 +25,9 @@ function LoginPage() { const [emailValue, setEmailValue] = useState(''); const [passwordValue, setPasswordValue] = useState(''); - const [isFormErrorState, setIsFormErrorState] = useState(false); - const [emailErrorMessage, setEmailErrorMessage] = useState(''); + const [noDataErrorMessage, setNoDataErrorMessage] = useState(''); - const loginMutation = useLoginMutation({ - onMutate: () => { - setIsFormErrorState(false); - setEmailErrorMessage(''); - }, - onSuccess: (data) => { - const { accessToken, refreshToken } = data.data.data; - localStorage.setItem('accessToken', accessToken); - localStorage.setItem('refreshToken', refreshToken); - - router.push('/'); - }, - onError: (error) => { - if (error.response) { - const { code, status, detail } = error.response.data; - - setIsFormErrorState(true); - if (status === 404) { - setEmailErrorMessage(detail); - } - - if (code === 400) { - setEmailErrorMessage('아이디 또는 비밀번호가 올바르지 않습니다.'); - } - } - }, - }); + const { userLogin, loginErrorMessage } = useLogin(); const handleLoginChangeValue = useCallback( (e: ChangeEvent, type: string) => { @@ -74,11 +46,10 @@ function LoginPage() { const handleLoginSubmit = useCallback( (data: LoginRequestDataType) => { - setEmailErrorMessage(''); + setNoDataErrorMessage(''); if ((data.email === '' || data.password === '') && passwordValue === '') { - setIsFormErrorState(true); - setEmailErrorMessage('이메일 또는 비밀번호를 입력해 주세요.'); + setNoDataErrorMessage('이메일 또는 비밀번호를 입력해 주세요.'); return; } @@ -87,11 +58,17 @@ function LoginPage() { password: passwordValue || data.password, }; - loginMutation.mutate(loginData); + userLogin(loginData); }, - [emailValue, passwordValue, isFormErrorState, emailErrorMessage] + [emailValue, passwordValue, noDataErrorMessage] ); + const handleErrorMessage = useCallback(() => { + const hasErrorMessage = !!errors.email?.message || !!noDataErrorMessage || !!loginErrorMessage; + + return hasErrorMessage; + }, [errors, noDataErrorMessage, loginErrorMessage]); + const handleSignupButton = () => { router.push('/signup'); }; @@ -110,7 +87,7 @@ function LoginPage() { value={emailValue} changeEvent={(e) => handleLoginChangeValue(e, 'email')} placeholderText="이메일을 입력해 주세요." - hasErrorDisplay={isFormErrorState || !!errors.email?.message} + hasErrorDisplay={handleErrorMessage()} margin="1.2rem" /> @@ -121,10 +98,11 @@ function LoginPage() { value={passwordValue} changeEvent={(e) => handleLoginChangeValue(e, 'password')} placeholderText="비밀번호를 입력해 주세요." - hasErrorDisplay={isFormErrorState || !!errors.email?.message} + hasErrorDisplay={handleErrorMessage()} /> - {errors && {errors.email?.message}} - {isFormErrorState && {emailErrorMessage}} + {errors && {errors.email?.message}} + {noDataErrorMessage && {noDataErrorMessage}} + {loginErrorMessage && {loginErrorMessage}}