[251024] [251025] feat: Voice검색 후 포커스 문제

🕐 커밋 시간: 2025. 10. 24. 21:16:53

📊 변경 통계:
  • 총 파일: 2개
  • 추가: +76줄
  • 삭제: -21줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchPanel.new.v2.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx

🔧 주요 변경 내용:
  • 소규모 기능 개선
This commit is contained in:
2025-10-24 21:16:53 +00:00
parent 587acbd2ee
commit 2838e4b8ec
2 changed files with 76 additions and 21 deletions

View File

@@ -183,6 +183,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
const [voiceOverlayMode, setVoiceOverlayMode] = useState(VOICE_MODES.PROMPT);
const [voiceOverlayResponseText, setVoiceOverlayResponseText] = useState('');
const [isVoiceOverlayBubbleSearch, setIsVoiceOverlayBubbleSearch] = useState(false);
const [shouldFocusVoiceResult, setShouldFocusVoiceResult] = useState(false);
// 🐛 [DEBUG] shopperHouseData 상태 변경 추적 (DEBUG_MODE가 true일 경우에만)
useEffect(() => {
@@ -657,11 +658,15 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
setVoiceOverlayResponseText('');
setIsVoiceOverlayBubbleSearch(false);
setIsVoiceOverlayVisible(false);
// ✅ VoiceOverlay가 닫힐 때 항상 TInput으로 포커스 이동
setTimeout(() => {
Spotlight.focus(SPOTLIGHT_IDS.SEARCH_INPUT_BOX);
}, 150); // Overlay 닫히는 시간을 고려한 지연
}, []);
setShouldFocusVoiceResult(false);
// ShopperHouse 데이터가 없을 때만 검색 인풋으로 포커스 복원
if (!shopperHouseData) {
setTimeout(() => {
Spotlight.focus(SPOTLIGHT_IDS.SEARCH_INPUT_BOX);
}, 150); // Overlay 닫히는 시간을 고려한 지연
}
}, [shopperHouseData]);
const handleHowAboutTheseQueryClick = useCallback(
(rawQuery) => {
@@ -678,6 +683,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
setVoiceOverlayMode(VOICE_MODES.RESPONSE);
setIsVoiceOverlayBubbleSearch(true);
setIsVoiceOverlayVisible(true);
setShouldFocusVoiceResult(false);
dispatch(getShopperHouseSearch(trimmedQuery, shopperHouseSearchId));
},
@@ -1161,7 +1167,47 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
clearTimeout(focusTimer);
};
}
}, [shopperHouseData, isOnTop, currentMode]);
}, [shopperHouseData, isOnTop, currentMode, DEBUG_MODE]);
useEffect(() => {
if (
isOnTop &&
currentMode === SEARCH_PANEL_MODES.VOICE_RESULT &&
shopperHouseData?.results?.[0]?.docs?.length > 0 &&
!isVoiceOverlayVisible
) {
if (DEBUG_MODE) {
console.log('[DEBUG] 🎯 ShopperHouse 데이터 감지 - 상품 포커스 예약');
}
setShouldFocusVoiceResult(true);
}
}, [isOnTop, currentMode, shopperHouseData, isVoiceOverlayVisible, DEBUG_MODE]);
useEffect(() => {
if (!shouldFocusVoiceResult) {
return;
}
const focusTimer = setTimeout(() => {
const targetId = 'searchItemContents0';
const targetElement = document.querySelector(`[data-spotlight-id="${targetId}"]`);
if (targetElement) {
Spotlight.focus(targetId);
if (DEBUG_MODE) {
console.log('[DEBUG] 🎯 ShopperHouse 첫 상품으로 포커스 이동:', targetId);
}
} else if (DEBUG_MODE) {
console.log('[DEBUG] ⚠️ ShopperHouse 첫 상품을 찾지 못했습니다');
}
setShouldFocusVoiceResult(false);
}, 200);
return () => {
clearTimeout(focusTimer);
};
}, [shouldFocusVoiceResult, DEBUG_MODE]);
/**
* LOG 용도,

View File

@@ -151,6 +151,7 @@ const SearchResultsNew = ({
const buttonTabList = useMemo(() => getButtonTabList(), [getButtonTabList]);
// 현재 탭의 데이터 가져오기 - ShopperHouse 데이터 우선
const hasShopperHouseItems = convertedShopperHouseItems?.length > 0;
const currentData = tab === 0 ? convertedShopperHouseItems || itemInfo : showInfo;
// 표시할 데이터 (처음부터 visibleCount 개수만큼)
@@ -209,20 +210,22 @@ const SearchResultsNew = ({
}
const targetId =
themeInfo?.length > 0
? 'searchProduct-0'
: itemInfo?.length > 0
? 'searchItemContents0'
: showInfo?.length > 0
? 'categoryShowContents0'
: null;
hasShopperHouseItems
? 'searchItemContents0'
: themeInfo?.length > 0
? 'searchProduct-0'
: itemInfo?.length > 0
? 'searchItemContents0'
: showInfo?.length > 0
? 'categoryShowContents0'
: null;
if (!targetId) {
Spotlight.focus('search-input-box');
} else {
Spotlight.focus(targetId);
}
}, []);
}, [hasShopperHouseItems, themeInfo, itemInfo, showInfo]);
// 10개씩 추가 로드 (아래 버튼)
const downBtnClick = useCallback(() => {
@@ -283,13 +286,15 @@ const SearchResultsNew = ({
useEffect(() => {
const targetId = panelInfo?.currentSpot
? panelInfo?.currentSpot
: themeInfo?.length > 0
? 'searchProduct-0'
: itemInfo?.length > 0
? 'searchItemContents0'
: showInfo?.length > 0
? 'categoryShowContents0'
: null;
: hasShopperHouseItems
? 'searchItemContents0'
: themeInfo?.length > 0
? 'searchProduct-0'
: itemInfo?.length > 0
? 'searchItemContents0'
: showInfo?.length > 0
? 'categoryShowContents0'
: null;
if (!targetId) return;
@@ -301,6 +306,10 @@ const SearchResultsNew = ({
itemInfo?.length,
showInfo?.length,
convertedShopperHouseItems?.length, // shopperHouseInfo 대신 구체적인 의존성 사용
hasShopperHouseItems,
themeInfo,
itemInfo,
showInfo,
]);
return (