117 lines
3.7 KiB
TypeScript
117 lines
3.7 KiB
TypeScript
/**
|
|
* 화면 컨텍스트
|
|
* 같은 화면 내의 컴포넌트들이 서로 통신할 수 있도록 합니다.
|
|
*/
|
|
|
|
"use client";
|
|
|
|
import React, { createContext, useContext, useCallback, useRef } from "react";
|
|
import type { DataProvidable, DataReceivable } from "@/types/data-transfer";
|
|
import { logger } from "@/lib/utils/logger";
|
|
|
|
interface ScreenContextValue {
|
|
screenId?: number;
|
|
tableName?: string;
|
|
|
|
// 컴포넌트 등록
|
|
registerDataProvider: (componentId: string, provider: DataProvidable) => void;
|
|
unregisterDataProvider: (componentId: string) => void;
|
|
registerDataReceiver: (componentId: string, receiver: DataReceivable) => void;
|
|
unregisterDataReceiver: (componentId: string) => void;
|
|
|
|
// 컴포넌트 조회
|
|
getDataProvider: (componentId: string) => DataProvidable | undefined;
|
|
getDataReceiver: (componentId: string) => DataReceivable | undefined;
|
|
|
|
// 모든 컴포넌트 조회
|
|
getAllDataProviders: () => Map<string, DataProvidable>;
|
|
getAllDataReceivers: () => Map<string, DataReceivable>;
|
|
}
|
|
|
|
const ScreenContext = createContext<ScreenContextValue | null>(null);
|
|
|
|
interface ScreenContextProviderProps {
|
|
screenId?: number;
|
|
tableName?: string;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
/**
|
|
* 화면 컨텍스트 프로바이더
|
|
*/
|
|
export function ScreenContextProvider({ screenId, tableName, children }: ScreenContextProviderProps) {
|
|
const dataProvidersRef = useRef<Map<string, DataProvidable>>(new Map());
|
|
const dataReceiversRef = useRef<Map<string, DataReceivable>>(new Map());
|
|
|
|
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);
|
|
}, []);
|
|
|
|
const value: ScreenContextValue = {
|
|
screenId,
|
|
tableName,
|
|
registerDataProvider,
|
|
unregisterDataProvider,
|
|
registerDataReceiver,
|
|
unregisterDataReceiver,
|
|
getDataProvider,
|
|
getDataReceiver,
|
|
getAllDataProviders,
|
|
getAllDataReceivers,
|
|
};
|
|
|
|
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);
|
|
}
|
|
|