[251028] feat: HowAboutTheseResponse-1

🕐 커밋 시간: 2025. 10. 28. 19:47:39

📊 변경 통계:
  • 총 파일: 6개
  • 추가: +142줄
  • 삭제: -38줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/searchActions.js
  ~ com.twin.app.shoptime/src/views/SearchPanel/HowAboutThese/HowAboutThese.response.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/HowAboutThese/HowAboutThese.response.module.less
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchPanel.new.v2.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.module.less

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • 중간 규모 기능 개선
  • 모듈 구조 개선
This commit is contained in:
2025-10-28 19:47:40 +09:00
parent 23d0b5374e
commit c95e8af4cf
6 changed files with 141 additions and 37 deletions

View File

@@ -144,6 +144,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
const panels = useSelector((state) => state.panels.panels);
// 0hun: 음성 검색 결과에 대한 전역 상태
const shopperHouseData = useSelector((state) => state.search.shopperHouseData);
const shopperHouseError = useSelector((state) => state.search.shopperHouseError);
// 0hun: 음성 검색 searchId (Redux에서 별도 관리)
const shopperHouseSearchId = useSelector((state) => state.search.shopperHouseSearchId);
// 0hun: 음성 검색 relativeQueries (Redux에서 별도 관리)
@@ -181,6 +182,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
// ✨ [Phase 1] SearchPanel의 현재 모드 상태 (VoiceInputOverlay의 VOICE_MODES와 동일한 개념)
const [currentMode, setCurrentMode] = useState(SEARCH_PANEL_MODES.INITIAL);
const [isShopperHousePending, setIsShopperHousePending] = useState(false);
const [voiceOverlayMode, setVoiceOverlayMode] = useState(VOICE_MODES.PROMPT);
const [voiceOverlayResponseText, setVoiceOverlayResponseText] = useState('');
const [isVoiceOverlayBubbleSearch, setIsVoiceOverlayBubbleSearch] = useState(false);
@@ -547,6 +549,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
currentMode,
searchQuery,
hasShopperHouseData: !!shopperHouseData,
isShopperHousePending,
});
}
@@ -593,6 +596,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
console.log('[VoiceInput] 🧹 VOICE_RESULT 모드에서 ESC 누름 - clearShopperHouseData 호출');
}
// 🎯 [포커스 로직 통합] 포커스는 상태 변경에 의해 자동으로 처리됨
setIsShopperHousePending(false);
dispatch(clearShopperHouseData()); // ✨ shopperHouseData만 초기화, searchId & relativeQuerys 유지
return;
}
@@ -1027,13 +1031,21 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
setSearchQuery(trimmedQuery);
// Voice overlay를 RESPONSE 모드로 전환하여 대기 화면 표시
setVoiceOverlayResponseText(trimmedQuery);
setVoiceOverlayMode(VOICE_MODES.RESPONSE);
setIsVoiceOverlayBubbleSearch(true);
setIsVoiceOverlayVisible(true);
setShouldFocusVoiceResult(false);
// setVoiceOverlayResponseText(trimmedQuery);
// setVoiceOverlayMode(VOICE_MODES.RESPONSE);
// setIsVoiceOverlayBubbleSearch(true);
// setIsVoiceOverlayVisible(true);
// setShouldFocusVoiceResult(false);
dispatch(getShopperHouseSearch(trimmedQuery, shopperHouseSearchId));
// API 호출 전에 이전 데이터 초기화
setIsShopperHousePending(true);
dispatch(clearShopperHouseData());
// Redux state 업데이트를 위해 약간의 지연 후 API 호출
setTimeout(() => {
console.log('[HowAboutThese] 🔄 Redux 업데이트 후 API 호출');
dispatch(getShopperHouseSearch(trimmedQuery, shopperHouseSearchId));
}, 50); // 50ms 지연
// 🎯 [포커스 로직 통합] 검색어만 업데이트
// 포커스는 shopperHouseData 변경에 의해 자동으로 처리됨
@@ -1050,6 +1062,20 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
[dispatch, shopperHouseSearchId]
);
// ShopperHouse API 응답 도착 시 로딩 상태 해제
useEffect(() => {
if (shopperHouseData) {
setIsShopperHousePending(false);
}
}, [shopperHouseData]);
// ShopperHouse API 오류 발생 시 로딩 상태 해제
useEffect(() => {
if (shopperHouseError) {
setIsShopperHousePending(false);
}
}, [shopperHouseError]);
// ✨ [Phase 3] handleInputIconClick 제거 (돋보기 아이콘 기능 비활성화)
// /**
// * ✨ [Phase 3] TInput icon click handler (showVirtualKeyboard 제거)
@@ -1355,12 +1381,13 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
searchQuery,
hasSearchResults: !!(
searchDatas?.theme?.length > 0 ||
searchDatas?.item?.length > 0 ||
searchDatas?.show?.length > 0
),
isSearchOverlayVisible,
currentMode,
});
searchDatas?.item?.length > 0 ||
searchDatas?.show?.length > 0
),
isSearchOverlayVisible,
isShopperHousePending,
currentMode,
});
}
// 우선순위 1: 음성 입력 오버레이가 열려있으면 VOICE_INPUT 모드
@@ -1371,9 +1398,12 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
nextMode = SEARCH_PANEL_MODES.VOICE_INPUT;
}
// 우선순위 2: 음성 검색 결과가 있으면 VOICE_RESULT 모드
else if (shopperHouseData) {
else if (shopperHouseData || isShopperHousePending) {
if (DEBUG_MODE) {
console.log('[DEBUG]-MODE: shopperHouseData EXISTS → VOICE_RESULT');
console.log('[DEBUG]-MODE: shopperHouseData EXISTS or pending → VOICE_RESULT', {
hasData: !!shopperHouseData,
isPending: isShopperHousePending,
});
}
nextMode = SEARCH_PANEL_MODES.VOICE_RESULT;
}
@@ -1410,6 +1440,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
console.log(`[DEBUG]-VOICE_RESULT 🔀 Mode changed: ${currentMode}${nextMode}`, {
isVoiceOverlayVisible,
shopperHouseData: !!shopperHouseData,
isShopperHousePending,
searchPerformed,
searchQuery,
hasSearchResults: !!(
@@ -1430,6 +1461,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
}, [
isVoiceOverlayVisible,
shopperHouseData,
isShopperHousePending,
searchPerformed,
searchQuery,
searchDatas,