[251024] fix: SearchInputOverlay Recent Searches

🕐 커밋 시간: 2025. 10. 24. 10:51:08

📊 변경 통계:
  • 총 파일: 7개
  • 추가: +146줄
  • 삭제: -52줄

📁 추가된 파일:
  + com.twin.app.shoptime/src/hooks/useSearchHistory.js
  + com.twin.app.shoptime/src/utils/searchHistory.js

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

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • 공통 유틸리티 함수 최적화
  • 중간 규모 기능 개선
  • 모듈 구조 개선
This commit is contained in:
2025-10-24 10:51:11 +09:00
parent ec6c3aa4cd
commit 2ae50602c7
6 changed files with 422 additions and 52 deletions

View File

@@ -35,10 +35,11 @@ import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPag
import TVirtualGridList from '../../components/TVirtualGridList/TVirtualGridList';
// import VirtualKeyboardContainer from "../../components/TToast/VirtualKeyboardContainer";
import usePrevious from '../../hooks/usePrevious';
import { useSearchHistory } from '../../hooks/useSearchHistory';
import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, panel_names } from '../../utils/Config';
import NoSearchResults from './NoSearchResults/NoSearchResults';
// import NoSearchResults from './NoSearchResults/NoSearchResults';
import SearchInputOverlay from './SearchInpuOverlay';
import SearchInputOverlay from './SearchInputOverlay';
import css from './SearchPanel.new.module.less';
import SearchResultsNew from './SearchResults.new.v2';
import TInputSimple, { ICONS, KINDS } from './TInput/TInputSimple';
@@ -252,10 +253,13 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
const SafeImage = useCallback(SafeImageComponent, []);
/**
* memoized variables
* useSearchHistory Hook 적용
*/
// 가짜 데이터 - 실제로는 Redux store나 API에서 가져와야 함
const recentSearches = useMemo(() => ['Puppy food', 'Dog toy', 'Fitness'], []);
const {
normalSearches,
addNormalSearch,
executeSearchFromHistory,
} = useSearchHistory();
// Voice overlay suggestions (동적으로 변경 가능)
const voiceSuggestions = useMemo(
@@ -373,6 +377,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
}
if (query.trim()) {
// 일반 검색 기록 저장
addNormalSearch(query.trim());
dispatch(
getSearch({
domain: 'theme,show,item',
@@ -390,7 +397,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
setSearchQuery(query);
},
[searchPerformed, dispatch] // ✨ [Phase 3] dispatch 추가, showVirtualKeyboard 제거
[searchPerformed, dispatch, addNormalSearch] // ✨ [Phase 3] dispatch 추가, showVirtualKeyboard 제거, addNormalSearch 추가
);
/**
@@ -558,6 +565,28 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
[handleSearchSubmit]
);
/**
* 검색 기록에서 키워드 클릭 핸들러
*/
const handleHistoryKeywordClick = useCallback(
(historyItem) => {
if (!historyItem || !historyItem.query) {
return;
}
// 검색어 설정
setSearchQuery(historyItem.query);
// 검색 타입에 따라 다른 API 호출
executeSearchFromHistory(historyItem);
// Overlay 닫기 및 포커스 해제
setIsSearchOverlayVisible(false);
setInputFocus(false);
},
[executeSearchFromHistory]
);
/**
* 키워드 클릭 핸들러 생성 함수
*/
@@ -568,6 +597,16 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
[handleKeywordClick]
);
/**
* 검색 기록 키워드 클릭 핸들러 생성 함수
*/
const createHistoryKeywordClickHandler = useCallback(
(historyItem) => {
return () => handleHistoryKeywordClick(historyItem);
},
[handleHistoryKeywordClick]
);
/**
* Search overlay close handler
*/
@@ -727,8 +766,8 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
default:
return (
<ContainerBasic className={css.contentContainer}>
{/* 최근 검색어 섹션 */}
{recentSearches && recentSearches.length > 0 && (
{/* 최근 검색어 섹션 (일반검색만 표시) */}
{normalSearches && normalSearches.length > 0 && (
<>
<SectionContainer
className={css.section}
@@ -740,14 +779,14 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
<div className={css.sectionTitle}>Your Recent Searches</div>
</div>
<div className={css.keywordList}>
{recentSearches.map((keyword, index) => (
{normalSearches.map((historyItem, index) => (
<SpottableKeyword
key={`recent-${index}`}
key={`recent-${historyItem.timestamp}`}
className={css.keywordButton}
onClick={createKeywordClickHandler(keyword)}
onClick={createHistoryKeywordClickHandler(historyItem)}
spotlightId={`recent-keyword-${index}`}
>
{keyword}
{historyItem.query}
</SpottableKeyword>
))}
</div>
@@ -847,12 +886,13 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
searchDatas?.item?.length,
searchDatas?.show?.length,
shopperHouseData?.results?.[0]?.docs?.length,
recentSearches?.length,
normalSearches?.length,
topSearchs?.length,
popularBrands?.length,
hotPicksForYou?.length,
handleKeywordClick,
createKeywordClickHandler,
createHistoryKeywordClickHandler,
renderItem,
panelInfo?.currentSpot,
]);