ERP-node/frontend/contexts/ScreenContext.tsx

170 lines
5.3 KiB
TypeScript
Raw Permalink Normal View History

2025-11-27 12:08:32 +09:00
/**
*
* .
*/
"use client";
import React, { createContext, useContext, useCallback, useRef, useState } from "react";
2025-11-27 12:08:32 +09:00
import type { DataProvidable, DataReceivable } from "@/types/data-transfer";
import { logger } from "@/lib/utils/logger";
2025-11-28 14:56:11 +09:00
import type { SplitPanelPosition } from "@/contexts/SplitPanelContext";
2025-11-27 12:08:32 +09:00
interface ScreenContextValue {
screenId?: number;
tableName?: string;
menuObjid?: number; // 메뉴 OBJID (카테고리 값 조회 시 필요)
2025-11-28 14:56:11 +09:00
splitPanelPosition?: SplitPanelPosition; // 🆕 분할 패널 위치 (left/right)
// 🆕 폼 데이터 (RepeaterFieldGroup 등 컴포넌트 데이터 저장)
formData: Record<string, any>;
updateFormData: (fieldName: string, value: any) => void;
2025-11-27 12:08:32 +09:00
// 컴포넌트 등록
registerDataProvider: (componentId: string, provider: DataProvidable) => void;
unregisterDataProvider: (componentId: string) => void;
registerDataReceiver: (componentId: string, receiver: DataReceivable) => void;
unregisterDataReceiver: (componentId: string) => void;
2025-11-27 12:08:32 +09:00
// 컴포넌트 조회
getDataProvider: (componentId: string) => DataProvidable | undefined;
getDataReceiver: (componentId: string) => DataReceivable | undefined;
2025-11-27 12:08:32 +09:00
// 모든 컴포넌트 조회
getAllDataProviders: () => Map<string, DataProvidable>;
getAllDataReceivers: () => Map<string, DataReceivable>;
}
const ScreenContext = createContext<ScreenContextValue | null>(null);
interface ScreenContextProviderProps {
screenId?: number;
tableName?: string;
menuObjid?: number; // 메뉴 OBJID
2025-11-28 14:56:11 +09:00
splitPanelPosition?: SplitPanelPosition; // 🆕 분할 패널 위치
2025-11-27 12:08:32 +09:00
children: React.ReactNode;
}
/**
*
*/
export function ScreenContextProvider({
screenId,
tableName,
menuObjid,
splitPanelPosition,
children,
}: ScreenContextProviderProps) {
2025-11-27 12:08:32 +09:00
const dataProvidersRef = useRef<Map<string, DataProvidable>>(new Map());
const dataReceiversRef = useRef<Map<string, DataReceivable>>(new Map());
// 🆕 폼 데이터 상태 (RepeaterFieldGroup 등 컴포넌트 데이터 저장)
const [formData, setFormData] = useState<Record<string, any>>({});
// 🆕 폼 데이터 업데이트 함수
const updateFormData = useCallback((fieldName: string, value: any) => {
setFormData((prev) => {
const updated = { ...prev, [fieldName]: value };
logger.debug("ScreenContext formData 업데이트", {
fieldName,
valueType: typeof value,
isArray: Array.isArray(value),
});
return updated;
});
}, []);
2025-11-27 12:08:32 +09:00
const registerDataProvider = useCallback((componentId: string, provider: DataProvidable) => {
dataProvidersRef.current.set(componentId, provider);
logger.debug("데이터 제공자 등록", { componentId, componentType: provider.componentType });
}, []);
const unregisterDataProvider = useCallback((componentId: string) => {
dataProvidersRef.current.delete(componentId);
logger.debug("데이터 제공자 해제", { componentId });
}, []);
const registerDataReceiver = useCallback((componentId: string, receiver: DataReceivable) => {
dataReceiversRef.current.set(componentId, receiver);
logger.debug("데이터 수신자 등록", { componentId, componentType: receiver.componentType });
}, []);
const unregisterDataReceiver = useCallback((componentId: string) => {
dataReceiversRef.current.delete(componentId);
logger.debug("데이터 수신자 해제", { componentId });
}, []);
const getDataProvider = useCallback((componentId: string) => {
return dataProvidersRef.current.get(componentId);
}, []);
const getDataReceiver = useCallback((componentId: string) => {
return dataReceiversRef.current.get(componentId);
}, []);
const getAllDataProviders = useCallback(() => {
return new Map(dataProvidersRef.current);
}, []);
const getAllDataReceivers = useCallback(() => {
return new Map(dataReceiversRef.current);
}, []);
2025-11-28 14:56:11 +09:00
// 🆕 useMemo로 value 객체 메모이제이션 (무한 루프 방지)
const value = React.useMemo<ScreenContextValue>(
() => ({
screenId,
tableName,
menuObjid,
splitPanelPosition,
formData,
updateFormData,
registerDataProvider,
unregisterDataProvider,
registerDataReceiver,
unregisterDataReceiver,
getDataProvider,
getDataReceiver,
getAllDataProviders,
getAllDataReceivers,
}),
[
screenId,
tableName,
menuObjid,
splitPanelPosition,
formData,
updateFormData,
registerDataProvider,
unregisterDataProvider,
registerDataReceiver,
unregisterDataReceiver,
getDataProvider,
getDataReceiver,
getAllDataProviders,
getAllDataReceivers,
],
);
2025-11-27 12:08:32 +09:00
return <ScreenContext.Provider value={value}>{children}</ScreenContext.Provider>;
}
/**
*
*/
export function useScreenContext() {
const context = useContext(ScreenContext);
if (!context) {
throw new Error("useScreenContext는 ScreenContextProvider 내부에서만 사용할 수 있습니다.");
}
return context;
}
/**
* ()
* .
*/
export function useScreenContextOptional() {
return useContext(ScreenContext);
}