@@ -2,20 +2,45 @@ import { useMutation } from "@tanstack/react-query";
22
33import type { AxiosError } from "axios" ;
44import { useRouter } from "next/navigation" ;
5+ import { SKIP_GLOBAL_ERROR_TOAST_META } from "@/lib/react-query/errorToastMeta" ;
56import { showIconToast } from "@/lib/toast/showIconToast" ;
67import useAuthStore from "@/lib/zustand/useAuthStore" ;
78import { getCommunityRedirectOrFallback } from "@/utils/authRedirect" ;
89import { type AuthRedirectOptions , authApi , type EmailLoginRequest , type EmailLoginResponse } from "./api" ;
910
11+ const EMAIL_LOGIN_FAILURE_MESSAGE = "이메일 또는 비밀번호를 확인해주세요." ;
12+ const EMAIL_LOGIN_REQUEST_FAILURE_MESSAGE = "로그인에 실패했습니다. 잠시 후 다시 시도해주세요." ;
13+
14+ type EmailLoginErrorResponse = {
15+ message ?: string ;
16+ } ;
17+
18+ const getEmailLoginErrorMessage = ( error : AxiosError < EmailLoginErrorResponse > ) => {
19+ const responseMessage = error . response ?. data ?. message ;
20+
21+ if ( responseMessage ) {
22+ return responseMessage ;
23+ }
24+
25+ if ( error . response ?. status === 401 ) {
26+ return EMAIL_LOGIN_FAILURE_MESSAGE ;
27+ }
28+
29+ return EMAIL_LOGIN_REQUEST_FAILURE_MESSAGE ;
30+ } ;
31+
1032/**
1133 * @description 이메일 로그인을 위한 useMutation 커스텀 훅
1234 */
1335const usePostEmailAuth = ( { redirectPath } : AuthRedirectOptions = { } ) => {
1436 const { setAccessToken } = useAuthStore ( ) ;
1537 const router = useRouter ( ) ;
1638
17- return useMutation < EmailLoginResponse , AxiosError , EmailLoginRequest > ( {
39+ return useMutation < EmailLoginResponse , AxiosError < EmailLoginErrorResponse > , EmailLoginRequest > ( {
1840 mutationFn : ( data ) => authApi . postEmailLogin ( data ) ,
41+ // 로그인 API는 publicAxiosInstance를 사용해 전역 401 인터셉터/토스트가 적용되지 않으므로
42+ // 전역 에러 토스트를 건너뛰고 이 mutation에서 직접 처리한다.
43+ meta : SKIP_GLOBAL_ERROR_TOAST_META ,
1944 onSuccess : ( data ) => {
2045 const { accessToken } = data ;
2146
@@ -31,6 +56,13 @@ const usePostEmailAuth = ({ redirectPath }: AuthRedirectOptions = {}) => {
3156 router . push ( getCommunityRedirectOrFallback ( redirectPath ) ) ;
3257 } , 100 ) ;
3358 } ,
59+ onError : ( error ) => {
60+ const message = getEmailLoginErrorMessage ( error ) ;
61+
62+ // 로그인 실패는 사용자가 자격증명을 고쳐 곧바로 재시도하는 경우가 많아
63+ // 동일 메시지 억제(dedupe)를 끄고 매 시도마다 토스트를 노출한다.
64+ showIconToast ( "logo" , message , { dedupe : false } ) ;
65+ } ,
3466 } ) ;
3567} ;
3668
0 commit comments