발주관리 수정시 공급처 표시 오류 수정

This commit is contained in:
hjjeong 2026-01-05 18:21:29 +09:00
parent 714698c20f
commit 64105bf525
1 changed files with 141 additions and 4 deletions

View File

@ -44,7 +44,42 @@ export function AutocompleteSearchInputComponent({
const displayField = config?.displayField || propDisplayField || "";
const displayFields = config?.displayFields || (displayField ? [displayField] : []); // 다중 표시 필드
const displaySeparator = config?.displaySeparator || " → "; // 구분자
const valueField = config?.valueField || propValueField || "";
// valueField 결정: fieldMappings 기반으로 추론 (config.valueField가 fieldMappings에 없으면 무시)
const getValueField = () => {
// fieldMappings가 있으면 그 안에서 추론 (가장 신뢰할 수 있는 소스)
if (config?.fieldMappings && config.fieldMappings.length > 0) {
// config.valueField가 fieldMappings의 sourceField에 있으면 사용
if (config?.valueField) {
const hasValueFieldInMappings = config.fieldMappings.some(
(m: any) => m.sourceField === config.valueField
);
if (hasValueFieldInMappings) {
return config.valueField;
}
// fieldMappings에 없으면 무시하고 추론
}
// _code 또는 _id로 끝나는 필드 우선 (보통 PK나 코드 필드)
const codeMapping = config.fieldMappings.find(
(m: any) => m.sourceField?.endsWith("_code") || m.sourceField?.endsWith("_id")
);
if (codeMapping) {
return codeMapping.sourceField;
}
// 없으면 첫 번째 매핑 사용
return config.fieldMappings[0].sourceField || "";
}
// fieldMappings가 없으면 기존 방식
if (config?.valueField) return config.valueField;
if (propValueField) return propValueField;
return "";
};
const valueField = getValueField();
const searchFields = config?.searchFields || propSearchFields || displayFields; // 검색 필드도 다중 표시 필드 사용
const placeholder = config?.placeholder || propPlaceholder || "검색...";
@ -76,11 +111,39 @@ export function AutocompleteSearchInputComponent({
// 선택된 데이터를 ref로도 유지 (리렌더링 시 초기화 방지)
const selectedDataRef = useRef<EntitySearchResult | null>(null);
const inputValueRef = useRef<string>("");
const initialValueLoadedRef = useRef<string | null>(null); // 초기값 로드 추적
// formData에서 현재 값 가져오기 (isInteractive 모드)
const currentValue = isInteractive && formData && component?.columnName
? formData[component.columnName]
: value;
// 우선순위: 1) component.columnName, 2) fieldMappings에서 valueField에 매핑된 targetField
const getCurrentValue = () => {
if (!isInteractive || !formData) {
return value;
}
// 1. component.columnName으로 직접 바인딩된 경우
if (component?.columnName && formData[component.columnName] !== undefined) {
return formData[component.columnName];
}
// 2. fieldMappings에서 valueField와 매핑된 targetField에서 값 가져오기
if (config?.fieldMappings && Array.isArray(config.fieldMappings)) {
const valueFieldMapping = config.fieldMappings.find(
(mapping: any) => mapping.sourceField === valueField
);
if (valueFieldMapping) {
const targetField = valueFieldMapping.targetField || valueFieldMapping.targetColumn;
if (targetField && formData[targetField] !== undefined) {
return formData[targetField];
}
}
}
return value;
};
const currentValue = getCurrentValue();
// selectedData 변경 시 ref도 업데이트
useEffect(() => {
@ -98,6 +161,79 @@ export function AutocompleteSearchInputComponent({
}
}, []);
// 초기값이 있을 때 해당 값의 표시 텍스트를 조회하여 설정
useEffect(() => {
const loadInitialDisplayValue = async () => {
// 이미 로드된 값이거나, 값이 없거나, 이미 선택된 데이터가 있으면 스킵
if (!currentValue || selectedData || selectedDataRef.current) {
return;
}
// 이미 같은 값을 로드한 적이 있으면 스킵
if (initialValueLoadedRef.current === currentValue) {
return;
}
// 테이블명과 필드 정보가 없으면 스킵
if (!tableName || !valueField) {
return;
}
console.log("🔄 AutocompleteSearchInput 초기값 로드:", {
currentValue,
tableName,
valueField,
displayFields,
});
try {
// API를 통해 해당 값의 표시 텍스트 조회
const { apiClient } = await import("@/lib/api/client");
const filterConditionWithValue = {
...filterCondition,
[valueField]: currentValue,
};
const params = new URLSearchParams({
searchText: "",
searchFields: searchFields.join(","),
filterCondition: JSON.stringify(filterConditionWithValue),
page: "1",
limit: "10",
});
const response = await apiClient.get<{ success: boolean; data: EntitySearchResult[] }>(
`/entity-search/${tableName}?${params.toString()}`
);
if (response.data.success && response.data.data && response.data.data.length > 0) {
const matchedItem = response.data.data.find((item: EntitySearchResult) =>
String(item[valueField]) === String(currentValue)
);
if (matchedItem) {
const displayText = getDisplayValue(matchedItem);
console.log("✅ 초기값 표시 텍스트 로드 성공:", {
currentValue,
displayText,
matchedItem,
});
setSelectedData(matchedItem);
setInputValue(displayText);
selectedDataRef.current = matchedItem;
inputValueRef.current = displayText;
initialValueLoadedRef.current = currentValue;
}
}
} catch (error) {
console.error("❌ 초기값 표시 텍스트 로드 실패:", error);
}
};
loadInitialDisplayValue();
}, [currentValue, tableName, valueField, displayFields, filterCondition, searchFields, selectedData]);
// value가 변경되면 표시값 업데이트 - 단, selectedData가 있으면 유지
useEffect(() => {
// selectedData가 있으면 표시값 유지 (사용자가 방금 선택한 경우)
@ -107,6 +243,7 @@ export function AutocompleteSearchInputComponent({
if (!currentValue) {
setInputValue("");
initialValueLoadedRef.current = null; // 값이 없어지면 초기화
}
}, [currentValue, selectedData]);