ERP-node/frontend/contexts/TableOptionsContext.tsx

136 lines
4.1 KiB
TypeScript
Raw Normal View History

2025-12-24 14:46:51 +09:00
import React, { createContext, useContext, useState, useCallback, useMemo, ReactNode } from "react";
import { TableRegistration, TableOptionsContextValue } from "@/types/table-options";
import { useActiveTab } from "./ActiveTabContext";
2025-12-24 14:46:51 +09:00
const TableOptionsContext = createContext<TableOptionsContextValue | undefined>(undefined);
2025-12-24 14:46:51 +09:00
export const TableOptionsProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [registeredTables, setRegisteredTables] = useState<Map<string, TableRegistration>>(new Map());
const [selectedTableId, setSelectedTableId] = useState<string | null>(null);
/**
*
*/
const registerTable = useCallback((registration: TableRegistration) => {
setRegisteredTables((prev) => {
const newMap = new Map(prev);
newMap.set(registration.tableId, registration);
// 첫 번째 테이블이면 자동 선택
if (newMap.size === 1) {
setSelectedTableId(registration.tableId);
}
return newMap;
});
}, []);
/**
*
2025-12-24 14:46:51 +09:00
* :
* 1. selectedTableId를
* 2. unregister가 selectedTableId를
*/
const unregisterTable = useCallback(
(tableId: string) => {
setRegisteredTables((prev) => {
const newMap = new Map(prev);
newMap.delete(tableId);
return newMap;
});
2025-12-24 14:46:51 +09:00
// 🚫 selectedTableId를 변경하지 않음
// 이유: useEffect 재실행 시 cleanup → register 순서로 호출되는데,
// cleanup에서 selectedTableId를 null로 만들면 필터 설정이 초기화됨
// 다른 테이블이 선택되어야 하면 TableSearchWidget에서 자동 선택함
},
2025-12-24 14:46:51 +09:00
[], // 의존성 없음 - 무한 루프 방지
);
/**
*
*/
const getTable = useCallback(
(tableId: string) => {
return registeredTables.get(tableId);
},
2025-12-24 14:46:51 +09:00
[registeredTables],
);
/**
*
*/
const updateTableDataCount = useCallback((tableId: string, count: number) => {
setRegisteredTables((prev) => {
const table = prev.get(tableId);
if (table) {
// 기존 테이블 정보에 dataCount만 업데이트
const updatedTable = { ...table, dataCount: count };
const newMap = new Map(prev);
newMap.set(tableId, updatedTable);
return newMap;
}
return prev;
});
}, []);
// ActiveTab context 사용 (optional - 에러 방지)
const activeTabContext = useActiveTab();
/**
*
*/
const getActiveTabTables = useCallback(() => {
const allTables = Array.from(registeredTables.values());
const activeTabIds = activeTabContext.getAllActiveTabIds();
2025-12-24 14:46:51 +09:00
// 활성 탭이 없으면 탭에 속하지 않은 테이블만 반환
if (activeTabIds.length === 0) {
2025-12-24 14:46:51 +09:00
return allTables.filter((table) => !table.parentTabId);
}
2025-12-24 14:46:51 +09:00
// 활성 탭에 속한 테이블 + 탭에 속하지 않은 테이블
2025-12-24 14:46:51 +09:00
return allTables.filter((table) => !table.parentTabId || activeTabIds.includes(table.parentTabId));
}, [registeredTables, activeTabContext]);
/**
*
*/
2025-12-24 14:46:51 +09:00
const getTablesForTab = useCallback(
(tabId: string) => {
const allTables = Array.from(registeredTables.values());
return allTables.filter((table) => table.parentTabId === tabId);
},
[registeredTables],
);
return (
<TableOptionsContext.Provider
value={{
registeredTables,
registerTable,
unregisterTable,
getTable,
updateTableDataCount,
selectedTableId,
setSelectedTableId,
getActiveTabTables,
getTablesForTab,
}}
>
{children}
</TableOptionsContext.Provider>
);
};
/**
* Context Hook
*/
export const useTableOptions = () => {
const context = useContext(TableOptionsContext);
if (!context) {
throw new Error("useTableOptions must be used within TableOptionsProvider");
}
return context;
};