diff --git a/frontend/components/screen/EditModal.tsx b/frontend/components/screen/EditModal.tsx index cde9086c..024f7ac7 100644 --- a/frontend/components/screen/EditModal.tsx +++ b/frontend/components/screen/EditModal.tsx @@ -304,7 +304,24 @@ export const EditModal: React.FC = ({ className }) => { }; // 저장 버튼 클릭 시 - UPDATE 액션 실행 - const handleSave = async () => { + const handleSave = async (saveData?: any) => { + // universal-form-modal 등에서 자체 저장 완료 후 호출된 경우 스킵 + if (saveData?._saveCompleted) { + console.log("[EditModal] 자체 저장 완료된 컴포넌트에서 호출됨 - 저장 스킵"); + + // 부모 컴포넌트의 onSave 콜백 실행 (테이블 새로고침) + if (modalState.onSave) { + try { + modalState.onSave(); + } catch (callbackError) { + console.error("onSave 콜백 에러:", callbackError); + } + } + + handleClose(); + return; + } + if (!screenData?.screenInfo?.tableName) { toast.error("테이블 정보가 없습니다."); return; diff --git a/frontend/lib/registry/components/modal-repeater-table/ModalRepeaterTableComponent.tsx b/frontend/lib/registry/components/modal-repeater-table/ModalRepeaterTableComponent.tsx index 6302e7f9..3a5b43dd 100644 --- a/frontend/lib/registry/components/modal-repeater-table/ModalRepeaterTableComponent.tsx +++ b/frontend/lib/registry/components/modal-repeater-table/ModalRepeaterTableComponent.tsx @@ -193,7 +193,18 @@ export function ModalRepeaterTableComponent({ // ✅ value는 formData[columnName] 우선, 없으면 prop 사용 const columnName = component?.columnName; - const value = (columnName && formData?.[columnName]) || componentConfig?.value || propValue || []; + const externalValue = (columnName && formData?.[columnName]) || componentConfig?.value || propValue || []; + + // 🆕 내부 상태로 데이터 관리 (즉시 UI 반영을 위해) + const [localValue, setLocalValue] = useState(externalValue); + + // 🆕 외부 값(formData, propValue) 변경 시 내부 상태 동기화 + useEffect(() => { + // 외부 값이 변경되었고, 내부 값과 다른 경우에만 동기화 + if (JSON.stringify(externalValue) !== JSON.stringify(localValue)) { + setLocalValue(externalValue); + } + }, [externalValue]); // ✅ onChange 래퍼 (기존 onChange 콜백 + onFormDataChange 호출 + 납기일 일괄 적용) const handleChange = (newData: any[]) => { @@ -249,6 +260,9 @@ export function ModalRepeaterTableComponent({ } } + // 🆕 내부 상태 즉시 업데이트 (UI 즉시 반영) - 일괄 적용된 데이터로 업데이트 + setLocalValue(processedData); + // 기존 onChange 콜백 호출 (호환성) const externalOnChange = componentConfig?.onChange || propOnChange; if (externalOnChange) { @@ -321,7 +335,7 @@ export function ModalRepeaterTableComponent({ const handleSaveRequest = async (event: Event) => { const componentKey = columnName || component?.id || "modal_repeater_data"; - if (value.length === 0) { + if (localValue.length === 0) { console.warn("⚠️ [ModalRepeaterTable] 저장할 데이터 없음"); return; } @@ -332,7 +346,7 @@ export function ModalRepeaterTableComponent({ .filter(col => col.mapping?.type === "source" && col.mapping?.sourceField) .map(col => col.field); - const filteredData = value.map((item: any) => { + const filteredData = localValue.map((item: any) => { const filtered: Record = {}; Object.keys(item).forEach((key) => { @@ -389,16 +403,16 @@ export function ModalRepeaterTableComponent({ return () => { window.removeEventListener("beforeFormSave", handleSaveRequest as EventListener); }; - }, [value, columnName, component?.id, onFormDataChange, targetTable]); + }, [localValue, columnName, component?.id, onFormDataChange, targetTable]); const { calculateRow, calculateAll } = useCalculation(calculationRules); // 초기 데이터에 계산 필드 적용 useEffect(() => { - if (value.length > 0 && calculationRules.length > 0) { - const calculated = calculateAll(value); + if (localValue.length > 0 && calculationRules.length > 0) { + const calculated = calculateAll(localValue); // 값이 실제로 변경된 경우만 업데이트 - if (JSON.stringify(calculated) !== JSON.stringify(value)) { + if (JSON.stringify(calculated) !== JSON.stringify(localValue)) { handleChange(calculated); } } @@ -506,7 +520,7 @@ export function ModalRepeaterTableComponent({ const calculatedItems = calculateAll(mappedItems); // 기존 데이터에 추가 - const newData = [...value, ...calculatedItems]; + const newData = [...localValue, ...calculatedItems]; console.log("✅ 최종 데이터:", newData.length, "개 항목"); // ✅ 통합 onChange 호출 (formData 반영 포함) @@ -518,7 +532,7 @@ export function ModalRepeaterTableComponent({ const calculatedRow = calculateRow(newRow); // 데이터 업데이트 - const newData = [...value]; + const newData = [...localValue]; newData[index] = calculatedRow; // ✅ 통합 onChange 호출 (formData 반영 포함) @@ -526,7 +540,7 @@ export function ModalRepeaterTableComponent({ }; const handleRowDelete = (index: number) => { - const newData = value.filter((_, i) => i !== index); + const newData = localValue.filter((_, i) => i !== index); // ✅ 통합 onChange 호출 (formData 반영 포함) handleChange(newData); @@ -543,7 +557,7 @@ export function ModalRepeaterTableComponent({ {/* 추가 버튼 */}
- {value.length > 0 && `${value.length}개 항목`} + {localValue.length > 0 && `${localValue.length}개 항목`}