|
1 | 1 | "use client"; |
2 | 2 |
|
| 3 | +import type { AxiosError } from "axios"; |
3 | 4 | import { useRouter } from "next/navigation"; |
4 | | -import { useEffect, useState } from "react"; |
5 | | -import { postReissueToken } from "@/apis/Auth"; |
| 5 | +import { useEffect } from "react"; |
| 6 | +import { useGetMyInfo } from "@/apis/MyPage"; |
6 | 7 | import CloudSpinnerPage from "@/components/ui/CloudSpinnerPage"; |
7 | 8 | import useAuthStore from "@/lib/zustand/useAuthStore"; |
8 | 9 | import { UserRole } from "@/types/mentor"; |
9 | | -import { isTokenExpired } from "@/utils/jwtUtils"; |
10 | 10 | import MenteePage from "./_ui/MenteePage"; |
11 | 11 | import MentorPage from "./_ui/MentorPage"; |
12 | 12 |
|
13 | 13 | const MentorClient = () => { |
14 | 14 | const router = useRouter(); |
15 | | - const { isLoading, accessToken, clientRole, isInitialized, refreshStatus, setRefreshStatus } = useAuthStore(); |
16 | | - const [isRefreshing, setIsRefreshing] = useState(false); |
17 | | - const hasValidAccessToken = Boolean(accessToken && !isTokenExpired(accessToken)); |
| 15 | + const clientRole = useAuthStore((state) => state.clientRole); |
| 16 | + const { data: myInfo, isLoading, isFetching, isError, error, refetch } = useGetMyInfo(); |
| 17 | + const role = myInfo?.role; |
| 18 | + const status = (error as AxiosError | null)?.response?.status; |
| 19 | + const isUnauthorized = status === 401 || status === 403; |
| 20 | + const isAuthResolving = isLoading || (isFetching && !role); |
18 | 21 |
|
19 | | - // 토큰 재발급 로직 |
20 | 22 | useEffect(() => { |
21 | | - const attemptTokenRefresh = async () => { |
22 | | - // 이미 실패한 경우 재시도하지 않음 (무한 루프 방지) |
23 | | - if (refreshStatus === "failed") { |
24 | | - return; |
25 | | - } |
| 23 | + if (isAuthResolving) return; |
| 24 | + if (isUnauthorized || (!isError && !role)) { |
| 25 | + router.replace("/login"); |
| 26 | + } |
| 27 | + }, [isAuthResolving, isUnauthorized, isError, role, router]); |
26 | 28 |
|
27 | | - // 초기화 이후 유효한 access token이 없을 때만 재발급 시도 |
28 | | - if (!isInitialized || hasValidAccessToken || isRefreshing || refreshStatus === "refreshing") { |
29 | | - return; |
30 | | - } |
31 | | - |
32 | | - setIsRefreshing(true); |
33 | | - setRefreshStatus("refreshing"); |
34 | | - |
35 | | - try { |
36 | | - await postReissueToken(); |
37 | | - setRefreshStatus("success"); |
38 | | - } catch { |
39 | | - // 재발급 실패 시 로그인 페이지로 리다이렉트 |
40 | | - setRefreshStatus("failed"); |
41 | | - router.push("/login"); |
42 | | - } finally { |
43 | | - setIsRefreshing(false); |
44 | | - } |
45 | | - }; |
46 | | - |
47 | | - attemptTokenRefresh(); |
48 | | - }, [isInitialized, hasValidAccessToken, isRefreshing, refreshStatus, setRefreshStatus, router]); |
49 | | - |
50 | | - // 초기화 전이거나 로딩 중이거나 재발급 중일 때 스피너 표시 |
51 | | - if (!isInitialized || isLoading || refreshStatus === "refreshing" || isRefreshing) { |
| 29 | + if (isAuthResolving) { |
52 | 30 | return <CloudSpinnerPage />; |
53 | 31 | } |
54 | 32 |
|
55 | | - // 초기화 완료 후에도 토큰이 없으면 리다이렉트 (useEffect에서 처리되지만 fallback) |
56 | | - if (!hasValidAccessToken) { |
| 33 | + if (isUnauthorized || (!isError && !role)) { |
57 | 34 | return <CloudSpinnerPage />; |
58 | 35 | } |
59 | 36 |
|
60 | | - if (!clientRole) { |
61 | | - return <CloudSpinnerPage />; |
| 37 | + if (isError) { |
| 38 | + return ( |
| 39 | + <div className="flex min-h-[40vh] flex-col items-center justify-center gap-3 px-4 text-center"> |
| 40 | + <p className="text-k-700 typo-medium-2">멘토 페이지 정보를 불러오지 못했어요.</p> |
| 41 | + <button |
| 42 | + type="button" |
| 43 | + onClick={() => refetch()} |
| 44 | + className="rounded-full bg-primary px-4 py-2 text-white typo-medium-2" |
| 45 | + > |
| 46 | + 다시 시도 |
| 47 | + </button> |
| 48 | + </div> |
| 49 | + ); |
| 50 | + } |
| 51 | + |
| 52 | + if (role === UserRole.ADMIN) { |
| 53 | + return clientRole === UserRole.MENTEE ? <MenteePage /> : <MentorPage />; |
62 | 54 | } |
63 | 55 |
|
64 | | - return clientRole === UserRole.MENTOR ? <MentorPage /> : <MenteePage />; |
| 56 | + return role === UserRole.MENTOR ? <MentorPage /> : <MenteePage />; |
65 | 57 | }; |
66 | 58 |
|
67 | 59 | export default MentorClient; |
0 commit comments