[서치 메인] today deals 노출 작업

- 데이터 받는곳 추가 및 노출 작업.
This commit is contained in:
junghoon86.park
2025-11-03 12:47:41 +09:00
parent a41dca6169
commit 52b1949330
3 changed files with 160 additions and 13 deletions

View File

@@ -1,27 +1,45 @@
// src/views/SearchPanel/SearchPanel.new.jsx
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import classNames from 'classnames';
import { useDispatch, useSelector } from 'react-redux';
import {
useDispatch,
useSelector,
} from 'react-redux';
import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable';
import micIcon from '../../../assets/images/searchpanel/image-mic.png';
import hotPicksImage from '../../../assets/images/searchpanel/img-hotpicks.png';
import hotPicksBrandImage from '../../../assets/images/searchpanel/img-search-hotpicks.png';
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions';
import { getMyRecommandedKeyword } from '../../actions/myPageActions';
import { popPanel, pushPanel, updatePanel } from '../../actions/panelActions';
import hotPicksBrandImage
from '../../../assets/images/searchpanel/img-search-hotpicks.png';
import {
sendLogGNB,
sendLogTotalRecommend,
} from '../../actions/logActions';
import { getMyRecommandedKeyword } from '../../actions/myPageActions';
import {
popPanel,
pushPanel,
updatePanel,
} from '../../actions/panelActions';
import {
clearPanelCommand,
clearShopperHouseData,
getSearch,
getSearchMain,
getShopperHouseSearch,
resetSearch,
resetVoiceSearch,
clearPanelCommand,
transitionToSearchInputOverlay,
} from '../../actions/searchActions';
// import {
@@ -33,21 +51,36 @@ import {
// showWarningToast,
// } from '../../actions/toastActions';
import TBody from '../../components/TBody/TBody';
import TItemCardNew, {
removeDotAndColon,
} from '../../components/TItemCard/TItemCard.new';
import TPanel from '../../components/TPanel/TPanel';
import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator';
import TVirtualGridList from '../../components/TVirtualGridList/TVirtualGridList';
import TVerticalPagenator
from '../../components/TVerticalPagenator/TVerticalPagenator';
import TVirtualGridList
from '../../components/TVirtualGridList/TVirtualGridList';
import usePanelHistory from '../../hooks/usePanelHistory/usePanelHistory';
// 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 {
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 './SearchInputOverlay';
import css from './SearchPanel.new.module.less';
import SearchResultsNew from './SearchResults.new.v2';
import TInputSimple, { ICONS, KINDS } from './TInput/TInputSimple';
import VoiceInputOverlay, { VOICE_MODES } from './VoiceInputOverlay/VoiceInputOverlay';
import TInputSimple, {
ICONS,
KINDS,
} from './TInput/TInputSimple';
import VoiceInputOverlay, {
VOICE_MODES,
} from './VoiceInputOverlay/VoiceInputOverlay';
/**
* ✨ Mode-Based Architecture 도입
@@ -126,6 +159,7 @@ const SPOTLIGHT_IDS = {
TOP_SEARCHES_SECTION: 'top-searches-section',
POPULAR_BRANDS_SECTION: 'popular-brands-section',
HOT_PICKS_SECTION: 'hot-picks-section',
TODAY_DEALS_SECTION: 'today-deals-section',
SEARCH_VERTICAL_PAGENATOR: 'search_verticalPagenator',
};
@@ -159,6 +193,8 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
const popularBrands = useSelector((state) => state.search.searchMainData.popularBrands);
// 0hun: 검색 메인, Top Searchs 영역에 대한 전역 상태 값
const topSearchs = useSelector((state) => state.search.searchMainData.topSearchs);
// jhun: 검색 메인, Today Deals 영역에 대한 전역 상태 값
const tsvInfo = useSelector((state) => state.search.searchMainData.tsvInfo);
/**
* states
@@ -1289,6 +1325,41 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
[hotPicksForYou, dispatch, SafeImage]
);
const handleClick = useCallback((patnrId, prdtId) => {
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId, prdtId },
})
);
},[dispatch])
const renderTsvItem = useCallback(
({ index, ...rest }) => {
const { offerInfo, prdtId, imgUrl, patnrId, prdtNm, priceInfo } =
tsvInfo[index];
return (
<TItemCardNew
imageAlt={prdtNm}
imageSource={imgUrl}
onClick={()=>{handleClick(patnrId,prdtId)}}
offerInfo={offerInfo}
priceInfo={priceInfo}
productId={prdtId}
productName={prdtNm}
spotlightId={
"searchMain-tsvInfo-spotlightId-" + removeDotAndColon(prdtId)
}
{...rest}
/>
);
},
[tsvInfo,handleClick]
);
/**
* ✨ [Phase 2] 모드별 콘텐츠 렌더링 (VoiceInputOverlay의 renderModeContent와 동일한 패턴)
* SearchPanel의 현재 모드에 따라 표시할 콘텐츠를 결정합니다.
@@ -1456,6 +1527,32 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
</SectionContainer>
</>
)}
{tsvInfo && tsvInfo.length > 0 && (
<>
<SectionContainer
className={css.todayDealSection}
data-wheel-point="true"
spotlightId={SPOTLIGHT_IDS.TODAY_DEALS_SECTION}
>
<div className={css.sectionHeader}>
<div className={css.sectionIndicator} />
<div className={css.sectionTitle}>Today's Deals</div>
</div>
<div className={css.itemList}>
<TVirtualGridList
dataSize={tsvInfo.length}
direction="horizontal"
renderItem={renderTsvItem}
itemWidth={324}
itemHeight={438}
spacing={18}
/>
</div>
</SectionContainer>
</>
)}
</ContainerBasic>
);
}