diff --git a/src/apis/groups.api.ts b/src/apis/groups.api.ts index b00b19a0..54772f37 100644 --- a/src/apis/groups.api.ts +++ b/src/apis/groups.api.ts @@ -9,34 +9,26 @@ import { Task } from '@/types/tasks.types'; import { axiosInstance } from './_axiosInstance'; export const getGroup = async (id: number) => { - try { - const response = await axiosInstance({ - method: 'GET', - url: `groups/${id}`, - }); - return response.data; - } catch (error) { - throw new Error('팀 정보를 가져오는 데 실패했습니다.'); - } + const response = await axiosInstance({ + method: 'GET', + url: `groups/${id}`, + }); + return response.data; }; export const postGroup = async ({ name, image }: PostGroupRequest) => { - try { - const response = await axiosInstance.post( - 'groups', - { name, image }, - { - headers: { - 'Content-Type': 'application/json', - }, - } - ); - const body = response.data; + const response = await axiosInstance.post( + 'groups', + { name, image }, + { + headers: { + 'Content-Type': 'application/json', + }, + } + ); + const body = response.data; - return body; - } catch (error) { - throw new Error('팀 생성하는 데 실패했습니다.'); - } + return body; }; export const patchGroup = async ({ id, name, image }: UpdateGroupRequest) => { @@ -63,22 +55,18 @@ export async function postInviteGroup({ userEmail, token, }: InviteGroupRequest) { - try { - const response = await axiosInstance.post( - 'groups/accept-invitation', - { userEmail, token }, - { - headers: { - 'Content-Type': 'application/json', - }, - } - ); - const body = response.data; + const response = await axiosInstance.post( + 'groups/accept-invitation', + { userEmail, token }, + { + headers: { + 'Content-Type': 'application/json', + }, + } + ); + const body = response.data; - return body; - } catch (error) { - throw new Error('그룹 참여에 실패했습니다.'); - } + return body; } export const getInviteGroup = async (id: number) => { @@ -90,44 +78,32 @@ export const getInviteGroup = async (id: number) => { }; export const postTaskList = async (groupId: number, name: string) => { - try { - const response = await axiosInstance({ - method: 'POST', - url: `/groups/${groupId}/task-lists`, - data: { name }, - headers: { - 'Content-Type': 'application/json', - }, - }); - return response.data; - } catch (error) { - throw new Error('할 일 목록를 생성하는 데 실패했습니다.'); - } + const response = await axiosInstance({ + method: 'POST', + url: `/groups/${groupId}/task-lists`, + data: { name }, + headers: { + 'Content-Type': 'application/json', + }, + }); + return response.data; }; export async function getTasks(id: number, date: string) { - try { - const response = await axiosInstance({ - method: 'GET', - url: `groups/${id}/tasks`, - data: { date }, - headers: { - 'Content-Type': 'application/json', - }, - }); - return response.data; - } catch (error) { - throw new Error('할 일을 불러오는 데 실패했습니다.'); - } + const response = await axiosInstance({ + method: 'GET', + url: `groups/${id}/tasks`, + data: { date }, + headers: { + 'Content-Type': 'application/json', + }, + }); + return response.data; } export async function deleteMember(groupId: number, memberUserId: number) { - try { - await axiosInstance({ - method: 'DELETE', - url: `groups/${groupId}/member/${memberUserId}`, - }); - } catch (error) { - throw new Error('멤버 삭제에 실패했습니다.'); - } + await axiosInstance({ + method: 'DELETE', + url: `groups/${groupId}/member/${memberUserId}`, + }); } diff --git a/src/apis/taskList.api.ts b/src/apis/taskList.api.ts index b8b7ef5a..cdaced62 100644 --- a/src/apis/taskList.api.ts +++ b/src/apis/taskList.api.ts @@ -2,32 +2,24 @@ import { TaskList } from '@/types/tasklist.types'; import { axiosInstance } from './_axiosInstance'; export const postTaskList = async (groupId: number, name: string) => { - try { - const response = await axiosInstance({ - method: 'POST', - url: `/groups/${groupId}/task-lists`, - data: { name }, - headers: { - 'Content-Type': 'application/json', - }, - }); - return response.data; - } catch (error) { - throw new Error('할 일 목록를 생성하는 데 실패했습니다.'); - } + const response = await axiosInstance({ + method: 'POST', + url: `/groups/${groupId}/task-lists`, + data: { name }, + headers: { + 'Content-Type': 'application/json', + }, + }); + return response.data; }; export const deleteTaskList = async (groupId: number, taskListId: number) => { - try { - const response = await axiosInstance({ - method: 'DELETE', - url: `/groups/${groupId}/task-lists/${taskListId}`, - headers: { - 'Content-Type': 'application/json', - }, - }); - return response; - } catch (error) { - throw new Error(''); - } + const response = await axiosInstance({ + method: 'DELETE', + url: `/groups/${groupId}/task-lists/${taskListId}`, + headers: { + 'Content-Type': 'application/json', + }, + }); + return response; }; diff --git a/src/hooks/useGlobalErrorHandler.ts b/src/hooks/useGlobalErrorHandler.ts new file mode 100644 index 00000000..716a489f --- /dev/null +++ b/src/hooks/useGlobalErrorHandler.ts @@ -0,0 +1,21 @@ +import { useToast } from '@/hooks/useToast'; +import axios, { AxiosError } from 'axios'; + +export const useGlobalErrorHandler = () => { + const { toast } = useToast(); + + return (error: AxiosError | Error, title: string) => { + let errorMessage = '알 수 없는 에러가 발생했습니다.'; + + if (axios.isAxiosError(error)) { + errorMessage = error.response?.data?.message as string; + } else { + errorMessage = error.message; + } + toast({ + title, + description: errorMessage, + variant: 'destructive', + }); + }; +}; diff --git a/src/queries/article.queries.ts b/src/queries/article.queries.ts index 37476672..29187335 100644 --- a/src/queries/article.queries.ts +++ b/src/queries/article.queries.ts @@ -19,6 +19,7 @@ import { UpdateArticleParams, } from '@/types/dto/requests/article.request.types'; // eslint-disable-next-line max-len +import { useGlobalErrorHandler } from '@/hooks/useGlobalErrorHandler'; import { toast } from '@/hooks/useToast'; import { ArticleCommentListResponse, @@ -95,7 +96,7 @@ export const useUpdateArticleMutation = ( orderBy: string ) => { const queryClient = useQueryClient(); - + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (data: UpdateArticleParams) => updateArticle(articleId, data), onSuccess: () => { @@ -112,12 +113,7 @@ export const useUpdateArticleMutation = ( title: '게시글 수정에 성공하였습니다.', }); }, - onError: () => { - toast({ - title: '게시글 수정에 실패하였습니다.', - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '게시글 수정에 실패하였습니다.'), }); }; @@ -127,6 +123,7 @@ export const useDeleteArticleMutation = ( orderBy: string ) => { const queryClient = useQueryClient(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: () => deleteArticle(articleId), onSuccess: () => { @@ -140,12 +137,7 @@ export const useDeleteArticleMutation = ( title: '게시글 삭제에 성공하였습니다.', }); }, - onError: () => { - toast({ - title: '게시글 삭제에 실패하였습니다.', - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '게시글 삭제에 실패하였습니다.'), }); }; diff --git a/src/queries/comments.queries.ts b/src/queries/comments.queries.ts index 1425416b..789b60ad 100644 --- a/src/queries/comments.queries.ts +++ b/src/queries/comments.queries.ts @@ -4,6 +4,7 @@ import { getComments, updateComment, } from '@/apis/comments.api'; +import { useGlobalErrorHandler } from '@/hooks/useGlobalErrorHandler'; import { useToast } from '@/hooks/useToast'; import { commentsQueryKeys } from '@/queries/keys/comments.keys'; import { @@ -30,7 +31,7 @@ export const useGetComments = (params: GetCommentsRequest) => { export const useAddComment = () => { const queryClient = useQueryClient(); - const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: AddCommentRequest) => addComment(params), onSuccess: (_, params) => { @@ -45,19 +46,14 @@ export const useAddComment = () => { }), }); }, - onError: (error) => { - toast({ - title: '댓글 추가를 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '댓글 추가를 실패했습니다.'), }); }; export const useUpdateComment = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: UpdateCommentRequest) => updateComment(params), onSuccess: (_, params) => { @@ -68,19 +64,14 @@ export const useUpdateComment = () => { title: '댓글을 수정했습니다.', }); }, - onError: (error) => { - toast({ - title: '댓글 수정을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '댓글 수정을 실패했습니다.'), }); }; export const useDeleteComment = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: DeleteCommentRequest) => deleteComment(params), onSuccess: (_, params) => { @@ -98,12 +89,6 @@ export const useDeleteComment = () => { title: '댓글을 삭제했습니다.', }); }, - onError: (error) => { - toast({ - title: '댓글 삭제를 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '댓글 수정을 실패했습니다.'), }); }; diff --git a/src/queries/groups.queries.ts b/src/queries/groups.queries.ts index 92040c2a..29d4178a 100644 --- a/src/queries/groups.queries.ts +++ b/src/queries/groups.queries.ts @@ -8,6 +8,7 @@ import { postGroup, postInviteGroup, } from '@/apis/groups.api'; +import { useGlobalErrorHandler } from '@/hooks/useGlobalErrorHandler'; import { useToast } from '@/hooks/useToast'; import { InviteGroupRequest, @@ -34,6 +35,7 @@ export const useTeamQuery = (id: number) => { export const usePatchTeamMutation = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: ({ id, name, image }: UpdateGroupRequest) => patchGroup({ id, name, ...(image && { image }) }), @@ -45,13 +47,7 @@ export const usePatchTeamMutation = () => { title: '해당 팀을 수정했습니다.', }); }, - onError: (error) => { - toast({ - title: '팀 수정을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '팀 수정을 실패했습니다.'), }); }; @@ -59,6 +55,7 @@ export const useDeleteTeamMutation = () => { const queryClient = useQueryClient(); const router = useRouter(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (id: number) => deleteGroup(id), onSuccess: () => { @@ -70,19 +67,14 @@ export const useDeleteTeamMutation = () => { }); router.push('/'); }, - onError: (error) => { - toast({ - title: '팀 삭제에 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '팀 삭제를 실패했습니다.'), }); }; export const useTeamMutation = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: PostGroupRequest) => postGroup(params), onSuccess: () => { @@ -96,19 +88,14 @@ export const useTeamMutation = () => { title: '해당 팀을 생성했습니다.', }); }, - onError: (error) => { - toast({ - title: '팀 생성을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '팀 생성을 실패했습니다.'), }); }; export const useInviteGroupMutation = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: ({ userEmail, token }: InviteGroupRequest) => postInviteGroup({ userEmail, token }), @@ -120,13 +107,7 @@ export const useInviteGroupMutation = () => { title: '팀 참여 완료.', }); }, - onError: (error) => { - toast({ - title: '팀 참여에 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '팀 참여에 실패했습니다.'), }); }; @@ -149,6 +130,7 @@ export const useTasksQuery = (params: { id: number; date: string }) => { export const useDeleteMember = () => { const { toast } = useToast(); const queryClient = useQueryClient(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: { groupId: number; memberUserId: number }) => deleteMember(params.groupId, params.memberUserId), @@ -160,12 +142,6 @@ export const useDeleteMember = () => { title: '해당 멤버를 삭제했습니다.', }); }, - onError: (error) => { - toast({ - title: '멤버 삭제할 수 없습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '해당 멤버를 삭제할 수 없습니다.'), }); }; diff --git a/src/queries/taskList.queries.ts b/src/queries/taskList.queries.ts index 24f9b346..4922162c 100644 --- a/src/queries/taskList.queries.ts +++ b/src/queries/taskList.queries.ts @@ -1,4 +1,5 @@ import { deleteTaskList, postTaskList } from '@/apis/taskList.api'; +import { useGlobalErrorHandler } from '@/hooks/useGlobalErrorHandler'; import { useToast } from '@/hooks/useToast'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { groupsQueryKeys } from './keys/groups.key'; @@ -6,6 +7,7 @@ import { groupsQueryKeys } from './keys/groups.key'; export const useTaskListMutation = () => { const { toast } = useToast(); const queryClient = useQueryClient(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: { groupId: number; name: string }) => { if (!params.name.trim()) { @@ -27,19 +29,14 @@ export const useTaskListMutation = () => { description: '새 목록이 생성되었습니다', }); }, - onError: (err) => { - toast({ - title: '목록생성 실패', - description: err.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '목록생성 실패'), }); }; export const useDeleteTaskList = () => { const { toast } = useToast(); const queryClient = useQueryClient(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: (params: { groupId: number; taskListId: number }) => deleteTaskList(params.groupId, params.taskListId), @@ -52,12 +49,6 @@ export const useDeleteTaskList = () => { queryKey: groupsQueryKeys.groups(params.groupId), }); }, - onError: (err) => { - toast({ - title: '목록삭제 실패', - description: err.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '목록생성 실패.'), }); }; diff --git a/src/queries/tasks.queries.ts b/src/queries/tasks.queries.ts index 333831d3..a4b98a4d 100644 --- a/src/queries/tasks.queries.ts +++ b/src/queries/tasks.queries.ts @@ -6,6 +6,7 @@ import { updateTask, updateTaskStatus, } from '@/apis/tasks.api'; +import { useGlobalErrorHandler } from '@/hooks/useGlobalErrorHandler'; import { useToast } from '@/hooks/useToast'; import { AddTaskRequest, @@ -39,7 +40,7 @@ export const useTaskDetail = (params: GetTaskDetailRequest) => { export const useAddTask = () => { const queryClient = useQueryClient(); const { toast } = useToast(); - + const handleError = useGlobalErrorHandler(); return useMutation({ onMutate: (params) => { if (params.frequencyType === FrequencyType.Weekly) { @@ -72,19 +73,14 @@ export const useAddTask = () => { queryKey: groupsQueryKeys.groups(params.groupId), }); }, - onError: (error) => { - toast({ - title: '할 일 추가를 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '할 일 추가를 실패했습니다.'), }); }; export const useUpdateTask = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: async (params: UpdateTaskRequest) => updateTask(params), onSuccess: (_, params) => { @@ -109,19 +105,13 @@ export const useUpdateTask = () => { queryKey: groupsQueryKeys.groups(params.groupId), }); }, - onError: (error) => { - toast({ - title: '할 일 수정을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '할 일 수정을 실패했습니다.'), }); }; export const useUpdateTaskStatus = () => { const queryClient = useQueryClient(); - const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: async (params: UpdateTaskStatusRequest) => updateTaskStatus(params), @@ -168,11 +158,7 @@ export const useUpdateTaskStatus = () => { context.previousTasks ); } - toast({ - title: '할 일 상태 수정을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); + handleError(error, '할 일 상태 수정을 실패했습니다.'); }, onSettled: (_, error, params) => { queryClient.invalidateQueries({ @@ -202,6 +188,7 @@ export const useUpdateTaskStatus = () => { export const useDeleteTask = () => { const queryClient = useQueryClient(); const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: async (params: DeleteTaskRequest) => deleteTask(params), onSuccess: (_, params) => { @@ -219,12 +206,6 @@ export const useDeleteTask = () => { queryKey: groupsQueryKeys.groups(params.groupId), }); }, - onError: (error) => { - toast({ - title: '할 일 삭제를 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '할 일 삭제를 실패했습니다.'), }); }; diff --git a/src/queries/users.queries.ts b/src/queries/users.queries.ts index 4934bad0..dd5528c5 100644 --- a/src/queries/users.queries.ts +++ b/src/queries/users.queries.ts @@ -5,6 +5,7 @@ import { resetPassword, sendResetPasswordEmail, } from '@/apis/users.api'; +import { useGlobalErrorHandler } from '@/hooks/useGlobalErrorHandler'; import { useToast } from '@/hooks/useToast'; import { useAuthStore } from '@/store/useAuthStore'; import { @@ -44,6 +45,7 @@ export const useGetMemberships = () => { export const useSendResetPasswordEmail = () => { const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: async (params: SendResetPasswordEmailRequest) => sendResetPasswordEmail(params), @@ -52,18 +54,14 @@ export const useSendResetPasswordEmail = () => { title: response.message, }); }, - onError: (error) => { - toast({ - title: '비밀번호 재설정 메일 전송을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => + handleError(error, '비밀번호 재설정 메일 전송을 실패했습니다.'), }); }; export const useResetPassword = () => { const { toast } = useToast(); + const handleError = useGlobalErrorHandler(); return useMutation({ mutationFn: async (params: ResetPasswordRequest) => resetPassword(params), onSuccess: (response) => { @@ -72,13 +70,7 @@ export const useResetPassword = () => { description: response.message, }); }, - onError: (error) => { - toast({ - title: '비밀번호 재설정을 실패했습니다.', - description: error.message, - variant: 'destructive', - }); - }, + onError: (error) => handleError(error, '비밀번호 재설정을 실패했습니다.'), }); };