Merge branch 'main' into feature/screen-management
This commit is contained in:
commit
47b61a9a35
|
|
@ -175,13 +175,21 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
|
||||||
if (editData) {
|
if (editData) {
|
||||||
console.log("📝 [ScreenModal] 수정 데이터 설정:", editData);
|
console.log("📝 [ScreenModal] 수정 데이터 설정:", editData);
|
||||||
|
|
||||||
// 🆕 배열인 경우 (그룹 레코드) vs 단일 객체 처리
|
// 🆕 배열인 경우 두 가지 데이터를 설정:
|
||||||
|
// 1. formData: 첫 번째 요소(객체) - 일반 입력 필드용 (TextInput 등)
|
||||||
|
// 2. selectedData: 전체 배열 - 다중 항목 컴포넌트용 (SelectedItemsDetailInput 등)
|
||||||
if (Array.isArray(editData)) {
|
if (Array.isArray(editData)) {
|
||||||
console.log(`📝 [ScreenModal] 그룹 레코드 ${editData.length}개 설정`);
|
const firstRecord = editData[0] || {};
|
||||||
setFormData(editData as any); // 배열 그대로 전달 (SelectedItemsDetailInput에서 처리)
|
console.log(`📝 [ScreenModal] 그룹 레코드 ${editData.length}개 설정:`, {
|
||||||
setOriginalData(editData[0] || null); // 첫 번째 레코드를 원본으로 저장
|
formData: "첫 번째 레코드 (일반 입력 필드용)",
|
||||||
|
selectedData: "전체 배열 (다중 항목 컴포넌트용)",
|
||||||
|
});
|
||||||
|
setFormData(firstRecord); // 🔧 일반 입력 필드용 (객체)
|
||||||
|
setSelectedData(editData); // 🔧 다중 항목 컴포넌트용 (배열) - groupedData로 전달됨
|
||||||
|
setOriginalData(firstRecord); // 첫 번째 레코드를 원본으로 저장
|
||||||
} else {
|
} else {
|
||||||
setFormData(editData);
|
setFormData(editData);
|
||||||
|
setSelectedData([editData]); // 🔧 단일 객체도 배열로 변환하여 저장
|
||||||
setOriginalData(editData); // 🆕 원본 데이터 저장 (UPDATE 판단용)
|
setOriginalData(editData); // 🆕 원본 데이터 저장 (UPDATE 판단용)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -281,10 +281,12 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
||||||
// 컴포넌트의 columnName에 해당하는 formData 값 추출
|
// 컴포넌트의 columnName에 해당하는 formData 값 추출
|
||||||
const fieldName = (component as any).columnName || component.id;
|
const fieldName = (component as any).columnName || component.id;
|
||||||
|
|
||||||
// modal-repeater-table은 배열 데이터를 다루므로 빈 배열로 초기화
|
// 다중 레코드를 다루는 컴포넌트는 배열 데이터로 초기화
|
||||||
let currentValue;
|
let currentValue;
|
||||||
if (componentType === "modal-repeater-table" || componentType === "repeat-screen-modal") {
|
if (componentType === "modal-repeater-table" ||
|
||||||
// EditModal에서 전달된 groupedData가 있으면 우선 사용
|
componentType === "repeat-screen-modal" ||
|
||||||
|
componentType === "selected-items-detail-input") {
|
||||||
|
// EditModal/ScreenModal에서 전달된 groupedData가 있으면 우선 사용
|
||||||
currentValue = props.groupedData || formData?.[fieldName] || [];
|
currentValue = props.groupedData || formData?.[fieldName] || [];
|
||||||
} else {
|
} else {
|
||||||
currentValue = formData?.[fieldName] || "";
|
currentValue = formData?.[fieldName] || "";
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
||||||
screenId,
|
screenId,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
|
// 🆕 groupedData 추출 (DynamicComponentRenderer에서 전달)
|
||||||
|
const groupedData = (props as any).groupedData || (props as any)._groupedData;
|
||||||
// 🆕 URL 파라미터에서 dataSourceId 읽기
|
// 🆕 URL 파라미터에서 dataSourceId 읽기
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const urlDataSourceId = searchParams?.get("dataSourceId") || undefined;
|
const urlDataSourceId = searchParams?.get("dataSourceId") || undefined;
|
||||||
|
|
@ -225,24 +227,32 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
||||||
|
|
||||||
// 🆕 모달 데이터를 ItemData 구조로 변환 (그룹별 구조)
|
// 🆕 모달 데이터를 ItemData 구조로 변환 (그룹별 구조)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 🆕 수정 모드: formData에서 데이터 로드 (URL에 mode=edit이 있으면)
|
// 🆕 수정 모드: groupedData 또는 formData에서 데이터 로드 (URL에 mode=edit이 있으면)
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
const mode = urlParams.get("mode");
|
const mode = urlParams.get("mode");
|
||||||
|
|
||||||
if (mode === "edit" && formData) {
|
// 🔧 데이터 소스 우선순위: groupedData > formData (배열) > formData (객체)
|
||||||
|
const sourceData = groupedData && Array.isArray(groupedData) && groupedData.length > 0
|
||||||
|
? groupedData
|
||||||
|
: formData;
|
||||||
|
|
||||||
|
if (mode === "edit" && sourceData) {
|
||||||
// 배열인지 단일 객체인지 확인
|
// 배열인지 단일 객체인지 확인
|
||||||
const isArray = Array.isArray(formData);
|
const isArray = Array.isArray(sourceData);
|
||||||
const dataArray = isArray ? formData : [formData];
|
const dataArray = isArray ? sourceData : [sourceData];
|
||||||
|
|
||||||
if (dataArray.length === 0 || (dataArray.length === 1 && Object.keys(dataArray[0]).length === 0)) {
|
if (dataArray.length === 0 || (dataArray.length === 1 && Object.keys(dataArray[0]).length === 0)) {
|
||||||
console.warn("⚠️ [SelectedItemsDetailInput] formData가 비어있음");
|
console.warn("⚠️ [SelectedItemsDetailInput] 데이터가 비어있음");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`📝 [SelectedItemsDetailInput] 수정 모드 - ${isArray ? "그룹 레코드" : "단일 레코드"} (${dataArray.length}개)`,
|
`📝 [SelectedItemsDetailInput] 수정 모드 - ${isArray ? "그룹 레코드" : "단일 레코드"} (${dataArray.length}개)`,
|
||||||
);
|
);
|
||||||
console.log("📝 [SelectedItemsDetailInput] formData (JSON):", JSON.stringify(dataArray, null, 2));
|
console.log("📝 [SelectedItemsDetailInput] 데이터 소스:", {
|
||||||
|
fromGroupedData: groupedData && Array.isArray(groupedData) && groupedData.length > 0,
|
||||||
|
dataArray: JSON.stringify(dataArray, null, 2),
|
||||||
|
});
|
||||||
|
|
||||||
const groups = componentConfig.fieldGroups || [];
|
const groups = componentConfig.fieldGroups || [];
|
||||||
const additionalFields = componentConfig.additionalFields || [];
|
const additionalFields = componentConfig.additionalFields || [];
|
||||||
|
|
@ -423,7 +433,7 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [modalData, component.id, componentConfig.fieldGroups, formData]); // formData 의존성 추가
|
}, [modalData, component.id, componentConfig.fieldGroups, formData, groupedData]); // groupedData 의존성 추가
|
||||||
|
|
||||||
// 🆕 Cartesian Product 생성 함수 (items에서 모든 그룹의 조합을 생성)
|
// 🆕 Cartesian Product 생성 함수 (items에서 모든 그룹의 조합을 생성)
|
||||||
const generateCartesianProduct = useCallback(
|
const generateCartesianProduct = useCallback(
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
||||||
// 숨김 상태 (props에서 전달받은 값 우선 사용)
|
// 숨김 상태 (props에서 전달받은 값 우선 사용)
|
||||||
const isHidden = props.hidden !== undefined ? props.hidden : component.hidden || componentConfig.hidden || false;
|
const isHidden = props.hidden !== undefined ? props.hidden : component.hidden || componentConfig.hidden || false;
|
||||||
|
|
||||||
|
// 수정 모드 여부 확인 (originalData가 있으면 수정 모드)
|
||||||
|
const originalData = props.originalData || (props as any)._originalData;
|
||||||
|
const isEditMode = originalData && Object.keys(originalData).length > 0;
|
||||||
|
|
||||||
// 자동생성된 값 상태
|
// 자동생성된 값 상태
|
||||||
const [autoGeneratedValue, setAutoGeneratedValue] = useState<string>("");
|
const [autoGeneratedValue, setAutoGeneratedValue] = useState<string>("");
|
||||||
|
|
||||||
|
|
@ -99,6 +103,16 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🆕 수정 모드일 때는 채번 규칙 스킵 (기존 값 유지)
|
||||||
|
if (isEditMode) {
|
||||||
|
console.log("⏭️ 수정 모드 - 채번 규칙 스킵:", {
|
||||||
|
columnName: component.columnName,
|
||||||
|
originalValue: originalData?.[component.columnName],
|
||||||
|
});
|
||||||
|
hasGeneratedRef.current = true; // 생성 완료로 표시하여 재실행 방지
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (testAutoGeneration.enabled && testAutoGeneration.type !== "none") {
|
if (testAutoGeneration.enabled && testAutoGeneration.type !== "none") {
|
||||||
// 폼 데이터에 이미 값이 있으면 자동생성하지 않음
|
// 폼 데이터에 이미 값이 있으면 자동생성하지 않음
|
||||||
const currentFormValue = formData?.[component.columnName];
|
const currentFormValue = formData?.[component.columnName];
|
||||||
|
|
@ -171,7 +185,7 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
generateAutoValue();
|
generateAutoValue();
|
||||||
}, [testAutoGeneration.enabled, testAutoGeneration.type, component.columnName, isInteractive]);
|
}, [testAutoGeneration.enabled, testAutoGeneration.type, component.columnName, isInteractive, isEditMode]);
|
||||||
|
|
||||||
// 실제 화면에서 숨김 처리된 컴포넌트는 렌더링하지 않음
|
// 실제 화면에서 숨김 처리된 컴포넌트는 렌더링하지 않음
|
||||||
if (isHidden && !isDesignMode) {
|
if (isHidden && !isDesignMode) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue