feat: Enhance entity options retrieval with additional fields support
- Updated the `getEntityOptions` function to accept an optional `fields` parameter, allowing clients to specify additional columns to be retrieved. - Implemented logic to dynamically include extra columns in the SQL query based on the provided `fields`, improving flexibility in data retrieval. - Enhanced the response to indicate whether extra fields were included, facilitating better client-side handling of the data. - Added logging for authentication failures in the `AuthGuard` component to improve debugging and user experience. - Integrated auto-fill functionality in the `V2Select` component to automatically populate fields based on selected entity references, enhancing user interaction. - Updated the `ItemSearchModal` to support multi-selection of items, improving usability in item management scenarios.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { apiCall } from "@/lib/api/client";
|
||||
import { AuthLogger } from "@/lib/authLogger";
|
||||
|
||||
interface UserInfo {
|
||||
userId: string;
|
||||
@@ -161,13 +162,15 @@ export const useAuth = () => {
|
||||
|
||||
const token = TokenManager.getToken();
|
||||
if (!token || TokenManager.isTokenExpired(token)) {
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", `refreshUserData: 토큰 ${!token ? "없음" : "만료됨"}`);
|
||||
setUser(null);
|
||||
setAuthStatus({ isLoggedIn: false, isAdmin: false });
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 토큰이 유효하면 우선 인증된 상태로 설정
|
||||
AuthLogger.log("AUTH_CHECK_START", "refreshUserData: API로 인증 상태 확인 시작");
|
||||
|
||||
setAuthStatus({
|
||||
isLoggedIn: true,
|
||||
isAdmin: false,
|
||||
@@ -186,15 +189,16 @@ export const useAuth = () => {
|
||||
};
|
||||
|
||||
setAuthStatus(finalAuthStatus);
|
||||
AuthLogger.log("AUTH_CHECK_SUCCESS", `사용자: ${userInfo.userId}, 인증: ${finalAuthStatus.isLoggedIn}`);
|
||||
|
||||
// API 결과가 비인증이면 상태만 업데이트 (리다이렉트는 client.ts가 처리)
|
||||
if (!finalAuthStatus.isLoggedIn) {
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", "API 응답에서 비인증 상태 반환 → 토큰 제거");
|
||||
TokenManager.removeToken();
|
||||
setUser(null);
|
||||
setAuthStatus({ isLoggedIn: false, isAdmin: false });
|
||||
}
|
||||
} else {
|
||||
// userInfo 조회 실패 → 토큰에서 최소 정보 추출하여 유지
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", "userInfo 조회 실패 → 토큰 기반 임시 인증 유지 시도");
|
||||
try {
|
||||
const payload = JSON.parse(atob(token.split(".")[1]));
|
||||
const tempUser: UserInfo = {
|
||||
@@ -210,14 +214,14 @@ export const useAuth = () => {
|
||||
isAdmin: tempUser.isAdmin,
|
||||
});
|
||||
} catch {
|
||||
// 토큰 파싱도 실패하면 비인증 상태로 전환
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", "토큰 파싱 실패 → 비인증 전환");
|
||||
TokenManager.removeToken();
|
||||
setUser(null);
|
||||
setAuthStatus({ isLoggedIn: false, isAdmin: false });
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// API 호출 전체 실패 → 토큰 기반 임시 인증 유지 시도
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", "API 호출 전체 실패 → 토큰 기반 임시 인증 유지 시도");
|
||||
try {
|
||||
const payload = JSON.parse(atob(token.split(".")[1]));
|
||||
const tempUser: UserInfo = {
|
||||
@@ -233,6 +237,7 @@ export const useAuth = () => {
|
||||
isAdmin: tempUser.isAdmin,
|
||||
});
|
||||
} catch {
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", "최종 fallback 실패 → 비인증 전환");
|
||||
TokenManager.removeToken();
|
||||
setUser(null);
|
||||
setAuthStatus({ isLoggedIn: false, isAdmin: false });
|
||||
@@ -408,19 +413,19 @@ export const useAuth = () => {
|
||||
const token = TokenManager.getToken();
|
||||
|
||||
if (token && !TokenManager.isTokenExpired(token)) {
|
||||
// 유효한 토큰 → 우선 인증 상태로 설정 후 API 확인
|
||||
AuthLogger.log("AUTH_CHECK_START", `초기 인증 확인: 유효한 토큰 존재 (경로: ${window.location.pathname})`);
|
||||
setAuthStatus({
|
||||
isLoggedIn: true,
|
||||
isAdmin: false,
|
||||
});
|
||||
refreshUserData();
|
||||
} else if (token && TokenManager.isTokenExpired(token)) {
|
||||
// 만료된 토큰 → 정리 (리다이렉트는 AuthGuard에서 처리)
|
||||
AuthLogger.log("TOKEN_EXPIRED_DETECTED", `초기 확인 시 만료된 토큰 발견 → 정리 (경로: ${window.location.pathname})`);
|
||||
TokenManager.removeToken();
|
||||
setAuthStatus({ isLoggedIn: false, isAdmin: false });
|
||||
setLoading(false);
|
||||
} else {
|
||||
// 토큰 없음 → 비인증 상태 (리다이렉트는 AuthGuard에서 처리)
|
||||
AuthLogger.log("AUTH_CHECK_FAIL", `초기 확인: 토큰 없음 (경로: ${window.location.pathname})`);
|
||||
setAuthStatus({ isLoggedIn: false, isAdmin: false });
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { MenuItem, MenuState } from "@/types/menu";
|
||||
import { apiClient } from "@/lib/api/client";
|
||||
import { AuthLogger } from "@/lib/authLogger";
|
||||
|
||||
/**
|
||||
* 메뉴 관련 비즈니스 로직을 관리하는 커스텀 훅
|
||||
@@ -84,8 +85,8 @@ export const useMenu = (user: any, authLoading: boolean) => {
|
||||
} else {
|
||||
setMenuState((prev: MenuState) => ({ ...prev, isLoading: false }));
|
||||
}
|
||||
} catch {
|
||||
// API 실패 시 빈 메뉴로 유지 (401은 client.ts 인터셉터가 리다이렉트 처리)
|
||||
} catch (err: any) {
|
||||
AuthLogger.log("MENU_LOAD_FAIL", `메뉴 로드 실패: ${err?.response?.status || err?.message || "unknown"}`);
|
||||
setMenuState((prev: MenuState) => ({ ...prev, isLoading: false }));
|
||||
}
|
||||
}, [convertToUpperCaseKeys, buildMenuTree]);
|
||||
|
||||
Reference in New Issue
Block a user