fromis_9/frontend-temp/src/hooks/useAdminAuth.js
caadiq 27c41b0af0 feat(frontend): Phase 5 - 커스텀 훅 구현
- useMediaQuery, useIsMobile, useIsDesktop: 반응형 레이아웃
- useScheduleData, useCategories: 스케줄/카테고리 데이터 조회
- useScheduleSearch: 무한 스크롤 검색
- useScheduleFiltering, useCategoryCounts: 필터링 및 정렬
- useCalendar: 캘린더 로직 (월 이동, 날짜 선택)
- useAdminAuth: 토큰 검증 및 리다이렉트
- utils/schedule.js: 스케줄 유틸리티 함수 추가
- constants: SEARCH_LIMIT, MIN_YEAR, MONTH_NAMES 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 17:22:38 +09:00

72 lines
2.1 KiB
JavaScript

import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { useAuthStore } from '@/stores';
import { authApi } from '@/api';
/**
* 어드민 인증 훅
* 토큰 유효성 검증 및 미인증 시 리다이렉트
* @param {object} options - 옵션
* @param {string} options.redirectTo - 미인증 시 리다이렉트 경로 (기본: /admin)
* @param {boolean} options.required - 인증 필수 여부 (기본: true)
*/
export function useAdminAuth(options = {}) {
const { redirectTo = '/admin', required = true } = options;
const navigate = useNavigate();
const { token, user, logout, isAuthenticated } = useAuthStore();
// 토큰 검증 쿼리
const { data, isLoading, isError } = useQuery({
queryKey: ['admin', 'auth'],
queryFn: authApi.verifyToken,
enabled: !!token,
retry: false,
staleTime: 1000 * 60 * 5, // 5분 캐시
});
// 토큰 없거나 검증 실패 시 처리
// 리다이렉트는 DOM 조작이므로 useEffect 사용 허용
useEffect(() => {
if (required && (!token || isError)) {
logout();
navigate(redirectTo);
}
}, [token, isError, required, logout, navigate, redirectTo]);
return {
user: data?.user || user,
isLoading: !token ? false : isLoading,
isAuthenticated: !!data?.valid || isAuthenticated,
isError,
};
}
/**
* 로그인 페이지에서 사용하는 훅
* 이미 인증된 경우 리다이렉트
* @param {string} redirectTo - 인증된 경우 리다이렉트 경로
*/
export function useRedirectIfAuthenticated(redirectTo = '/admin/dashboard') {
const navigate = useNavigate();
const { isAuthenticated, token } = useAuthStore();
// 토큰 검증
const { data, isLoading } = useQuery({
queryKey: ['admin', 'auth'],
queryFn: authApi.verifyToken,
enabled: !!token,
retry: false,
});
useEffect(() => {
if (data?.valid) {
navigate(redirectTo);
}
}, [data, navigate, redirectTo]);
return {
isLoading: !!token && isLoading,
isAuthenticated: !!data?.valid,
};
}