Skip to content

Commit

Permalink
Merge pull request #36 from epigram5-9/feat/FE-63
Browse files Browse the repository at this point in the history
FE-63 ✨ 로그인 api 연동
  • Loading branch information
jangmoonwon authored Jul 18, 2024
2 parents bad3c27 + e4bebb9 commit 7da1e94
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 3 deletions.
30 changes: 30 additions & 0 deletions src/apis/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { PostSigninRequestType, PostSigninResponseType } from '@/schema/auth';
import { AxiosError } from 'axios';
import httpClient from '.';

const postSignin = async (request: PostSigninRequestType): Promise<PostSigninResponseType> => {
try {
const response = await httpClient.post('/auth/signIn', request);
return response.data;
} catch (error) {
if (error instanceof AxiosError) {
// Axios 에러인 경우
const axiosError = error as AxiosError;
if (axiosError.response) {
// 서버에서 응답이 온 경우 (예: 4xx, 5xx)
throw new Error('로그인 요청 처리 중 문제가 발생했습니다.');
} else if (axiosError.request) {
// 요청을 보냈지만 응답을 받지 못한 경우
throw new Error('서버 응답을 받지 못했습니다. 잠시 후 다시 시도해 주세요.');
} else {
// 요청을 설정하는 과정에서 문제가 발생한 경우
throw new Error('로그인 요청을 처리하는 동안 문제가 발생했습니다.');
}
} else {
// Axios 에러가 아닌 경우 (네트워크 문제 등)
throw new Error('알 수 없는 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.');
}
}
};

export default postSignin;
39 changes: 39 additions & 0 deletions src/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,42 @@ const httpClient = axios.create({
});

export default httpClient;

// NOTE: eslint-disable no-param-reassign 미해결로 인한 설정
httpClient.interceptors.request.use((config) => {
const accessToken = localStorage.getItem('accessToken');
/* eslint-disable no-param-reassign */
if (accessToken) config.headers.Authorization = `Bearer ${accessToken}`;
/* eslint-enable no-param-reassign */
return config;
});

httpClient.interceptors.response.use(
(response) => response,

(error) => {
if (error.response && error.response.status === 401) {
const refreshToken = localStorage.getItem('refreshToken');

if (!refreshToken) {
window.location.href = '/auth/SignIn';
} else {
httpClient
.post('/auth/refresh-token', null, {
headers: { Authorization: `Bearer ${refreshToken}` },
})
.then((response) => {
const { accessToken } = response.data;
const { refreshToken: newRefreshToken } = response.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', newRefreshToken);
})
.catch(() => {
window.location.href = '/auth/SignIn';
});
}
} else {
throw new Error(error.response.status);
}
},
);
20 changes: 20 additions & 0 deletions src/hooks/userQueryHooks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import postSignin from '@/apis/auth';
import quries from '@/apis/queries';
import { updateMe } from '@/apis/user';
import { GetUserReponseType, GetUserRequestType, PatchMeRequestType } from '@/schema/user';
import { MutationOptions } from '@/types/query';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';

export const useMeQuery = () => useQuery(quries.user.getMe());

Expand All @@ -21,3 +23,21 @@ export const useUpdateMe = (options: MutationOptions<GetUserReponseType>) => {
},
});
};

export const useSignin = () => {
const router = useRouter();

return useMutation({
mutationFn: postSignin,
onSuccess: (data) => {
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
router.push('/');
},
onError: (error) => {
// NOTE: 임시 테스트용 콘솔, 토스트 추가 예정
/* eslint-disable no-console */
console.error(error);
},
});
};
6 changes: 3 additions & 3 deletions src/pages/auth/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form';
import { PostSigninRequest, PostSigninRequestType } from '@/schema/auth';
import { useSignin } from '@/hooks/userQueryHooks';

export default function SignIn() {
const mutationSignin = useSignin();
// 폼 정의
const form = useForm<PostSigninRequestType>({
resolver: zodResolver(PostSigninRequest),
Expand All @@ -20,9 +22,7 @@ export default function SignIn() {
});

function onSubmit(values: PostSigninRequestType) {
// NOTE : 테스트를 위해서 콘솔 넣음
/* eslint-disable no-console */
console.log(values);
mutationSignin.mutate(values);
}

// TODO: 나중에 컴포넌트 분리하기
Expand Down
17 changes: 17 additions & 0 deletions src/schema/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,21 @@ export const PostSigninRequest = z.object({
password: z.string().min(1, { message: '비밀번호는 필수 입력입니다.' }),
});

const User = z.object({
id: z.number(),
email: z.string().email(),
nickname: z.string(),
teamId: z.string(),
updatedAt: z.coerce.date(),
createdAt: z.coerce.date(),
image: z.string(),
});

export const PostSigninResponse = z.object({
accessToken: z.string(),
refreshToken: z.string(),
user: User,
});

export type PostSigninRequestType = z.infer<typeof PostSigninRequest>;
export type PostSigninResponseType = z.infer<typeof PostSigninResponse>;

0 comments on commit 7da1e94

Please sign in to comment.