diff --git a/frontend/lib/registry/components/location-swap-selector/LocationSwapSelectorComponent.tsx b/frontend/lib/registry/components/location-swap-selector/LocationSwapSelectorComponent.tsx index 02f4e436..53fd0c0c 100644 --- a/frontend/lib/registry/components/location-swap-selector/LocationSwapSelectorComponent.tsx +++ b/frontend/lib/registry/components/location-swap-selector/LocationSwapSelectorComponent.tsx @@ -94,21 +94,21 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps) const showSwapButton = config.showSwapButton !== false && props.showSwapButton !== false; const variant = config.variant || props.variant || "card"; - // 상태 - const [options, setOptions] = useState([]); - const [loading, setLoading] = useState(false); - const [isSwapping, setIsSwapping] = useState(false); - - // 현재 선택된 값 - const departureValue = formData[departureField] || ""; - const destinationValue = formData[destinationField] || ""; - // 기본 옵션 (포항/광양) const DEFAULT_OPTIONS: LocationOption[] = [ { value: "pohang", label: "포항" }, { value: "gwangyang", label: "광양" }, ]; + // 상태 + const [options, setOptions] = useState(DEFAULT_OPTIONS); + const [loading, setLoading] = useState(false); + const [isSwapping, setIsSwapping] = useState(false); + + // 로컬 선택 상태 (Select 컴포넌트용) + const [localDeparture, setLocalDeparture] = useState(""); + const [localDestination, setLocalDestination] = useState(""); + // 옵션 로드 useEffect(() => { const loadOptions = async () => { @@ -124,13 +124,19 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps) if (shouldUseStatic) { const staticOpts = dataSource.staticOptions || []; - // 정적 옵션이 설정되어 있으면 사용 - if (staticOpts.length > 0 && staticOpts[0]?.value) { + // 정적 옵션이 설정되어 있고, value가 유효한 경우 사용 + // (value가 필드명과 같으면 잘못 설정된 것이므로 기본값 사용) + const isValidOptions = staticOpts.length > 0 && + staticOpts[0]?.value && + staticOpts[0].value !== departureField && + staticOpts[0].value !== destinationField; + + if (isValidOptions) { console.log("[LocationSwapSelector] 정적 옵션 사용:", staticOpts); setOptions(staticOpts); } else { // 기본값 (포항/광양) - console.log("[LocationSwapSelector] 기본 옵션 사용:", DEFAULT_OPTIONS); + console.log("[LocationSwapSelector] 기본 옵션 사용 (잘못된 설정 감지):", { staticOpts, DEFAULT_OPTIONS }); setOptions(DEFAULT_OPTIONS); } return; @@ -187,69 +193,109 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps) loadOptions(); }, [dataSource, isDesignMode]); + // formData에서 초기값 동기화 + useEffect(() => { + const depVal = formData[departureField]; + const destVal = formData[destinationField]; + + if (depVal && options.some(o => o.value === depVal)) { + setLocalDeparture(depVal); + } + if (destVal && options.some(o => o.value === destVal)) { + setLocalDestination(destVal); + } + }, [formData, departureField, destinationField, options]); + // 출발지 변경 - const handleDepartureChange = (value: string) => { + const handleDepartureChange = (selectedValue: string) => { + console.log("[LocationSwapSelector] 출발지 변경:", { selectedValue, options }); + + // 로컬 상태 업데이트 + setLocalDeparture(selectedValue); + + // 부모에게 전달 if (onFormDataChange) { - onFormDataChange(departureField, value); + onFormDataChange(departureField, selectedValue); // 라벨 필드도 업데이트 if (departureLabelField) { - const selectedOption = options.find((opt) => opt.value === value); - onFormDataChange(departureLabelField, selectedOption?.label || ""); + const selectedOption = options.find((opt) => opt.value === selectedValue); + if (selectedOption) { + onFormDataChange(departureLabelField, selectedOption.label); + } } } }; // 도착지 변경 - const handleDestinationChange = (value: string) => { + const handleDestinationChange = (selectedValue: string) => { + console.log("[LocationSwapSelector] 도착지 변경:", { selectedValue, options }); + + // 로컬 상태 업데이트 + setLocalDestination(selectedValue); + + // 부모에게 전달 if (onFormDataChange) { - onFormDataChange(destinationField, value); + onFormDataChange(destinationField, selectedValue); // 라벨 필드도 업데이트 if (destinationLabelField) { - const selectedOption = options.find((opt) => opt.value === value); - onFormDataChange(destinationLabelField, selectedOption?.label || ""); + const selectedOption = options.find((opt) => opt.value === selectedValue); + if (selectedOption) { + onFormDataChange(destinationLabelField, selectedOption.label); + } } } }; // 출발지/도착지 교환 const handleSwap = () => { - if (!onFormDataChange) return; - setIsSwapping(true); - // 값 교환 - const tempDeparture = departureValue; - const tempDestination = destinationValue; + // 로컬 상태 교환 + const tempDeparture = localDeparture; + const tempDestination = localDestination; + + setLocalDeparture(tempDestination); + setLocalDestination(tempDeparture); - onFormDataChange(departureField, tempDestination); - onFormDataChange(destinationField, tempDeparture); + // 부모에게 전달 + if (onFormDataChange) { + onFormDataChange(departureField, tempDestination); + onFormDataChange(destinationField, tempDeparture); - // 라벨도 교환 - if (departureLabelField && destinationLabelField) { - const tempDepartureLabel = formData[departureLabelField]; - const tempDestinationLabel = formData[destinationLabelField]; - onFormDataChange(departureLabelField, tempDestinationLabel); - onFormDataChange(destinationLabelField, tempDepartureLabel); + // 라벨도 교환 + if (departureLabelField && destinationLabelField) { + const depOption = options.find(o => o.value === tempDestination); + const destOption = options.find(o => o.value === tempDeparture); + onFormDataChange(departureLabelField, depOption?.label || ""); + onFormDataChange(destinationLabelField, destOption?.label || ""); + } } // 애니메이션 효과 setTimeout(() => setIsSwapping(false), 300); }; - // 선택된 라벨 가져오기 - const getDepartureLabel = () => { - const option = options.find((opt) => opt.value === departureValue); - return option?.label || "선택"; - }; - - const getDestinationLabel = () => { - const option = options.find((opt) => opt.value === destinationValue); - return option?.label || "선택"; - }; - // 스타일에서 width, height 추출 const { width, height, ...restStyle } = style || {}; + // 선택된 라벨 가져오기 + const getDepartureLabel = () => { + const opt = options.find(o => o.value === localDeparture); + return opt?.label || ""; + }; + + const getDestinationLabel = () => { + const opt = options.find(o => o.value === localDestination); + return opt?.label || ""; + }; + + // 디버그 로그 + console.log("[LocationSwapSelector] 렌더:", { + localDeparture, + localDestination, + options: options.map(o => `${o.value}:${o.label}`), + }); + // Card 스타일 (이미지 참고) if (variant === "card") { return ( @@ -263,27 +309,26 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps)
{departureLabel}
@@ -308,27 +353,26 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps)
{destinationLabel}
@@ -348,23 +392,19 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps)
@@ -384,23 +424,19 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps)
@@ -416,23 +452,19 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps) style={restStyle} > @@ -449,23 +481,19 @@ export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps) )}