화면 분할 패널 기능
This commit is contained in:
@@ -12,6 +12,8 @@ import {
|
||||
import { ConditionalContainerProps, ConditionalSection } from "./types";
|
||||
import { ConditionalSectionViewer } from "./ConditionalSectionViewer";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useScreenContextOptional } from "@/contexts/ScreenContext";
|
||||
import type { DataProvidable } from "@/types/data-transfer";
|
||||
|
||||
/**
|
||||
* 조건부 컨테이너 컴포넌트
|
||||
@@ -42,6 +44,9 @@ export function ConditionalContainerComponent({
|
||||
onSave, // 🆕 EditModal의 handleSave 콜백
|
||||
}: ConditionalContainerProps) {
|
||||
|
||||
// 화면 컨텍스트 (데이터 제공자로 등록)
|
||||
const screenContext = useScreenContextOptional();
|
||||
|
||||
// config prop 우선, 없으면 개별 prop 사용
|
||||
const controlField = config?.controlField || propControlField || "condition";
|
||||
const controlLabel = config?.controlLabel || propControlLabel || "조건 선택";
|
||||
@@ -50,30 +55,86 @@ export function ConditionalContainerComponent({
|
||||
const showBorder = config?.showBorder ?? propShowBorder ?? true;
|
||||
const spacing = config?.spacing || propSpacing || "normal";
|
||||
|
||||
// 초기값 계산 (한 번만)
|
||||
const initialValue = React.useMemo(() => {
|
||||
return value || formData?.[controlField] || defaultValue || "";
|
||||
}, []); // 의존성 없음 - 마운트 시 한 번만 계산
|
||||
|
||||
// 현재 선택된 값
|
||||
const [selectedValue, setSelectedValue] = useState<string>(
|
||||
value || formData?.[controlField] || defaultValue || ""
|
||||
);
|
||||
const [selectedValue, setSelectedValue] = useState<string>(initialValue);
|
||||
|
||||
// 최신 값을 ref로 유지 (클로저 문제 방지)
|
||||
const selectedValueRef = React.useRef(selectedValue);
|
||||
selectedValueRef.current = selectedValue; // 렌더링마다 업데이트 (useEffect 대신)
|
||||
|
||||
// formData 변경 시 동기화
|
||||
useEffect(() => {
|
||||
if (formData?.[controlField]) {
|
||||
setSelectedValue(formData[controlField]);
|
||||
}
|
||||
}, [formData, controlField]);
|
||||
|
||||
// 값 변경 핸들러
|
||||
const handleValueChange = (newValue: string) => {
|
||||
// 콜백 refs (의존성 제거)
|
||||
const onChangeRef = React.useRef(onChange);
|
||||
const onFormDataChangeRef = React.useRef(onFormDataChange);
|
||||
onChangeRef.current = onChange;
|
||||
onFormDataChangeRef.current = onFormDataChange;
|
||||
|
||||
// 값 변경 핸들러 - 의존성 없음
|
||||
const handleValueChange = React.useCallback((newValue: string) => {
|
||||
// 같은 값이면 무시
|
||||
if (newValue === selectedValueRef.current) return;
|
||||
|
||||
setSelectedValue(newValue);
|
||||
|
||||
if (onChange) {
|
||||
onChange(newValue);
|
||||
if (onChangeRef.current) {
|
||||
onChangeRef.current(newValue);
|
||||
}
|
||||
|
||||
if (onFormDataChange) {
|
||||
onFormDataChange(controlField, newValue);
|
||||
if (onFormDataChangeRef.current) {
|
||||
onFormDataChangeRef.current(controlField, newValue);
|
||||
}
|
||||
};
|
||||
}, [controlField]);
|
||||
|
||||
// sectionsRef 추가 (dataProvider에서 사용)
|
||||
const sectionsRef = React.useRef(sections);
|
||||
React.useEffect(() => {
|
||||
sectionsRef.current = sections;
|
||||
}, [sections]);
|
||||
|
||||
// dataProvider를 useMemo로 감싸서 불필요한 재생성 방지
|
||||
const dataProvider = React.useMemo<DataProvidable>(() => ({
|
||||
componentId: componentId || "conditional-container",
|
||||
componentType: "conditional-container",
|
||||
|
||||
getSelectedData: () => {
|
||||
// ref를 통해 최신 값 참조 (클로저 문제 방지)
|
||||
const currentValue = selectedValueRef.current;
|
||||
const currentSections = sectionsRef.current;
|
||||
return [{
|
||||
[controlField]: currentValue,
|
||||
condition: currentValue,
|
||||
label: currentSections.find(s => s.condition === currentValue)?.label || currentValue,
|
||||
}];
|
||||
},
|
||||
|
||||
getAllData: () => {
|
||||
const currentSections = sectionsRef.current;
|
||||
return currentSections.map(section => ({
|
||||
condition: section.condition,
|
||||
label: section.label,
|
||||
}));
|
||||
},
|
||||
|
||||
clearSelection: () => {
|
||||
// 조건부 컨테이너는 초기화하지 않음
|
||||
console.log("조건부 컨테이너는 선택 초기화를 지원하지 않습니다.");
|
||||
},
|
||||
}), [componentId, controlField]); // selectedValue, sections는 ref로 참조
|
||||
|
||||
// 화면 컨텍스트에 데이터 제공자로 등록
|
||||
useEffect(() => {
|
||||
if (screenContext && componentId) {
|
||||
screenContext.registerDataProvider(componentId, dataProvider);
|
||||
|
||||
return () => {
|
||||
screenContext.unregisterDataProvider(componentId);
|
||||
};
|
||||
}
|
||||
}, [screenContext, componentId, dataProvider]);
|
||||
|
||||
// 컨테이너 높이 측정용 ref
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -158,6 +219,8 @@ export function ConditionalContainerComponent({
|
||||
onFormDataChange={onFormDataChange}
|
||||
groupedData={groupedData}
|
||||
onSave={onSave}
|
||||
controlField={controlField}
|
||||
selectedCondition={selectedValue}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -179,6 +242,8 @@ export function ConditionalContainerComponent({
|
||||
onFormDataChange={onFormDataChange}
|
||||
groupedData={groupedData}
|
||||
onSave={onSave}
|
||||
controlField={controlField}
|
||||
selectedCondition={selectedValue}
|
||||
/>
|
||||
) : null
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user