Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand All @@ -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<bodyDataType>(bodyData: bodyDataType) {
await createAxiosWithToken('v2').post(`/users/${this.url}`, bodyData);
}
}

const api = (url: string) => new Apis(url);

export default api;
38 changes: 38 additions & 0 deletions src/components/Login/useLogin.ts
Original file line number Diff line number Diff line change
@@ -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<string>('');

const { mutate: userLogin } = useMutation((loginData: LoginRequestDataType) => api('login').fetchUser(loginData), {
onMutate: () => {
setLoginErrorMessage('');
},
onSuccess: () => {
router.push('/');
},
onError: (error: AxiosError<FetchDataType>) => {
if (error.response) {
const { code, status, detail } = error.response.data;

if (status === 404) {
setLoginErrorMessage(detail);
}

if (code === 400) {
setLoginErrorMessage('아이디 또는 비밀번호가 올바르지 않습니다.');
}
}
},
});

return { userLogin, loginErrorMessage };
}
60 changes: 19 additions & 41 deletions src/pages/login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -26,36 +25,9 @@ function LoginPage() {

const [emailValue, setEmailValue] = useState<string>('');
const [passwordValue, setPasswordValue] = useState<string>('');
const [isFormErrorState, setIsFormErrorState] = useState<boolean>(false);
const [emailErrorMessage, setEmailErrorMessage] = useState<string>('');
const [noDataErrorMessage, setNoDataErrorMessage] = useState<string>('');

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<HTMLInputElement>, type: string) => {
Expand All @@ -74,11 +46,10 @@ function LoginPage() {

const handleLoginSubmit = useCallback(
(data: LoginRequestDataType) => {
setEmailErrorMessage('');
setNoDataErrorMessage('');

if ((data.email === '' || data.password === '') && passwordValue === '') {
setIsFormErrorState(true);
setEmailErrorMessage('이메일 또는 비밀번호를 입력해 주세요.');
setNoDataErrorMessage('이메일 또는 비밀번호를 입력해 주세요.');
return;
}

Expand All @@ -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');
};
Expand All @@ -110,7 +87,7 @@ function LoginPage() {
value={emailValue}
changeEvent={(e) => handleLoginChangeValue(e, 'email')}
placeholderText="이메일을 입력해 주세요."
hasErrorDisplay={isFormErrorState || !!errors.email?.message}
hasErrorDisplay={handleErrorMessage()}
margin="1.2rem"
/>
<label>Password</label>
Expand All @@ -121,10 +98,11 @@ function LoginPage() {
value={passwordValue}
changeEvent={(e) => handleLoginChangeValue(e, 'password')}
placeholderText="비밀번호를 입력해 주세요."
hasErrorDisplay={isFormErrorState || !!errors.email?.message}
hasErrorDisplay={handleErrorMessage()}
/>
{errors && <SignupStyle.ErrorMessage>{errors.email?.message}</SignupStyle.ErrorMessage>}
{isFormErrorState && <Text hasError={isFormErrorState}>{emailErrorMessage}</Text>}
{errors && <Text hasError={!!errors.email?.message}>{errors.email?.message}</Text>}
{noDataErrorMessage && <Text hasError={!!noDataErrorMessage}>{noDataErrorMessage}</Text>}
{loginErrorMessage && <Text hasError={!!loginErrorMessage}>{loginErrorMessage}</Text>}

<Button type="submit" margin="3.6rem 0 0 0">
로그인
Expand Down