[search] 일반 검색 초기 스팟 처리#1
- theme,item,show 부분 체크하여 첫번째 스팟가도록 변경. - 상세 다녀와서의 스팟처리중.
This commit is contained in:
@@ -1,19 +1,37 @@
|
||||
// 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 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 {
|
||||
popPanel,
|
||||
pushPanel,
|
||||
updatePanel,
|
||||
} from '../../actions/panelActions';
|
||||
import {
|
||||
getSearch,
|
||||
getSearchMain,
|
||||
@@ -30,43 +48,65 @@ import {
|
||||
// } from '../../actions/toastActions';
|
||||
import TBody from '../../components/TBody/TBody';
|
||||
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 VirtualKeyboardContainer from "../../components/TToast/VirtualKeyboardContainer";
|
||||
import usePrevious from '../../hooks/usePrevious';
|
||||
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 './SearchInpuOverlay';
|
||||
import css from './SearchPanel.new.module.less';
|
||||
import SearchResultsNew from './SearchResults.new';
|
||||
import TInput, { ICONS, KINDS } from './TInput/TInput';
|
||||
import VoiceInputOverlay, { VOICE_MODES } from './VoiceInputOverlay/VoiceInputOverlay';
|
||||
import TInput, {
|
||||
ICONS,
|
||||
KINDS,
|
||||
} from './TInput/TInput';
|
||||
import VoiceInputOverlay, {
|
||||
VOICE_MODES,
|
||||
} from './VoiceInputOverlay/VoiceInputOverlay';
|
||||
|
||||
const ContainerBasic = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||
const ContainerBasic = SpotlightContainerDecorator(
|
||||
{ enterTo: "last-focused" },
|
||||
"div"
|
||||
);
|
||||
|
||||
// 검색 입력 영역 컨테이너
|
||||
const InputContainer = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||
const InputContainer = SpotlightContainerDecorator(
|
||||
{ enterTo: "last-focused" },
|
||||
"div"
|
||||
);
|
||||
|
||||
// 콘텐츠 섹션 컨테이너
|
||||
const SectionContainer = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||
const SectionContainer = SpotlightContainerDecorator(
|
||||
{ enterTo: "last-focused" },
|
||||
"div"
|
||||
);
|
||||
|
||||
// Spottable 컴포넌트들
|
||||
const SpottableMicButton = Spottable('div');
|
||||
const SpottableKeyword = Spottable('div');
|
||||
const SpottableProduct = Spottable('div');
|
||||
const SpottableMicButton = Spottable("div");
|
||||
const SpottableKeyword = Spottable("div");
|
||||
const SpottableProduct = Spottable("div");
|
||||
|
||||
const ITEMS_PER_PAGE = 9;
|
||||
|
||||
// Spotlight ID 상수
|
||||
const SPOTLIGHT_IDS = {
|
||||
SEARCH_INPUT_LAYER: 'search-input-layer',
|
||||
SEARCH_INPUT_BOX: 'search-input-box',
|
||||
MICROPHONE_BUTTON: 'microphone-button',
|
||||
RECENT_SEARCHES_SECTION: 'recent-searches-section',
|
||||
TOP_SEARCHES_SECTION: 'top-searches-section',
|
||||
POPULAR_BRANDS_SECTION: 'popular-brands-section',
|
||||
HOT_PICKS_SECTION: 'hot-picks-section',
|
||||
SEARCH_VERTICAL_PAGENATOR: 'search_verticalPagenator',
|
||||
SEARCH_INPUT_LAYER: "search-input-layer",
|
||||
SEARCH_INPUT_BOX: "search-input-box",
|
||||
MICROPHONE_BUTTON: "microphone-button",
|
||||
RECENT_SEARCHES_SECTION: "recent-searches-section",
|
||||
TOP_SEARCHES_SECTION: "top-searches-section",
|
||||
POPULAR_BRANDS_SECTION: "popular-brands-section",
|
||||
HOT_PICKS_SECTION: "hot-picks-section",
|
||||
SEARCH_VERTICAL_PAGENATOR: "search_verticalPagenator",
|
||||
};
|
||||
|
||||
export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
@@ -82,13 +122,21 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
// 0hun: 패널 전역 상태
|
||||
const panels = useSelector((state) => state.panels.panels);
|
||||
// 0hun: 음성 검색 결과에 대한 전역 상태
|
||||
const shopperHouseData = useSelector((state) => state.search.shopperHouseData);
|
||||
const shopperHouseData = useSelector(
|
||||
(state) => state.search.shopperHouseData
|
||||
);
|
||||
// 0hun: 검색 메인, Hot Picks for you 영역에 대한 전역 상태 값
|
||||
const hotPicksForYou = useSelector((state) => state.search.searchMainData.hotPicksForYou);
|
||||
const hotPicksForYou = useSelector(
|
||||
(state) => state.search.searchMainData.hotPicksForYou
|
||||
);
|
||||
// 0hun: 검색 메인, Popular Brands 영역에 대한 전역 상태 값
|
||||
const popularBrands = useSelector((state) => state.search.searchMainData.popularBrands);
|
||||
const popularBrands = useSelector(
|
||||
(state) => state.search.searchMainData.popularBrands
|
||||
);
|
||||
// 0hun: 검색 메인, Top Searchs 영역에 대한 전역 상태 값
|
||||
const topSearchs = useSelector((state) => state.search.searchMainData.topSearchs);
|
||||
const topSearchs = useSelector(
|
||||
(state) => state.search.searchMainData.topSearchs
|
||||
);
|
||||
|
||||
/**
|
||||
* states
|
||||
@@ -96,7 +144,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
// 0hun: 초기 포커스 유무를 나타내는 Boolean 상태
|
||||
const [firstSpot, setFirstSpot] = useState(false);
|
||||
// 0hun: 검색어 상태
|
||||
const [searchQuery, setSearchQuery] = useState(panelInfo.searchVal ? panelInfo.searchVal : null);
|
||||
const [searchQuery, setSearchQuery] = useState(
|
||||
panelInfo.searchVal ? panelInfo.searchVal : null
|
||||
);
|
||||
// 0hun: 검색 컨테이너 포커스 position 상태 값
|
||||
const [position, setPosition] = useState(null);
|
||||
// 0hun: 가상 키보드 Display 유무 Boolean 값
|
||||
@@ -110,7 +160,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
// TInput의 입력 모드 상태 (webOS 키보드가 뜨는지 여부)
|
||||
const [isInputModeActive, setIsInputModeActive] = useState(false);
|
||||
// 0hun: 현재 포커스된 container의 spotlightId를 관리하는 상태 값
|
||||
const [focusedContainerId, setFocusedContainerId] = useState(panelInfo?.focusedContainerId);
|
||||
const [focusedContainerId, setFocusedContainerId] = useState(
|
||||
panelInfo?.focusedContainerId
|
||||
);
|
||||
|
||||
/**
|
||||
* refs
|
||||
@@ -126,7 +178,10 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
* memoized variables
|
||||
*/
|
||||
// 가짜 데이터 - 실제로는 Redux store나 API에서 가져와야 함
|
||||
const recentSearches = useMemo(() => ['Puppy food', 'Dog toy', 'Fitness'], []);
|
||||
const recentSearches = useMemo(
|
||||
() => ["Puppy food", "Dog toy", "Fitness"],
|
||||
[]
|
||||
);
|
||||
|
||||
// Voice overlay suggestions (동적으로 변경 가능)
|
||||
const voiceSuggestions = useMemo(
|
||||
@@ -162,7 +217,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
}
|
||||
|
||||
// Enter 키 처리
|
||||
if (e.key === 'Enter') {
|
||||
if (e.key === "Enter") {
|
||||
// e.preventDefault();
|
||||
if (showVirtualKeyboard) {
|
||||
// 가상 키보드가 열려있으면 검색 실행하고 키보드 닫기
|
||||
@@ -176,26 +231,32 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
|
||||
// 방향키 처리 - Spotlight 네비게이션 허용
|
||||
const arrowKeys = [
|
||||
'ArrowLeft',
|
||||
'ArrowRight',
|
||||
'ArrowUp',
|
||||
'ArrowDown',
|
||||
'Left',
|
||||
'Right',
|
||||
'Up',
|
||||
'Down',
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"ArrowUp",
|
||||
"ArrowDown",
|
||||
"Left",
|
||||
"Right",
|
||||
"Up",
|
||||
"Down",
|
||||
];
|
||||
if (arrowKeys.includes(e.key)) {
|
||||
// 입력 필드가 비어있고 왼쪽 화살표인 경우에만 방지
|
||||
if (position === 0 && (e.key === 'Left' || e.key === 'ArrowLeft') && !searchQuery) {
|
||||
if (
|
||||
position === 0 &&
|
||||
(e.key === "Left" || e.key === "ArrowLeft") &&
|
||||
!searchQuery
|
||||
) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// 오른쪽 화살표 키 처리 - 포커스 이동 허용
|
||||
if (e.key === 'ArrowRight' || e.key === 'Right') {
|
||||
if (e.key === "ArrowRight" || e.key === "Right") {
|
||||
// 커서가 텍스트 끝에 있을 때만 포커스 이동 허용
|
||||
const input = document.querySelector(`[data-spotlight-id="input-field-box"] > input`);
|
||||
const input = document.querySelector(
|
||||
`[data-spotlight-id="input-field-box"] > input`
|
||||
);
|
||||
if (input && position === input.value.length) {
|
||||
// 커서가 텍스트 끝에 있으면 포커스 이동 허용
|
||||
return;
|
||||
@@ -214,8 +275,8 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
*/
|
||||
const handleInputModeChange = useCallback((isActive) => {
|
||||
console.log(
|
||||
'[SearchPanel] TInput 입력 모드:',
|
||||
isActive ? '활성화 (키보드 표시)' : '비활성화 (키보드 숨김)'
|
||||
"[SearchPanel] TInput 입력 모드:",
|
||||
isActive ? "활성화 (키보드 표시)" : "비활성화 (키보드 숨김)"
|
||||
);
|
||||
setIsInputModeActive(isActive);
|
||||
}, []);
|
||||
@@ -243,9 +304,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
if (query.trim()) {
|
||||
dispatch(
|
||||
getSearch({
|
||||
domain: 'theme,show,item',
|
||||
domain: "theme,show,item",
|
||||
query: query,
|
||||
service: 'com.lgshop.app',
|
||||
service: "com.lgshop.app",
|
||||
})
|
||||
);
|
||||
|
||||
@@ -268,7 +329,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
* 0hun: keyUp 이벤트 핸들러, keyUp 시 `position`의 상태값 변경하는 함수
|
||||
*/
|
||||
const cursorPosition = useCallback(() => {
|
||||
const input = document.querySelector(`[data-spotlight-id="input-field-box"] > input`);
|
||||
const input = document.querySelector(
|
||||
`[data-spotlight-id="input-field-box"] > input`
|
||||
);
|
||||
|
||||
if (input) {
|
||||
setPosition(input.selectionStart);
|
||||
@@ -284,7 +347,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
}
|
||||
|
||||
console.log(
|
||||
'🖱️ [DEBUG][SearchPanel] onClickMic called, current isVoiceOverlayVisible:',
|
||||
"🖱️ [DEBUG][SearchPanel] onClickMic called, current isVoiceOverlayVisible:",
|
||||
isVoiceOverlayVisible
|
||||
);
|
||||
setIsVoiceOverlayVisible(true);
|
||||
@@ -311,10 +374,10 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (searchQuery === null || searchQuery === '') {
|
||||
if (searchQuery === null || searchQuery === "") {
|
||||
dispatch(popPanel(panel_names.SEARCH_PANEL));
|
||||
} else {
|
||||
setSearchQuery('');
|
||||
setSearchQuery("");
|
||||
dispatch(resetSearch());
|
||||
Spotlight.focus(SPOTLIGHT_IDS.SEARCH_INPUT_BOX);
|
||||
}
|
||||
@@ -337,7 +400,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
Spotlight.resume();
|
||||
setFirstSpot(true);
|
||||
if (panelInfo.currentSpot) {
|
||||
if (panels[panels.length - 1]?.name === 'searchpanel') {
|
||||
if (panels[panels.length - 1]?.name === "searchpanel") {
|
||||
Spotlight.focus(panelInfo.currentSpot);
|
||||
}
|
||||
}
|
||||
@@ -390,7 +453,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
*/
|
||||
const handleVoiceOverlayClose = useCallback(() => {
|
||||
console.log(
|
||||
'🚪 [DEBUG][SearchPanel] handleVoiceOverlayClose called, setting isVoiceOverlayVisible to FALSE'
|
||||
"🚪 [DEBUG][SearchPanel] handleVoiceOverlayClose called, setting isVoiceOverlayVisible to FALSE"
|
||||
);
|
||||
|
||||
// ✨ Redux 정리는 VoiceInputOverlay.handleClose()에서 처리함
|
||||
@@ -429,7 +492,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
*/
|
||||
const handleMicKeyDown = useCallback(
|
||||
(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
if (e.key === "Enter") {
|
||||
onClickMic();
|
||||
}
|
||||
},
|
||||
@@ -471,17 +534,27 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
{...rest}
|
||||
>
|
||||
<div className={css.productImageWrapper}>
|
||||
<img src={bgImgPath} alt={curationNm} className={css.productImage} />
|
||||
<img
|
||||
src={bgImgPath}
|
||||
alt={curationNm}
|
||||
className={css.productImage}
|
||||
/>
|
||||
</div>
|
||||
<div className={css.productInfo}>
|
||||
{showBrandLogo && (
|
||||
<div className={css.productBrandWrapper}>
|
||||
<img src={patncLogoPath} alt={patncNm} className={css.brandLogo} />
|
||||
<img
|
||||
src={patncLogoPath}
|
||||
alt={patncNm}
|
||||
className={css.brandLogo}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={css.productDetails}>
|
||||
{showBrandName && <div className={css.brandName}>{patncNm}</div>}
|
||||
{showProductTitle && <div className={css.productTitle}>{curationNm}</div>}
|
||||
{showProductTitle && (
|
||||
<div className={css.productTitle}>{curationNm}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</SpottableProduct>
|
||||
@@ -618,7 +691,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
dispatch(
|
||||
sendLogTotalRecommend({
|
||||
query: searchQuery,
|
||||
searchType: searchPerformed ? 'query' : 'keyword',
|
||||
searchType: searchPerformed ? "query" : "keyword",
|
||||
result: result,
|
||||
contextName: LOG_CONTEXT_NAME.SEARCH,
|
||||
messageId: LOG_MESSAGE_ID.SEARCH_ITEM,
|
||||
@@ -672,7 +745,11 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<TPanel className={css.container} handleCancel={onCancel} spotlightId={spotlightId}>
|
||||
<TPanel
|
||||
className={css.container}
|
||||
handleCancel={onCancel}
|
||||
spotlightId={spotlightId}
|
||||
>
|
||||
<TBody
|
||||
className={css.tBody}
|
||||
scrollable
|
||||
@@ -696,8 +773,10 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
className={classNames(
|
||||
css.inputContainer,
|
||||
inputFocus === true && css.inputFocus,
|
||||
searchDatas && css.searchValue /* 이건 결과값 있을때만. 조건 추가필요 */,
|
||||
(isVoiceOverlayVisible || isSearchOverlayVisible) && css.hidden
|
||||
searchDatas &&
|
||||
css.searchValue /* 이건 결과값 있을때만. 조건 추가필요 */,
|
||||
(isVoiceOverlayVisible || isSearchOverlayVisible) &&
|
||||
css.hidden
|
||||
)}
|
||||
data-wheel-point="true"
|
||||
spotlightId={SPOTLIGHT_IDS.SEARCH_INPUT_LAYER}
|
||||
@@ -738,7 +817,11 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
spotlightId={SPOTLIGHT_IDS.MICROPHONE_BUTTON}
|
||||
>
|
||||
<div className={css.microphoneCircle}>
|
||||
<img src={micIcon} alt="Microphone" className={css.microphoneIcon} />
|
||||
<img
|
||||
src={micIcon}
|
||||
alt="Microphone"
|
||||
className={css.microphoneIcon}
|
||||
/>
|
||||
</div>
|
||||
</SpottableMicButton>
|
||||
|
||||
@@ -781,13 +864,21 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
{/* 결과갑 부분 작업중 끝! */}
|
||||
{/* 검색 결과 표시 영역 */}
|
||||
{(searchPerformed && searchQuery !== null) || shopperHouseData ? (
|
||||
<SearchResultsNew
|
||||
themeInfo={searchDatas.theme}
|
||||
itemInfo={searchDatas.item}
|
||||
showInfo={searchDatas.show}
|
||||
shopperHouseInfo={shopperHouseData}
|
||||
keywordClick={handleKeywordClick}
|
||||
/>
|
||||
searchDatas?.theme?.length > 0 ||
|
||||
searchDatas?.item?.length > 0 ||
|
||||
searchDatas?.show?.length > 0 ||
|
||||
shopperHouseData ? (
|
||||
<SearchResultsNew
|
||||
themeInfo={searchDatas.theme}
|
||||
itemInfo={searchDatas.item}
|
||||
showInfo={searchDatas.show}
|
||||
shopperHouseInfo={shopperHouseData}
|
||||
keywordClick={handleKeywordClick}
|
||||
panelInfo={panelInfo}
|
||||
/>
|
||||
) : (
|
||||
<NoSearchResults />
|
||||
)
|
||||
) : (
|
||||
<ContainerBasic className={css.contentContainer}>
|
||||
{/* 노출 조건 변경 필요. 포커스 블러만으로는 안됌.(가상 키보드 노출시가 맞을듯) */}
|
||||
@@ -804,7 +895,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
>
|
||||
<div className={css.sectionHeader}>
|
||||
<div className={css.sectionIndicator} />
|
||||
<div className={css.sectionTitle}>Your Recent Searches</div>
|
||||
<div className={css.sectionTitle}>
|
||||
Your Recent Searches
|
||||
</div>
|
||||
</div>
|
||||
<div className={css.keywordList}>
|
||||
{recentSearches.map((keyword, index) => (
|
||||
@@ -885,7 +978,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
>
|
||||
<div className={css.sectionHeader}>
|
||||
<div className={css.sectionIndicator} />
|
||||
<div className={css.sectionTitle}>Hot Picks for You</div>
|
||||
<div className={css.sectionTitle}>
|
||||
Hot Picks for You
|
||||
</div>
|
||||
</div>
|
||||
<div className={css.productList}>
|
||||
{hotPicksForYou && hotPicksForYou.length > 0 && (
|
||||
|
||||
@@ -8,6 +8,7 @@ import React, {
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Spotlight from '@enact/spotlight';
|
||||
import Spottable from '@enact/spotlight/Spottable';
|
||||
|
||||
import downBtnImg from '../../../assets/images/btn/search_btn_down_arrow.png';
|
||||
@@ -26,6 +27,7 @@ import ShowCard from './SearchResultsNew/ShowCard';
|
||||
const ITEMS_PER_PAGE = 10;
|
||||
|
||||
const SearchResultsNew = ({
|
||||
panelInfo,
|
||||
itemInfo,
|
||||
showInfo,
|
||||
themeInfo,
|
||||
@@ -215,8 +217,20 @@ const SearchResultsNew = ({
|
||||
}, [shopperHouseInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("###shopperHouseInfo", shopperHouseInfo);
|
||||
}, [shopperHouseInfo]);
|
||||
const targetId =
|
||||
themeInfo?.length > 0
|
||||
? "searchProduct-0"
|
||||
: itemInfo?.length > 0
|
||||
? "searchItemContents0"
|
||||
: showInfo?.length > 0
|
||||
? "categoryShowContents0"
|
||||
: null;
|
||||
|
||||
if (!targetId) return;
|
||||
|
||||
const spotTimeout = setTimeout(() => Spotlight.focus(targetId), 100);
|
||||
return () => clearTimeout(spotTimeout);
|
||||
}, [themeInfo?.length, itemInfo?.length, showInfo?.length]);
|
||||
|
||||
return (
|
||||
<div className={css.searchBox}>
|
||||
@@ -285,8 +299,12 @@ const SearchResultsNew = ({
|
||||
</TDropDown>
|
||||
)}
|
||||
</div>
|
||||
{tab === 0 && <ItemCard itemInfo={displayedData} />}
|
||||
{tab === 1 && <ShowCard showInfo={displayedData} />}
|
||||
{tab === 0 && (
|
||||
<ItemCard itemInfo={displayedData} panelInfo={panelInfo} />
|
||||
)}
|
||||
{tab === 1 && (
|
||||
<ShowCard showInfo={displayedData} panelInfo={panelInfo} />
|
||||
)}
|
||||
</div>
|
||||
<div className={css.buttonContainer}>
|
||||
{hasMore && (
|
||||
|
||||
@@ -1,22 +1,41 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useRef,
|
||||
} from 'react';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { pushPanel } from '../../../actions/panelActions';
|
||||
import Spotlight from '@enact/spotlight';
|
||||
|
||||
import {
|
||||
pushPanel,
|
||||
updatePanel,
|
||||
} from '../../../actions/panelActions';
|
||||
import TItemCardNew from '../../../components/TItemCard/TItemCard.new';
|
||||
import TScroller from '../../../components/TScroller/TScroller';
|
||||
import { panel_names } from '../../../utils/Config';
|
||||
import { SpotlightIds } from '../../../utils/SpotlightIds';
|
||||
import css from './ItemCard.module.less';
|
||||
|
||||
const ItemCard = ({ onClick, itemInfo }) => {
|
||||
const ItemCard = ({ panelInfo, onClick, itemInfo }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId);
|
||||
const _handleItemClick = useCallback(
|
||||
(patnrId, prdtId) => (ev) => {
|
||||
if (onClick) {
|
||||
onClick(ev);
|
||||
}
|
||||
const currentSpot =
|
||||
Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null;
|
||||
dispatch(
|
||||
updatePanel({
|
||||
name: panel_names.SEARCH_PANEL,
|
||||
panelInfo: {
|
||||
currentSpot,
|
||||
focusedContainerId: focusedContainerIdRef.current,
|
||||
},
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
pushPanel({
|
||||
name: panel_names.DETAIL_PANEL,
|
||||
@@ -32,12 +51,15 @@ const ItemCard = ({ onClick, itemInfo }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<TScroller className={css.container} spotlightId={SpotlightIds.SEARCH_ITEM}>
|
||||
<TScroller
|
||||
className={css.container}
|
||||
spotlightId={SpotlightIds.SEARCH_ITEM}
|
||||
>
|
||||
{itemInfo.map((item, index) => {
|
||||
const { thumbnail, title, dcPrice, price, soldout, contentId } = item;
|
||||
const tokens = contentId && contentId.split('_');
|
||||
const patnrId = tokens?.[4] || '';
|
||||
const prdtId = tokens?.[5] || '';
|
||||
const tokens = contentId && contentId.split("_");
|
||||
const patnrId = tokens?.[4] || "";
|
||||
const prdtId = tokens?.[5] || "";
|
||||
return (
|
||||
<TItemCardNew
|
||||
key={prdtId}
|
||||
@@ -49,8 +71,8 @@ const ItemCard = ({ onClick, itemInfo }) => {
|
||||
soldoutFlag={soldout}
|
||||
dcPrice={dcPrice}
|
||||
originPrice={price}
|
||||
spotlightId={'searchItemContents' + index}
|
||||
label={index * 1 + 1 + ' of ' + itemInfo.length + 1}
|
||||
spotlightId={"searchItemContents" + index}
|
||||
label={index * 1 + 1 + " of " + itemInfo.length + 1}
|
||||
lastLabel=" go to detail, button"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,25 +2,28 @@ import React, { useCallback } from 'react';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
||||
import SpotlightContainerDecorator
|
||||
from '@enact/spotlight/SpotlightContainerDecorator';
|
||||
|
||||
import { pushPanel } from '../../../actions/panelActions';
|
||||
import TItemCardNew, { TYPES } from '../../../components/TItemCard/TItemCard.new';
|
||||
import TItemCardNew, {
|
||||
TYPES,
|
||||
} from '../../../components/TItemCard/TItemCard.new';
|
||||
import { panel_names } from '../../../utils/Config';
|
||||
import { SpotlightIds } from '../../../utils/SpotlightIds';
|
||||
import css from './ShowCard.module.less';
|
||||
|
||||
const Container = SpotlightContainerDecorator({ enterTo: null }, 'div');
|
||||
const ShowCard = ({ onClick, showInfo }) => {
|
||||
const Container = SpotlightContainerDecorator({ enterTo: null }, "div");
|
||||
const ShowCard = ({ panelInfo, onClick, showInfo }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleClick = useCallback(
|
||||
(contentId, thumbnail, liveFlag) => () => {
|
||||
const tokens = contentId && contentId.split('_');
|
||||
const tokens = contentId && contentId.split("_");
|
||||
|
||||
const linkTpCd = tokens[1] || '';
|
||||
const patnrId = tokens[4] || '';
|
||||
const showId = tokens[5] || '';
|
||||
const linkTpCd = tokens[1] || "";
|
||||
const patnrId = tokens[4] || "";
|
||||
const showId = tokens[5] || "";
|
||||
|
||||
if (onClick) {
|
||||
onClick();
|
||||
@@ -35,7 +38,7 @@ const ShowCard = ({ onClick, showInfo }) => {
|
||||
chanId: showId,
|
||||
linkTpCd,
|
||||
thumbnail,
|
||||
shptmBanrTpNm: liveFlag === 'Y' ? 'LIVE' : 'VOD',
|
||||
shptmBanrTpNm: liveFlag === "Y" ? "LIVE" : "VOD",
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -47,8 +50,8 @@ const ShowCard = ({ onClick, showInfo }) => {
|
||||
<Container className={css.container} spotlightId={SpotlightIds.SEARCH_SHOW}>
|
||||
{showInfo.map((item, index) => {
|
||||
const { contentId, liveFlag, partnerLogo, thumbnail, title } = item;
|
||||
const tokkens = contentId && contentId.split('_');
|
||||
const showId = tokkens[5] || '';
|
||||
const tokkens = contentId && contentId.split("_");
|
||||
const showId = tokkens[5] || "";
|
||||
return (
|
||||
<TItemCardNew
|
||||
type={TYPES.videoShow}
|
||||
@@ -59,7 +62,7 @@ const ShowCard = ({ onClick, showInfo }) => {
|
||||
logo={partnerLogo}
|
||||
onClick={handleClick(contentId, thumbnail, liveFlag)}
|
||||
productId={showId}
|
||||
spotlightId={'categoryShowContents' + index}
|
||||
spotlightId={"categoryShowContents" + index}
|
||||
data-wheel-point="true"
|
||||
logoDisplay="true"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user