Compare commits

..

No commits in common. "e9bd6777807f7b76c7dd2d16dcb882ef163e0217" and "d43a8c9e189eb4c65f57e6e1bf0248664a17dbb5" have entirely different histories.

2 changed files with 59 additions and 51 deletions

View File

@ -200,21 +200,12 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
// onChange 핸들러 - 컴포넌트 타입에 따라 다르게 처리
const handleChange = (value: any) => {
// React 이벤트 객체인 경우 값 추출
let actualValue = value;
if (value && typeof value === "object" && value.nativeEvent && value.target) {
// SyntheticEvent인 경우 target.value 추출
actualValue = value.target.value;
console.log("⚠️ DynamicComponentRenderer: 이벤트 객체 감지, value 추출:", actualValue);
}
console.log("🔄 DynamicComponentRenderer handleChange 호출:", {
componentType,
fieldName,
originalValue: value,
actualValue,
valueType: typeof actualValue,
isArray: Array.isArray(actualValue),
value,
valueType: typeof value,
isArray: Array.isArray(value),
});
if (onFormDataChange) {
@ -222,11 +213,11 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
// 단순 input 컴포넌트는 (fieldName, value) 형태로 전달받음
if (componentType === "repeater-field-group" || componentType === "repeater") {
// fieldName과 함께 전달
console.log("💾 RepeaterInput 데이터 저장:", fieldName, actualValue);
onFormDataChange(fieldName, actualValue);
console.log("💾 RepeaterInput 데이터 저장:", fieldName, value);
onFormDataChange(fieldName, value);
} else {
// 이미 fieldName이 포함된 경우는 그대로 전달
onFormDataChange(fieldName, actualValue);
onFormDataChange(fieldName, value);
}
}
};

View File

@ -325,8 +325,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setEmailUsername(newUsername);
const fullEmail = `${newUsername}@${emailDomain}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullEmail);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullEmail,
});
}
}}
className={`h-full flex-1 rounded-md border px-3 py-2 text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -364,8 +367,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setEmailDomain(value);
const fullEmail = `${emailUsername}@${value}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullEmail);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullEmail,
});
}
}}
/>
@ -382,8 +388,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setEmailDomain(currentValue);
const fullEmail = `${emailUsername}@${currentValue}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullEmail);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullEmail,
});
}
setEmailDomainOpen(false);
}}
@ -428,8 +437,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setTelPart1(value);
const fullTel = `${value}-${telPart2}-${telPart3}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullTel);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullTel,
});
}
}}
className={`h-full flex-1 rounded-md border px-3 py-2 text-center text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -450,8 +462,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setTelPart2(value);
const fullTel = `${telPart1}-${value}-${telPart3}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullTel);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullTel,
});
}
}}
className={`h-full flex-1 rounded-md border px-3 py-2 text-center text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -472,8 +487,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setTelPart3(value);
const fullTel = `${telPart1}-${telPart2}-${value}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullTel);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullTel,
});
}
}}
className={`h-full flex-1 rounded-md border px-3 py-2 text-center text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -505,8 +523,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setUrlProtocol(newProtocol);
const fullUrl = `${newProtocol}${urlDomain}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullUrl);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullUrl,
});
}
}}
className={`h-full w-[100px] cursor-pointer rounded-md border px-2 py-2 text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -527,8 +548,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
setUrlDomain(newDomain);
const fullUrl = `${urlProtocol}${newDomain}`;
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, fullUrl);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: fullUrl,
});
}
}}
className={`h-full flex-1 rounded-md border px-3 py-2 text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -571,8 +595,11 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
required={componentConfig.required || false}
readOnly={componentConfig.readonly || false}
onChange={(e) => {
if (isInteractive && onFormDataChange && component.columnName) {
onFormDataChange(component.columnName, e.target.value);
if (isInteractive && formData && onFormDataChange && component.columnName) {
onFormDataChange({
...formData,
[component.columnName]: e.target.value,
});
}
}}
className={`box-border h-full w-full max-w-full resize-none rounded-md border px-3 py-2 text-sm transition-all duration-200 outline-none ${isSelected ? "border-blue-500 ring-2 ring-blue-100" : "border-gray-300"} ${componentConfig.disabled ? "bg-gray-100 text-gray-400" : "bg-white text-gray-900"} placeholder:text-gray-400 focus:border-orange-500 focus:ring-2 focus:ring-orange-100 disabled:cursor-not-allowed`}
@ -598,13 +625,10 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
if (isInteractive && formData && component.columnName) {
// 인터랙티브 모드: formData 우선, 없으면 자동생성 값
const rawValue = formData[component.columnName] || autoGeneratedValue || "";
// 객체인 경우 빈 문자열로 변환 (에러 방지)
displayValue = typeof rawValue === "object" ? "" : String(rawValue);
displayValue = formData[component.columnName] || autoGeneratedValue || "";
} else {
// 디자인 모드: component.value 우선, 없으면 자동생성 값
const rawValue = component.value || autoGeneratedValue || "";
displayValue = typeof rawValue === "object" ? "" : String(rawValue);
displayValue = component.value || autoGeneratedValue || "";
}
console.log("📄 Input 값 계산:", {
@ -612,11 +636,9 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
hasFormData: !!formData,
columnName: component.columnName,
formDataValue: formData?.[component.columnName],
formDataValueType: typeof formData?.[component.columnName],
componentValue: component.value,
autoGeneratedValue,
finalDisplayValue: displayValue,
isObject: typeof displayValue === "object",
});
return displayValue;
@ -648,28 +670,23 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
// isInteractive 모드에서는 formData 업데이트
if (isInteractive && onFormDataChange && component.columnName) {
console.log(`✅ TextInputComponent onChange 조건 충족:`, {
columnName: component.columnName,
newValue,
valueType: typeof newValue,
isInteractive,
hasOnFormDataChange: !!onFormDataChange,
onFormDataChangeType: typeof onFormDataChange,
// console.log(`📤 TextInputComponent -> onFormDataChange 호출: ${component.columnName} = "${newValue}"`);
console.log("🔍 onFormDataChange 함수 정보:", {
functionName: onFormDataChange.name,
functionString: onFormDataChange.toString().substring(0, 200),
});
onFormDataChange(component.columnName, newValue);
console.log(`✅ onFormDataChange 호출 완료`);
} else {
console.log("❌ TextInputComponent onFormDataChange 조건 미충족:", {
isInteractive,
hasOnFormDataChange: !!onFormDataChange,
hasColumnName: !!component.columnName,
columnName: component.columnName,
});
}
// props.onChange는 DynamicComponentRenderer의 handleChange
// 이벤트 객체 감지 및 값 추출 로직이 있으므로 안전하게 호출 가능
// 기존 onChange 핸들러도 호출
if (props.onChange) {
// console.log(`📤 TextInputComponent -> props.onChange 호출: "${newValue}"`);
props.onChange(newValue);
}
}}