diff --git a/index.html b/index.html index 04388cf0..ce9b70c7 100644 --- a/index.html +++ b/index.html @@ -13,7 +13,7 @@ - + diff --git a/src/apis/api.ts b/src/apis/api.ts index 88eecaea..2a653607 100644 --- a/src/apis/api.ts +++ b/src/apis/api.ts @@ -39,13 +39,22 @@ export function del(...args: Parameters) { const fetchAccessToken = async (): Promise => { const refreshToken = localStorage.getItem('refreshToken'); + // 리프레시 토큰이 없는 경우 로그아웃 처리 + if (!refreshToken) { + console.error('리프레시 토큰이 없습니다. 로그아웃 처리합니다.'); + clearLocalStorage(); + window.location.href = '/login'; + return null; + } + try { const response = await axios.get>( - `${import.meta.env.VITE_APP_BASE_URL}/v1/user/token-refresh?refreshToken=${refreshToken}` + `${import.meta.env.VITE_APP_BASE_URL}/v1/user/token-refresh?refreshToken=${encodeURIComponent(refreshToken)}` ); const accessToken = response.data.data.accessToken; if (!accessToken) { + console.error('액세스 토큰을 받지 못했습니다.'); return null; } localStorage.setItem('accessToken', accessToken); @@ -54,15 +63,17 @@ const fetchAccessToken = async (): Promise => { } catch (error) { console.error('토큰 재발급 실패:', error); - const errorData = (error as AxiosError)?.response?.data as ErrorType; + const axiosError = error as AxiosError; + const errorData = axiosError.response?.data; // 리프레시 토큰 만료 시. 로그아웃 처리 - if (errorData.status === 40101) { + if (errorData?.status === 40101) { console.error('리프레시 토큰 만료:', errorData); clearLocalStorage(); window.location.href = '/login'; return Promise.reject(error); } + return null; } }; @@ -70,12 +81,14 @@ const fetchAccessToken = async (): Promise => { instance.interceptors.response.use( (response) => response, // 성공적인 응답은 그대로 반환 async (error) => { - const errorData = error?.response.data; + const status = error?.response?.status; + const errorData = error?.response?.data; const accessToken = localStorage.getItem('accessToken'); - if (errorData && errorData.status && accessToken) { - // 액세스 토큰 만료 시. 리프레시 토큰으로 재발급 시도 - if (errorData.status === 40100) { + // 401 계열 에러 처리 + if (status === 401) { + // 40100인 경우에만 리프레시 토큰을 사용한 재발급 로직 실행 + if (errorData?.status === 40100 && accessToken) { const originalRequest = error.config; try { @@ -91,6 +104,12 @@ instance.interceptors.response.use( console.error('토큰 갱신 후 재시도 실패:', tokenError); return Promise.reject(tokenError); } + } else { + // 그 외의 40101, 40102, 40103, 40104 에러는 로그아웃 처리 + console.error('인증 에러'); + clearLocalStorage(); + window.location.href = '/login'; + return; } } diff --git a/src/pages/classList/page/ClassList/ClassList.tsx b/src/pages/classList/page/ClassList/ClassList.tsx index 01734c63..c4d8b0f1 100644 --- a/src/pages/classList/page/ClassList/ClassList.tsx +++ b/src/pages/classList/page/ClassList/ClassList.tsx @@ -86,12 +86,27 @@ const ClassList = () => { if (categoriesRef.current) { const selectedIndex = (categories ?? []).indexOf(selectedCategory); setTimeout(() => { - if (selectedIndex < 5) { + if (selectedIndex === 4) { + if (categoriesRef.current?.scrollLeft === 0) { + categoriesRef.current?.scrollTo({ + left: 353, + // left: categoriesRef.current?.scrollWidth, + behavior: 'smooth', + }); + } else { + categoriesRef.current?.scrollTo({ + left: 30, + behavior: 'smooth', + }); + } + } + + if (selectedIndex < 4) { categoriesRef.current?.scrollTo({ left: 0, behavior: 'smooth', }); - } else { + } else if (selectedIndex > 4) { categoriesRef.current?.scrollTo({ left: categoriesRef.current?.scrollWidth, behavior: 'smooth', @@ -127,8 +142,6 @@ const ClassList = () => { return ; } - console.log(categories); - return ( <> diff --git a/src/pages/myPage/page/HostMyPage/HostMyPage.tsx b/src/pages/myPage/page/HostMyPage/HostMyPage.tsx index a3086dd0..38460ff1 100644 --- a/src/pages/myPage/page/HostMyPage/HostMyPage.tsx +++ b/src/pages/myPage/page/HostMyPage/HostMyPage.tsx @@ -1,4 +1,3 @@ -import { useAtom } from 'jotai'; import { useEffect, useState } from 'react'; import { useFetchMyHost } from '@apis/domains/moim/useFetchMyHost'; @@ -10,7 +9,6 @@ import { Error } from '@pages/error'; import { ApprovalReviewingView, HostMyPageEmptyView } from '@pages/myPage/components'; import HostInfoCardWithLink from '@pages/myPage/components/HostInfoCardWithLink/HostInfoCardWithLink'; import LogoutModal from '@pages/myPage/components/LogoutModal/LogoutModal'; -import { userAtom } from '@stores'; import { IcNext } from '@svg'; import { clearLocalStorage } from '@utils'; @@ -27,7 +25,7 @@ import { } from './HostMyPage.style'; import { components } from '@schema'; -import { ErrorType } from '@types'; +import { ErrorType, localStorageUserType } from '@types'; type HostGetResponse = components['schemas']['HostGetResponse']; @@ -48,13 +46,14 @@ const isErrorResponseType = (data: unknown): data is ErrorType => { } return false; }; + const HostMyPage = () => { - const [user] = useAtom(userAtom); const { data: hostInfoResponse, isSuccess, isLoading } = useFetchMyHost(); const { goGuestMyPage } = useEasyNavigate(); const [isModalOpen, setIsModalOpen] = useState(false); - const { hostId: jotaiHostId, hostNickname: jotaiHostNickname } = user; + const localStorageUser: localStorageUserType = JSON.parse(localStorage.getItem('user') || '{}'); + const { hostId: localStorageHostId, hostNickname: localStorageHostNickname } = localStorageUser; let hostInfoData: HostGetResponse | null = null; let errorData: ErrorType | null = null; @@ -84,7 +83,7 @@ const HostMyPage = () => { }; useEffect(() => { - if (isSuccess && hostInfoData && !jotaiHostId && !jotaiHostNickname) { + if (isSuccess && hostInfoData && !localStorageHostId && !localStorageHostNickname) { const { hostId, hostNickName } = hostInfoData; const isFirstApproval = hostId && hostNickName; if (isFirstApproval) { @@ -94,7 +93,7 @@ const HostMyPage = () => { window.location.href = '/login'; } } - }, [isSuccess, hostInfoData, jotaiHostId, jotaiHostNickname]); + }, [isSuccess, hostInfoData, localStorageHostId, localStorageHostNickname]); return ( <> diff --git a/src/types/commonType.ts b/src/types/commonType.ts index a54b4c2b..d31c047b 100644 --- a/src/types/commonType.ts +++ b/src/types/commonType.ts @@ -30,3 +30,10 @@ export type MoimIdPathParameterType = { export type NoticeIdPathParameterType = { noticeId: string; }; + +export interface localStorageUserType { + guestId: number; + guestNickname: string; + hostId: number; + hostNickname: string; +}