feat: 코드 컴포넌트에 메뉴 스코프 적용
- useCodeOptions 훅에 menuObjid 파라미터 추가 - commonCodeApi.codes.getList에 menuObjid 전달 - SelectBasicComponent에서 menuObjid 받아서 useCodeOptions로 전달 - InteractiveScreenViewer에서 DynamicWebTypeRenderer로 menuObjid 전달 - 화면 페이지에서 RealtimePreview로 menuObjid 전달 이제 코드 위젯도 카테고리처럼 형제 메뉴별로 격리됩니다.
This commit is contained in:
@@ -20,8 +20,9 @@ export class CommonCodeController {
|
|||||||
*/
|
*/
|
||||||
async getCategories(req: AuthenticatedRequest, res: Response) {
|
async getCategories(req: AuthenticatedRequest, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { search, isActive, page = "1", size = "20" } = req.query;
|
const { search, isActive, page = "1", size = "20", menuObjid } = req.query;
|
||||||
const userCompanyCode = req.user?.companyCode;
|
const userCompanyCode = req.user?.companyCode;
|
||||||
|
const menuObjidNum = menuObjid ? Number(menuObjid) : undefined;
|
||||||
|
|
||||||
const categories = await this.commonCodeService.getCategories(
|
const categories = await this.commonCodeService.getCategories(
|
||||||
{
|
{
|
||||||
@@ -35,7 +36,8 @@ export class CommonCodeController {
|
|||||||
page: parseInt(page as string),
|
page: parseInt(page as string),
|
||||||
size: parseInt(size as string),
|
size: parseInt(size as string),
|
||||||
},
|
},
|
||||||
userCompanyCode
|
userCompanyCode,
|
||||||
|
menuObjidNum
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
@@ -61,8 +63,9 @@ export class CommonCodeController {
|
|||||||
async getCodes(req: AuthenticatedRequest, res: Response) {
|
async getCodes(req: AuthenticatedRequest, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { categoryCode } = req.params;
|
const { categoryCode } = req.params;
|
||||||
const { search, isActive, page, size } = req.query;
|
const { search, isActive, page, size, menuObjid } = req.query;
|
||||||
const userCompanyCode = req.user?.companyCode;
|
const userCompanyCode = req.user?.companyCode;
|
||||||
|
const menuObjidNum = menuObjid ? Number(menuObjid) : undefined;
|
||||||
|
|
||||||
const result = await this.commonCodeService.getCodes(
|
const result = await this.commonCodeService.getCodes(
|
||||||
categoryCode,
|
categoryCode,
|
||||||
@@ -77,7 +80,8 @@ export class CommonCodeController {
|
|||||||
page: page ? parseInt(page as string) : undefined,
|
page: page ? parseInt(page as string) : undefined,
|
||||||
size: size ? parseInt(size as string) : undefined,
|
size: size ? parseInt(size as string) : undefined,
|
||||||
},
|
},
|
||||||
userCompanyCode
|
userCompanyCode,
|
||||||
|
menuObjidNum
|
||||||
);
|
);
|
||||||
|
|
||||||
// 프론트엔드가 기대하는 형식으로 데이터 변환
|
// 프론트엔드가 기대하는 형식으로 데이터 변환
|
||||||
@@ -131,6 +135,7 @@ export class CommonCodeController {
|
|||||||
const categoryData: CreateCategoryData = req.body;
|
const categoryData: CreateCategoryData = req.body;
|
||||||
const userId = req.user?.userId || "SYSTEM";
|
const userId = req.user?.userId || "SYSTEM";
|
||||||
const companyCode = req.user?.companyCode || "*";
|
const companyCode = req.user?.companyCode || "*";
|
||||||
|
const menuObjid = req.body.menuObjid;
|
||||||
|
|
||||||
// 입력값 검증
|
// 입력값 검증
|
||||||
if (!categoryData.categoryCode || !categoryData.categoryName) {
|
if (!categoryData.categoryCode || !categoryData.categoryName) {
|
||||||
@@ -140,10 +145,18 @@ export class CommonCodeController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!menuObjid) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: "메뉴 OBJID는 필수입니다.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const category = await this.commonCodeService.createCategory(
|
const category = await this.commonCodeService.createCategory(
|
||||||
categoryData,
|
categoryData,
|
||||||
userId,
|
userId,
|
||||||
companyCode
|
companyCode,
|
||||||
|
Number(menuObjid)
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.status(201).json({
|
return res.status(201).json({
|
||||||
@@ -263,6 +276,7 @@ export class CommonCodeController {
|
|||||||
const codeData: CreateCodeData = req.body;
|
const codeData: CreateCodeData = req.body;
|
||||||
const userId = req.user?.userId || "SYSTEM";
|
const userId = req.user?.userId || "SYSTEM";
|
||||||
const companyCode = req.user?.companyCode || "*";
|
const companyCode = req.user?.companyCode || "*";
|
||||||
|
const menuObjid = req.body.menuObjid;
|
||||||
|
|
||||||
// 입력값 검증
|
// 입력값 검증
|
||||||
if (!codeData.codeValue || !codeData.codeName) {
|
if (!codeData.codeValue || !codeData.codeName) {
|
||||||
@@ -272,11 +286,19 @@ export class CommonCodeController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!menuObjid) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: "메뉴 OBJID는 필수입니다.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const code = await this.commonCodeService.createCode(
|
const code = await this.commonCodeService.createCode(
|
||||||
categoryCode,
|
categoryCode,
|
||||||
codeData,
|
codeData,
|
||||||
userId,
|
userId,
|
||||||
companyCode
|
companyCode,
|
||||||
|
Number(menuObjid)
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.status(201).json({
|
return res.status(201).json({
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export class CommonCodeService {
|
|||||||
/**
|
/**
|
||||||
* 카테고리 목록 조회
|
* 카테고리 목록 조회
|
||||||
*/
|
*/
|
||||||
async getCategories(params: GetCategoriesParams, userCompanyCode?: string) {
|
async getCategories(params: GetCategoriesParams, userCompanyCode?: string, menuObjid?: number) {
|
||||||
try {
|
try {
|
||||||
const { search, isActive, page = 1, size = 20 } = params;
|
const { search, isActive, page = 1, size = 20 } = params;
|
||||||
|
|
||||||
@@ -74,6 +74,16 @@ export class CommonCodeService {
|
|||||||
const values: any[] = [];
|
const values: any[] = [];
|
||||||
let paramIndex = 1;
|
let paramIndex = 1;
|
||||||
|
|
||||||
|
// 메뉴별 필터링 (형제 메뉴 포함)
|
||||||
|
if (menuObjid) {
|
||||||
|
const { getSiblingMenuObjids } = await import('./menuService');
|
||||||
|
const siblingMenuObjids = await getSiblingMenuObjids(menuObjid);
|
||||||
|
whereConditions.push(`menu_objid = ANY($${paramIndex})`);
|
||||||
|
values.push(siblingMenuObjids);
|
||||||
|
paramIndex++;
|
||||||
|
logger.info(`메뉴별 코드 카테고리 필터링: ${menuObjid}, 형제 메뉴: ${siblingMenuObjids.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
if (userCompanyCode && userCompanyCode !== "*") {
|
||||||
whereConditions.push(`company_code = $${paramIndex}`);
|
whereConditions.push(`company_code = $${paramIndex}`);
|
||||||
@@ -142,7 +152,8 @@ export class CommonCodeService {
|
|||||||
async getCodes(
|
async getCodes(
|
||||||
categoryCode: string,
|
categoryCode: string,
|
||||||
params: GetCodesParams,
|
params: GetCodesParams,
|
||||||
userCompanyCode?: string
|
userCompanyCode?: string,
|
||||||
|
menuObjid?: number
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { search, isActive, page = 1, size = 20 } = params;
|
const { search, isActive, page = 1, size = 20 } = params;
|
||||||
@@ -151,6 +162,16 @@ export class CommonCodeService {
|
|||||||
const values: any[] = [categoryCode];
|
const values: any[] = [categoryCode];
|
||||||
let paramIndex = 2;
|
let paramIndex = 2;
|
||||||
|
|
||||||
|
// 메뉴별 필터링 (형제 메뉴 포함)
|
||||||
|
if (menuObjid) {
|
||||||
|
const { getSiblingMenuObjids } = await import('./menuService');
|
||||||
|
const siblingMenuObjids = await getSiblingMenuObjids(menuObjid);
|
||||||
|
whereConditions.push(`menu_objid = ANY($${paramIndex})`);
|
||||||
|
values.push(siblingMenuObjids);
|
||||||
|
paramIndex++;
|
||||||
|
logger.info(`메뉴별 코드 필터링: ${menuObjid}, 형제 메뉴: ${siblingMenuObjids.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
if (userCompanyCode && userCompanyCode !== "*") {
|
||||||
whereConditions.push(`company_code = $${paramIndex}`);
|
whereConditions.push(`company_code = $${paramIndex}`);
|
||||||
@@ -212,14 +233,15 @@ export class CommonCodeService {
|
|||||||
async createCategory(
|
async createCategory(
|
||||||
data: CreateCategoryData,
|
data: CreateCategoryData,
|
||||||
createdBy: string,
|
createdBy: string,
|
||||||
companyCode: string
|
companyCode: string,
|
||||||
|
menuObjid: number
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const category = await queryOne<CodeCategory>(
|
const category = await queryOne<CodeCategory>(
|
||||||
`INSERT INTO code_category
|
`INSERT INTO code_category
|
||||||
(category_code, category_name, category_name_eng, description, sort_order,
|
(category_code, category_name, category_name_eng, description, sort_order,
|
||||||
is_active, company_code, created_by, updated_by, created_date, updated_date)
|
is_active, menu_objid, company_code, created_by, updated_by, created_date, updated_date)
|
||||||
VALUES ($1, $2, $3, $4, $5, 'Y', $6, $7, $8, NOW(), NOW())
|
VALUES ($1, $2, $3, $4, $5, 'Y', $6, $7, $8, $9, NOW(), NOW())
|
||||||
RETURNING *`,
|
RETURNING *`,
|
||||||
[
|
[
|
||||||
data.categoryCode,
|
data.categoryCode,
|
||||||
@@ -227,6 +249,7 @@ export class CommonCodeService {
|
|||||||
data.categoryNameEng || null,
|
data.categoryNameEng || null,
|
||||||
data.description || null,
|
data.description || null,
|
||||||
data.sortOrder || 0,
|
data.sortOrder || 0,
|
||||||
|
menuObjid,
|
||||||
companyCode,
|
companyCode,
|
||||||
createdBy,
|
createdBy,
|
||||||
createdBy,
|
createdBy,
|
||||||
@@ -234,7 +257,7 @@ export class CommonCodeService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`카테고리 생성 완료: ${data.categoryCode} (회사: ${companyCode})`
|
`카테고리 생성 완료: ${data.categoryCode} (메뉴: ${menuObjid}, 회사: ${companyCode})`
|
||||||
);
|
);
|
||||||
return category;
|
return category;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -352,14 +375,15 @@ export class CommonCodeService {
|
|||||||
categoryCode: string,
|
categoryCode: string,
|
||||||
data: CreateCodeData,
|
data: CreateCodeData,
|
||||||
createdBy: string,
|
createdBy: string,
|
||||||
companyCode: string
|
companyCode: string,
|
||||||
|
menuObjid: number
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const code = await queryOne<CodeInfo>(
|
const code = await queryOne<CodeInfo>(
|
||||||
`INSERT INTO code_info
|
`INSERT INTO code_info
|
||||||
(code_category, code_value, code_name, code_name_eng, description, sort_order,
|
(code_category, code_value, code_name, code_name_eng, description, sort_order,
|
||||||
is_active, company_code, created_by, updated_by, created_date, updated_date)
|
is_active, menu_objid, company_code, created_by, updated_by, created_date, updated_date)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, 'Y', $7, $8, $9, NOW(), NOW())
|
VALUES ($1, $2, $3, $4, $5, $6, 'Y', $7, $8, $9, $10, NOW(), NOW())
|
||||||
RETURNING *`,
|
RETURNING *`,
|
||||||
[
|
[
|
||||||
categoryCode,
|
categoryCode,
|
||||||
@@ -368,6 +392,7 @@ export class CommonCodeService {
|
|||||||
data.codeNameEng || null,
|
data.codeNameEng || null,
|
||||||
data.description || null,
|
data.description || null,
|
||||||
data.sortOrder || 0,
|
data.sortOrder || 0,
|
||||||
|
menuObjid,
|
||||||
companyCode,
|
companyCode,
|
||||||
createdBy,
|
createdBy,
|
||||||
createdBy,
|
createdBy,
|
||||||
@@ -375,7 +400,7 @@ export class CommonCodeService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`코드 생성 완료: ${categoryCode}.${data.codeValue} (회사: ${companyCode})`
|
`코드 생성 완료: ${categoryCode}.${data.codeValue} (메뉴: ${menuObjid}, 회사: ${companyCode})`
|
||||||
);
|
);
|
||||||
return code;
|
return code;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -403,6 +403,7 @@ export default function ScreenViewPage() {
|
|||||||
isSelected={false}
|
isSelected={false}
|
||||||
isDesignMode={false}
|
isDesignMode={false}
|
||||||
onClick={() => {}}
|
onClick={() => {}}
|
||||||
|
menuObjid={menuObjid}
|
||||||
screenId={screenId}
|
screenId={screenId}
|
||||||
tableName={screen?.tableName}
|
tableName={screen?.tableName}
|
||||||
userId={user?.userId}
|
userId={user?.userId}
|
||||||
@@ -468,6 +469,7 @@ export default function ScreenViewPage() {
|
|||||||
isSelected={false}
|
isSelected={false}
|
||||||
isDesignMode={false}
|
isDesignMode={false}
|
||||||
onClick={() => {}}
|
onClick={() => {}}
|
||||||
|
menuObjid={menuObjid}
|
||||||
screenId={screenId}
|
screenId={screenId}
|
||||||
tableName={screen?.tableName}
|
tableName={screen?.tableName}
|
||||||
userId={user?.userId}
|
userId={user?.userId}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ interface InteractiveScreenViewerProps {
|
|||||||
id: number;
|
id: number;
|
||||||
tableName?: string;
|
tableName?: string;
|
||||||
};
|
};
|
||||||
|
menuObjid?: number; // 🆕 메뉴 OBJID (코드 스코프용)
|
||||||
// 새로운 검증 관련 옵션들
|
// 새로운 검증 관련 옵션들
|
||||||
enableEnhancedValidation?: boolean;
|
enableEnhancedValidation?: boolean;
|
||||||
tableColumns?: ColumnInfo[];
|
tableColumns?: ColumnInfo[];
|
||||||
@@ -76,6 +77,7 @@ export const InteractiveScreenViewer: React.FC<InteractiveScreenViewerProps> = (
|
|||||||
onFormDataChange,
|
onFormDataChange,
|
||||||
hideLabel = false,
|
hideLabel = false,
|
||||||
screenInfo,
|
screenInfo,
|
||||||
|
menuObjid, // 🆕 메뉴 OBJID
|
||||||
enableEnhancedValidation = false,
|
enableEnhancedValidation = false,
|
||||||
tableColumns = [],
|
tableColumns = [],
|
||||||
showValidationPanel = false,
|
showValidationPanel = false,
|
||||||
@@ -1117,6 +1119,7 @@ export const InteractiveScreenViewer: React.FC<InteractiveScreenViewerProps> = (
|
|||||||
required: required,
|
required: required,
|
||||||
placeholder: config?.placeholder || "코드를 선택하세요...",
|
placeholder: config?.placeholder || "코드를 선택하세요...",
|
||||||
className: "w-full h-full",
|
className: "w-full h-full",
|
||||||
|
menuObjid: menuObjid, // 🆕 메뉴 OBJID 전달
|
||||||
}}
|
}}
|
||||||
config={{
|
config={{
|
||||||
...config,
|
...config,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ interface RealtimePreviewProps {
|
|||||||
userId?: string; // 🆕 현재 사용자 ID
|
userId?: string; // 🆕 현재 사용자 ID
|
||||||
userName?: string; // 🆕 현재 사용자 이름
|
userName?: string; // 🆕 현재 사용자 이름
|
||||||
companyCode?: string; // 🆕 현재 사용자의 회사 코드
|
companyCode?: string; // 🆕 현재 사용자의 회사 코드
|
||||||
menuObjid?: number; // 🆕 현재 메뉴 OBJID (메뉴 스코프)
|
menuObjid?: number; // 🆕 메뉴 OBJID (코드/카테고리 스코프용)
|
||||||
selectedRowsData?: any[];
|
selectedRowsData?: any[];
|
||||||
onSelectedRowsChange?: (selectedRows: any[], selectedRowsData: any[]) => void;
|
onSelectedRowsChange?: (selectedRows: any[], selectedRowsData: any[]) => void;
|
||||||
flowSelectedData?: any[];
|
flowSelectedData?: any[];
|
||||||
|
|||||||
@@ -51,14 +51,19 @@ export function useTableCodeCategory(tableName?: string, columnName?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 코드 옵션 조회 (select용)
|
// 코드 옵션 조회 (select용)
|
||||||
export function useCodeOptions(codeCategory?: string, enabled: boolean = true) {
|
export function useCodeOptions(codeCategory?: string, enabled: boolean = true, menuObjid?: number) {
|
||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: queryKeys.codes.options(codeCategory || ""),
|
queryKey: menuObjid
|
||||||
|
? [...queryKeys.codes.options(codeCategory || ""), 'menu', menuObjid]
|
||||||
|
: queryKeys.codes.options(codeCategory || ""),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (!codeCategory || codeCategory === "none") return [];
|
if (!codeCategory || codeCategory === "none") return [];
|
||||||
|
|
||||||
console.log(`🔍 [React Query] 코드 옵션 조회: ${codeCategory}`);
|
console.log(`🔍 [React Query] 코드 옵션 조회: ${codeCategory} (menuObjid: ${menuObjid})`);
|
||||||
const response = await commonCodeApi.codes.getList(codeCategory, { isActive: true });
|
const response = await commonCodeApi.codes.getList(codeCategory, {
|
||||||
|
isActive: true,
|
||||||
|
menuObjid
|
||||||
|
});
|
||||||
|
|
||||||
if (response.success && response.data) {
|
if (response.success && response.data) {
|
||||||
const options = response.data.map((code: any) => {
|
const options = response.data.map((code: any) => {
|
||||||
@@ -73,7 +78,7 @@ export function useCodeOptions(codeCategory?: string, enabled: boolean = true) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`✅ [React Query] 코드 옵션 결과: ${codeCategory} (${options.length}개)`);
|
console.log(`✅ [React Query] 코드 옵션 결과: ${codeCategory} (${options.length}개, menuObjid: ${menuObjid})`);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,13 +66,14 @@ export const commonCodeApi = {
|
|||||||
/**
|
/**
|
||||||
* 카테고리별 코드 목록 조회
|
* 카테고리별 코드 목록 조회
|
||||||
*/
|
*/
|
||||||
async getList(categoryCode: string, params?: GetCodesQuery): Promise<ApiResponse<CodeInfo[]>> {
|
async getList(categoryCode: string, params?: GetCodesQuery & { menuObjid?: number }): Promise<ApiResponse<CodeInfo[]>> {
|
||||||
const searchParams = new URLSearchParams();
|
const searchParams = new URLSearchParams();
|
||||||
|
|
||||||
if (params?.search) searchParams.append("search", params.search);
|
if (params?.search) searchParams.append("search", params.search);
|
||||||
if (params?.isActive !== undefined) searchParams.append("isActive", params.isActive.toString());
|
if (params?.isActive !== undefined) searchParams.append("isActive", params.isActive.toString());
|
||||||
if (params?.page !== undefined) searchParams.append("page", params.page.toString());
|
if (params?.page !== undefined) searchParams.append("page", params.page.toString());
|
||||||
if (params?.size !== undefined) searchParams.append("size", params.size.toString());
|
if (params?.size !== undefined) searchParams.append("size", params.size.toString());
|
||||||
|
if (params?.menuObjid !== undefined) searchParams.append("menuObjid", params.menuObjid.toString());
|
||||||
|
|
||||||
const queryString = searchParams.toString();
|
const queryString = searchParams.toString();
|
||||||
const url = `/common-codes/categories/${categoryCode}/codes${queryString ? `?${queryString}` : ""}`;
|
const url = `/common-codes/categories/${categoryCode}/codes${queryString ? `?${queryString}` : ""}`;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export interface SelectBasicComponentProps {
|
|||||||
onDragStart?: () => void;
|
onDragStart?: () => void;
|
||||||
onDragEnd?: () => void;
|
onDragEnd?: () => void;
|
||||||
value?: any; // 외부에서 전달받는 값
|
value?: any; // 외부에서 전달받는 값
|
||||||
|
menuObjid?: number; // 🆕 메뉴 OBJID (코드 스코프용)
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
|||||||
onDragStart,
|
onDragStart,
|
||||||
onDragEnd,
|
onDragEnd,
|
||||||
value: externalValue, // 명시적으로 value prop 받기
|
value: externalValue, // 명시적으로 value prop 받기
|
||||||
|
menuObjid, // 🆕 메뉴 OBJID
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
// 🚨 최우선 디버깅: 컴포넌트가 실행되는지 확인
|
// 🚨 최우선 디버깅: 컴포넌트가 실행되는지 확인
|
||||||
@@ -132,7 +134,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
|||||||
options: codeOptions,
|
options: codeOptions,
|
||||||
isLoading: isLoadingCodes,
|
isLoading: isLoadingCodes,
|
||||||
isFetching,
|
isFetching,
|
||||||
} = useCodeOptions(codeCategory, isCodeCategoryValid);
|
} = useCodeOptions(codeCategory, isCodeCategoryValid, menuObjid);
|
||||||
|
|
||||||
// React Query 상태 디버깅
|
// React Query 상태 디버깅
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user