[No Jira Issue] IF-LGSP-LOG-005 (GNB 이력) Magic Mouse 대응 (TrendingNowPanel 1차)

1. deepLinkHandler.js
2. SpotlightIds.js
3. BestSeller.jsx
4. PopularShow.jsx
5. TrendingNowPanel.jsx
6. PopularShowIndicator.jsx
7. PopularProductList.jsx
8. PopularVideoCard.jsx
This commit is contained in:
younghoon100.park
2024-11-13 18:02:50 +09:00
parent f9cf2b3f30
commit 18f4e2dafc
8 changed files with 270 additions and 321 deletions

View File

@@ -184,6 +184,9 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
// "PS": Popular Shows // "PS": Popular Shows
// V3_진입경로코드_진입경로명_PS_노출순번 // V3_진입경로코드_진입경로명_PS_노출순번
panelName = panel_names.TRENDING_NOW_PANEL; panelName = panel_names.TRENDING_NOW_PANEL;
panelInfo = {
pageName: "PS",
};
break; break;
case "SC": case "SC":

View File

@@ -13,6 +13,16 @@ export const SpotlightIds = {
BRAND_QUICK_MENU: "brandQuickMenu", BRAND_QUICK_MENU: "brandQuickMenu",
BRAND_TOP_BUTTON: "brandTopButton", BRAND_TOP_BUTTON: "brandTopButton",
// TrendingNowPanel
TRENDING_NOW_VERTICAL_PAGINATOR: "trendingNowVerticalPaginator",
TRENDING_NOW_POPULAR_SHOW: "trendingNowPopularShow",
TRENDING_NOW_POPULAR_VIDEO: "trendingNowPopularVideo",
TRENDING_NOW_POPULAR_GRID_LIST: "trendingNowVirtualGridList",
TRENDING_NOW_PREV_INDICATOR: "trendingNowPrevIndicator",
TRENDING_NOW_NEXT_INDICATOR: "trendingNowNextIndicator",
TRENDING_NOW_BEST_SELLER: "trendingNowBestSeller",
TRENDING_NOW_TOP_BUTTON: "trendingNowTopButton",
// myPagePanel // myPagePanel
MY_PAGE_FAVORITES_BOX: "myPageFavoritesBox", MY_PAGE_FAVORITES_BOX: "myPageFavoritesBox",
MY_PAGE_REMINDRES_BOX: "myPageRemindresBox", MY_PAGE_REMINDRES_BOX: "myPageRemindresBox",

View File

@@ -14,6 +14,7 @@ import useScrollReset from "../../../hooks/useScrollReset";
import useScrollTo from "../../../hooks/useScrollTo"; import useScrollTo from "../../../hooks/useScrollTo";
import { panel_names } from "../../../utils/Config"; import { panel_names } from "../../../utils/Config";
import { $L, scaleW } from "../../../utils/helperMethods"; import { $L, scaleW } from "../../../utils/helperMethods";
import { SpotlightIds } from "../../../utils/SpotlightIds";
import css from "./BestSeller.module.less"; import css from "./BestSeller.module.less";
const SpottableComponent = Spottable("div"); const SpottableComponent = Spottable("div");
@@ -64,7 +65,7 @@ const BestSeller = ({ order, scrollTopBody, spotlightId, handleItemFocus }) => {
name: panel_names.TRENDING_NOW_PANEL, name: panel_names.TRENDING_NOW_PANEL,
panelInfo: { panelInfo: {
pageName: "BS", pageName: "BS",
focusedContainerId: "trandingnow_bestseller", focusedContainerId: SpotlightIds.TRENDING_NOW_BEST_SELLER,
}, },
}) })
); );

View File

@@ -18,6 +18,7 @@ import useScrollReset from "../../../hooks/useScrollReset";
import useScrollTo from "../../../hooks/useScrollTo"; import useScrollTo from "../../../hooks/useScrollTo";
import { panel_names } from "../../../utils/Config"; import { panel_names } from "../../../utils/Config";
import { $L, scaleW } from "../../../utils/helperMethods"; import { $L, scaleW } from "../../../utils/helperMethods";
import { SpotlightIds } from "../../../utils/SpotlightIds";
import css from "../PopularShow/PopularShow.module.less"; import css from "../PopularShow/PopularShow.module.less";
const SpottableComponent = Spottable("div"); const SpottableComponent = Spottable("div");
@@ -79,7 +80,7 @@ const PopularShow = ({
name: panel_names.TRENDING_NOW_PANEL, name: panel_names.TRENDING_NOW_PANEL,
panelInfo: { panelInfo: {
pageName: "PS", pageName: "PS",
focusedContainerId: "trandingnow_popularcontainer", focusedContainerId: SpotlightIds.TRENDING_NOW_POPULAR_SHOW,
}, },
}, },
[dispatch] [dispatch]

View File

@@ -1,28 +1,27 @@
import React, { useCallback, useState } from "react"; import React, { memo, useCallback } from "react";
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import { LOG_MENU } from "../../../utils/Config"; import { LOG_MENU } from "../../../utils/Config";
import { SpotlightIds } from "../../../utils/SpotlightIds";
import css from "./PopularShowIndicator.module.less"; import css from "./PopularShowIndicator.module.less";
import PopularProductList from "./PopularShowVerticalContents/PopularProductList"; import PopularProductList from "./PopularShowVerticalContents/PopularProductList";
import PopularVideoCard from "./PopularVideoCard/PopularVideoCard"; import PopularVideoCard from "./PopularVideoCard/PopularVideoCard";
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(
{ { enterTo: "last-focused" },
enterTo: "last-focused",
},
"div" "div"
); );
export default function PopularShowIndicator({ const PopularShowIndicator = ({
onSpotlightDown,
topInfos, topInfos,
selectedIndex, selectedIndex,
onSpotlightDown,
onSpotlightRight,
handleItemFocus, handleItemFocus,
handleItemClick, handleItemClick,
isOnTop, isOnTop,
}) { }) => {
const { const {
thumbnailUrl960, thumbnailUrl960,
showNm, showNm,
@@ -41,10 +40,6 @@ export default function PopularShowIndicator({
const isVertical = Boolean(vtctpYn === "Y"); const isVertical = Boolean(vtctpYn === "Y");
const onSpotlightRight = () => {
Spotlight.focus("popular-next-arrow");
};
const _handleItemFocus = useCallback(() => { const _handleItemFocus = useCallback(() => {
if (handleItemFocus) { if (handleItemFocus) {
handleItemFocus(LOG_MENU.TRENDING_NOW_POPULAR_SHOWS); handleItemFocus(LOG_MENU.TRENDING_NOW_POPULAR_SHOWS);
@@ -59,46 +54,46 @@ export default function PopularShowIndicator({
return ( return (
<div className={css.popularContainer}> <div className={css.popularContainer}>
{topInfos && topInfos.length > 0 && ( <div className={css.popularContents}>
<div className={css.popularContents}> <Container>
<Container> <PopularVideoCard
<PopularVideoCard thumbnailImgPath={thumbnailUrl960}
thumbnailImgPath={thumbnailUrl960} showNm={showNm}
showNm={showNm} disclaimer={disclaimer}
disclaimer={disclaimer} expsOrd={expsOrd}
expsOrd={expsOrd} orderPhnNo={orderPhnNo}
orderPhnNo={orderPhnNo} thumbnailType={isVertical ? "vertical" : "horizontal"}
thumbnailType={isVertical ? "vertical" : "horizontal"} isVertical={isVertical}
isVertical={isVertical} popularShowInfos={topInfos[selectedIndex]}
popularShowInfos={topInfos[selectedIndex]} showUrl={showUrl}
showUrl={showUrl} spotlightId={SpotlightIds.TRENDING_NOW_POPULAR_VIDEO}
spotlightId="popular_video" onSpotlightDown={onSpotlightDown}
onSpotlightDown={onSpotlightDown} showId={showId}
showId={showId} patnrId={patnrId}
patnrId={patnrId} lgCatCd={catCd}
lgCatCd={catCd} handleItemClick={_handleItemClick}
handleItemClick={_handleItemClick} handleItemFocus={_handleItemFocus}
handleItemFocus={_handleItemFocus} patncNm={patncNm}
patncNm={patncNm} isOnTop={isOnTop}
isOnTop={isOnTop} />
/> </Container>
</Container> <Container className={css.popularProductListContainer}>
<Container className={css.popularProductListContainer}> <PopularProductList
<PopularProductList brandProductInfo={productInfos}
brandProductInfo={productInfos} topInfosData={topInfos[selectedIndex]}
topInfosData={topInfos[selectedIndex]} patnrId={patnrId}
patnrId={patnrId} lgCatCd={catCd}
lgCatCd={catCd} selectedPatnrId={selectedPatnrId}
selectedPatnrId={selectedPatnrId} onSpotlightRight={onSpotlightRight}
onSpotlightRight={onSpotlightRight} onSpotlightDown={onSpotlightDown}
onSpotlightDown={onSpotlightDown} selectedIndex={selectedIndex}
selectedIndex={selectedIndex} handleItemFocus={_handleItemFocus}
handleItemFocus={_handleItemFocus} handleItemClick={_handleItemClick}
handleItemClick={_handleItemClick} />
/> </Container>
</Container> </div>
</div>
)}
</div> </div>
); );
} };
export default memo(PopularShowIndicator);

View File

@@ -12,6 +12,7 @@ import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGr
import useScrollTo from "../../../../hooks/useScrollTo"; import useScrollTo from "../../../../hooks/useScrollTo";
import { panel_names } from "../../../../utils/Config"; import { panel_names } from "../../../../utils/Config";
import { scaleH } from "../../../../utils/helperMethods"; import { scaleH } from "../../../../utils/helperMethods";
import { SpotlightIds } from "../../../../utils/SpotlightIds";
import css from "./PopularProductList.module.less"; import css from "./PopularProductList.module.less";
export default function PopularProductList({ export default function PopularProductList({
@@ -131,7 +132,7 @@ export default function PopularProductList({
spacing={12} spacing={12}
renderItem={renderItem} renderItem={renderItem}
noScrollByWheel={false} noScrollByWheel={false}
spotlightId="popular-productList" spotlightId={SpotlightIds.TRENDING_NOW_POPULAR_GRID_LIST}
/> />
)} )}
</div> </div>

View File

@@ -11,9 +11,11 @@ import { Marquee } from "@enact/ui/Marquee";
import ic_crown from "../../../../../assets/images/icons/ic-crown-badge@3x.png"; import ic_crown from "../../../../../assets/images/icons/ic-crown-badge@3x.png";
import ic_warning from "../../../../../assets/images/icons/ic-warning@3x.png"; import ic_warning from "../../../../../assets/images/icons/ic-warning@3x.png";
import ic_call from "../../../../../assets/images/icons/ic-wh-call@3x.png"; import ic_call from "../../../../../assets/images/icons/ic-wh-call@3x.png";
import { finishVideoPreview, startVideoPlayer } from "../../../../actions/playActions"; import {
finishVideoPreview,
startVideoPlayer,
} from "../../../../actions/playActions";
import CustomImage from "../../../../components/CustomImage/CustomImage"; import CustomImage from "../../../../components/CustomImage/CustomImage";
import { $L } from "../../../../utils/helperMethods";
import css from "./PopularVideoCard.module.less"; import css from "./PopularVideoCard.module.less";
const SpottableComponent = Spottable("div"); const SpottableComponent = Spottable("div");
@@ -52,7 +54,9 @@ export default function PopularVideoCard({
const videoFocusTimeoutJob = useRef(new Job((func) => func(), 1000)); const videoFocusTimeoutJob = useRef(new Job((func) => func(), 1000));
const isFullScreenModeActivedRef = useRef(false); const isFullScreenModeActivedRef = useRef(false);
const cursorVisible = useSelector((state) => state.common.appStatus.cursorVisible); const cursorVisible = useSelector(
(state) => state.common.appStatus.cursorVisible
);
useEffect(() => { useEffect(() => {
if (isFullScreenModeActivedRef.current && isOnTop) { if (isFullScreenModeActivedRef.current && isOnTop) {
@@ -91,7 +95,6 @@ export default function PopularVideoCard({
} }
}, [isFocused, dispatch, showId]); }, [isFocused, dispatch, showId]);
// 포커스 인
const onFocus = useCallback(() => { const onFocus = useCallback(() => {
setIsFocused(true); setIsFocused(true);
if (handleItemFocus) { if (handleItemFocus) {
@@ -99,12 +102,10 @@ export default function PopularVideoCard({
} }
}, [handleItemFocus]); }, [handleItemFocus]);
// 포커스 아웃
const onBlur = useCallback(() => { const onBlur = useCallback(() => {
setIsFocused(false); setIsFocused(false);
}, []); }, []);
// 비디오 클릭
const onClick = useCallback(() => { const onClick = useCallback(() => {
setIsFocused(false); setIsFocused(false);
@@ -148,7 +149,14 @@ export default function PopularVideoCard({
aria-label={"SHOW " + showNm} aria-label={"SHOW " + showNm}
> >
<figure className={css[thumbnailType]}> <figure className={css[thumbnailType]}>
{thumbnailImgPath && <CustomImage delay={0} src={thumbnailImgPath} animationSpeed="fast" alt={showNm} />} {thumbnailImgPath && (
<CustomImage
delay={0}
src={thumbnailImgPath}
animationSpeed="fast"
alt={showNm}
/>
)}
</figure> </figure>
<div className={classNames(css.videoDesc, isFocused && css.descFocused)}> <div className={classNames(css.videoDesc, isFocused && css.descFocused)}>
<div> <div>

View File

@@ -1,34 +1,28 @@
import React, { useCallback, useEffect, useMemo, useRef } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import { import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
notifyEnterContainer,
setContainerLastFocusedElement,
} from "@enact/spotlight/src/container";
import { sendLogGNB } from "../../actions/logActions"; import { sendLogGNB } from "../../actions/logActions";
import { getTop20Show } from "../../actions/mainActions"; import { getTop20Show } from "../../actions/mainActions";
import { popPanel, pushPanel, updatePanel } from "../../actions/panelActions"; import { pushPanel, updatePanel } from "../../actions/panelActions";
import { finishVideoPreview } from "../../actions/playActions"; import { finishVideoPreview } from "../../actions/playActions";
import { getBestSeller } from "../../actions/productActions"; import { getBestSeller } from "../../actions/productActions";
import SectionTitle from "../../components/SectionTitle/SectionTitle"; import SectionTitle from "../../components/SectionTitle/SectionTitle";
import TBody from "../../components/TBody/TBody"; import TBody from "../../components/TBody/TBody";
import TButton, { TYPES } from "../../components/TButton/TButton"; import TButton, { TYPES } from "../../components/TButton/TButton";
import TItemCard, { import TItemCard from "../../components/TItemCard/TItemCard";
removeDotAndColon,
} from "../../components/TItemCard/TItemCard";
import TPanel from "../../components/TPanel/TPanel"; import TPanel from "../../components/TPanel/TPanel";
import TVerticalPagenator from "../../components/TVerticalPagenator/TVerticalPagenator"; import TVerticalPagenator from "../../components/TVerticalPagenator/TVerticalPagenator";
import usePrevious from "../../hooks/usePrevious"; import usePrevious from "../../hooks/usePrevious";
import useScrollReset from "../../hooks/useScrollReset";
import useScrollTo from "../../hooks/useScrollTo";
import useWhyDidYouUpdate from "../../hooks/useWhyDidYouUpdate"; import useWhyDidYouUpdate from "../../hooks/useWhyDidYouUpdate";
import { LOG_MENU, panel_names } from "../../utils/Config"; import { LOG_MENU, panel_names } from "../../utils/Config";
import { $L, scaleH } from "../../utils/helperMethods"; import { $L } from "../../utils/helperMethods";
import { SpotlightIds } from "../../utils/SpotlightIds";
import PopularShowIndicator from "./PopularShow/PopularShowIndicator"; import PopularShowIndicator from "./PopularShow/PopularShowIndicator";
import css from "./TrendingNowPanel.module.less"; import css from "./TrendingNowPanel.module.less";
@@ -44,6 +38,7 @@ const STRING_CONF = {
POPULAR_SHOW: "POPULAR SHOW", POPULAR_SHOW: "POPULAR SHOW",
BEST_SELLER: "BEST SELLER", BEST_SELLER: "BEST SELLER",
}; };
const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => { const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { USE_SELECTOR, USE_STATE } = useWhyDidYouUpdate(spotlightId, { const { USE_SELECTOR, USE_STATE } = useWhyDidYouUpdate(spotlightId, {
@@ -51,249 +46,192 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
isOnTop, isOnTop,
...rest, ...rest,
}); });
const topInfos = USE_SELECTOR( const topInfos = USE_SELECTOR(
"topInfos", "topInfos",
(state) => state.main.top20ShowData?.topInfos (state) => state.main.top20ShowData?.topInfos
); );
const bestSellerDatas = USE_SELECTOR( const bestSeller = USE_SELECTOR(
"bestSellerDatas", "bestSeller",
(state) => state.product?.bestSellerData?.bestSeller (state) => state.product?.bestSellerData?.bestSeller
); );
const {
getScrollTo: getScrollToBody,
scrollTop: scrollTopBody,
scrollLeft,
} = useScrollTo();
const { handleScrollReset, handleStopScrolling } = useScrollReset(
scrollLeft,
true
);
const [targetId, setTargetId] = USE_STATE("targetId", null);
const [firstChk, setFirstChk] = USE_STATE("firstChk", false);
const [showButton, setShowButton] = USE_STATE("showButton", true); const [showButton, setShowButton] = USE_STATE("showButton", true);
const timerRef = useRef();
const { cursorVisible } = USE_SELECTOR(
"cursorVisible",
(state) => state.common.appStatus
);
const [selectedIndex, setSelectedIndex] = USE_STATE("selectedIndex", 0); const [selectedIndex, setSelectedIndex] = USE_STATE("selectedIndex", 0);
const cbChangePageRef = useRef(null); const cbChangePageRef = useRef(null);
const isInitialRef = useRef(true);
const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId); const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId);
const handleCardClick = useCallback(
(item) => {
const c = Spotlight.getCurrent();
let targetSpotlightId = null;
if (c) {
targetSpotlightId = c.getAttribute("data-spotlight-id");
}
dispatch(
updatePanel({
name: panel_names.TRENDING_NOW_PANEL,
panelInfo: {
currentSpot: targetSpotlightId,
focusedContainerId: focusedContainerIdRef.current,
selectedIndex,
},
})
);
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId: item.patnrId, prdtId: item.prdtId },
})
);
},
[dispatch, selectedIndex]
);
useEffect(() => { useEffect(() => {
if (!topInfos && !bestSellerDatas) { if (!topInfos) dispatch(getTop20Show());
dispatch(getTop20Show()); if (!bestSeller) dispatch(getBestSeller());
dispatch(getBestSeller());
}
}, [dispatch]); }, [dispatch]);
const handlePrevClick = useCallback(() => { useEffect(() => {
if (topInfos) { if (isInitialRef.current && !panelInfo?.currentSpot) {
if (selectedIndex > 0) { if (topInfos && bestSeller) {
setSelectedIndex((prev) => prev - 1); const target =
setContainerLastFocusedElement(null, ["popular-productList"]); panelInfo?.pageName === "BS"
if (selectedIndex === 1) { ? SpotlightIds.TRENDING_NOW_BEST_SELLER
Spotlight.focus("popular_video"); : SpotlightIds.TRENDING_NOW_POPULAR_SHOW;
}
Spotlight.focus(target);
isInitialRef.current = false;
} }
} }
}, [selectedIndex, topInfos]); }, [topInfos, bestSeller]);
const handleNextClick = useCallback(() => { useEffect(() => {
if (topInfos) { if (panelInfo?.currentSpot) Spotlight.focus(panelInfo.currentSpot);
if (selectedIndex < topInfos.length - 1) { }, [panelInfo?.currentSpot]);
setSelectedIndex((prev) => prev + 1);
setContainerLastFocusedElement(null, ["popular-productList"]); useEffect(() => {
if (selectedIndex === topInfos.length - 2) { if (panelInfo?.selectedIndex) setSelectedIndex(panelInfo.selectedIndex);
Spotlight.focus("popular_video"); }, [panelInfo?.selectedIndex]);
}
} useEffect(() => {
if (isOnTop && panelInfo?.focusedContainerId) {
const menu =
panelInfo?.focusedContainerId === SpotlightIds.TRENDING_NOW_POPULAR_SHOW
? LOG_MENU.TRENDING_NOW_POPULAR_SHOWS
: LOG_MENU.TRENDING_NOW_BEST_SELLER;
dispatch(sendLogGNB(menu));
} }
}, [selectedIndex, topInfos]); }, [isOnTop && panelInfo?.focusedContainerId]);
const indicatorLeftonSpotlight = useCallback( const onFocusedContainerId = useCallback((containerId) => {
(e) => { focusedContainerIdRef.current = containerId;
}, []);
const handleScroll = useCallback((e) => {
setShowButton(e.scrollTop === 0);
if (e.scrollTop !== 0) dispatch(finishVideoPreview());
}, []);
const handleSpotlight = useCallback(
(spotlightId) => (e) => {
e.stopPropagation(); e.stopPropagation();
Spotlight.focus("popular_video"); if (spotlightId) Spotlight.focus(spotlightId);
}, },
[]
);
const handleIndicatorClick = useCallback(
(direction) => () => {
if (!topInfos) return;
const isPrev = direction === "prev";
const isNext = direction === "next";
const isEdgeIndex =
(isPrev && selectedIndex === 1) ||
(isNext && selectedIndex === topInfos.length - 2);
if (isEdgeIndex) Spotlight.focus(SpotlightIds.TRENDING_NOW_POPULAR_VIDEO);
setSelectedIndex((prev) => prev + (isPrev ? -1 : isNext ? 1 : 0));
setContainerLastFocusedElement(null, [
SpotlightIds.TRENDING_NOW_POPULAR_GRID_LIST,
]);
},
[selectedIndex, topInfos]
);
const handleBestSellerClick = useCallback(
({ patnrId, prdtId }) =>
() => {
const currentSpot =
Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null;
dispatch(
updatePanel({
name: panel_names.TRENDING_NOW_PANEL,
panelInfo: {
currentSpot,
focusedContainerId: focusedContainerIdRef.current,
selectedIndex,
},
})
);
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId, prdtId },
})
);
},
[selectedIndex] [selectedIndex]
); );
const _onScroll = (e) => { const handleBestSellerFocus = useCallback(() => {
if (e.scrollTop !== 0) { handleItemFocus(LOG_MENU.TRENDING_NOW_BEST_SELLER);
dispatch(finishVideoPreview()); }, [handleItemFocus]);
setShowButton(false);
} else {
setShowButton(true);
}
};
useEffect(() => { const handleItemClick = useCallback(() => {
if (panelInfo.currentSpot) { const currentSpot =
setTargetId(panelInfo.currentSpot); Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null;
}
}, [panelInfo]);
useEffect(() => { dispatch(
if (isOnTop) { updatePanel({
timerRef.current = setTimeout(() => { name: panel_names.TRENDING_NOW_PANEL,
Spotlight.focus(targetId); panelInfo: {
}, 0); currentSpot,
} focusedContainerId: focusedContainerIdRef.current,
return () => clearTimeout(timerRef.current); selectedIndex,
}, [targetId]); },
})
);
}, [selectedIndex]);
const handleItemFocus = useCallback((nowMenu) => {
setTimeout(() => dispatch(sendLogGNB(nowMenu)));
}, []);
const handleTopButtonClick = useCallback(() => { const handleTopButtonClick = useCallback(() => {
if (cbChangePageRef.current) { if (cbChangePageRef.current) {
cbChangePageRef.current(0, true); cbChangePageRef.current(0, true);
} }
if (topInfos && topInfos.length > 0) { let target = SpotlightIds.TRENDING_NOW_POPULAR_VIDEO;
Spotlight.focus("popular_video");
} else { if (!topInfos && bestSeller && bestSeller.length > 0) {
if (bestSellerDatas && bestSellerDatas.length > 0) { target = SpotlightIds.TRENDING_NOW_BEST_SELLER;
Spotlight.focus(
"bs-spotlightId-" + removeDotAndColon(bestSellerDatas[0]?.prdtId)
);
} else return;
} }
setContainerLastFocusedElement(null, ["trandingnow_bestseller"]); Spotlight.focus(target);
}, [targetId, bestSellerDatas, topInfos]); setContainerLastFocusedElement(null, [
SpotlightIds.TRENDING_NOW_BEST_SELLER,
]);
}, [bestSeller, topInfos]);
useEffect(() => { const getFirstLabel = useCallback((rankOrder) => {
if (panelInfo.currentSpot) { switch (rankOrder) {
Spotlight.focus(panelInfo.currentSpot); case 1:
} return `${rankOrder}st,`;
}, [panelInfo?.currentSpot]); case 2:
return `${rankOrder}nd,`;
useEffect(() => { case 3:
if (topInfos && bestSellerDatas) { return `${rankOrder}rd,`;
if (panelInfo?.pageName === "BS") { default:
if (panelInfo?.linkTpCd) { return `${rankOrder}th,`;
Spotlight.focus("trandingnow_bestseller");
} else {
Spotlight.focus(panelInfo?.focusedContainerId);
}
} else {
if (!firstChk && !panelInfo.currentSpot) {
Spotlight.focus("popular_video");
setFirstChk(true);
}
}
}
}, [
firstChk,
topInfos,
bestSellerDatas,
panelInfo?.focusedContainerId,
panelInfo.currentSpot,
panelInfo?.pageName,
panelInfo?.linkTpCd,
]);
const onItemSpotlightDown = useCallback((e) => {
e.stopPropagation();
Spotlight.focus("trandingnow_bestseller");
}, []);
const handleBlur = useCallback((itemIndex) => {
if (itemIndex === 0) {
handleStopScrolling();
} }
}, []); }, []);
const handleFocus = useCallback(
(index) => () => {
handleItemFocus(LOG_MENU.TRENDING_NOW_BEST_SELLER);
if (cursorVisible) {
return;
}
},
[cursorVisible, handleItemFocus]
);
const handleSpotlightRight = useCallback((e) => {
e.stopPropagation();
Spotlight.focus("spotlightId-trendingNowTopBtn");
}, []);
const handleItemFocus = useCallback((nowMenu) => {
setTimeout(() => dispatch(sendLogGNB(nowMenu)));
}, []);
const handleItemClick = useCallback(
(e) => {
const c = Spotlight.getCurrent();
let targetSpotlightId = null;
if (c) {
targetSpotlightId = c.getAttribute("data-spotlight-id");
}
dispatch(
updatePanel({
name: panel_names.TRENDING_NOW_PANEL,
panelInfo: {
currentSpot: targetSpotlightId,
focusedContainerId: focusedContainerIdRef.current,
selectedIndex,
},
})
);
},
[selectedIndex]
);
const onFocusedContainerId = useCallback((containerId) => {
focusedContainerIdRef.current = containerId;
}, []);
useEffect(() => {
if (panelInfo && panelInfo?.selectedIndex) {
setSelectedIndex(panelInfo?.selectedIndex);
}
}, [panelInfo?.selectedIndex]);
return ( return (
<div className={css.trendingNowWrap}> <div className={css.trendingNowWrap}>
{selectedIndex >= 1 && showButton && ( {selectedIndex >= 1 && showButton && (
<TButton <TButton
className={classNames(css.button, css.prevBtn)} className={classNames(css.button, css.prevBtn)}
onClick={handlePrevClick} onClick={handleIndicatorClick("prev")}
spotlightId="popular-prev-arrow" onSpotlightRight={handleSpotlight(
onSpotlightRight={indicatorLeftonSpotlight} SpotlightIds.TRENDING_NOW_POPULAR_VIDEO
onSpotlightDown={onItemSpotlightDown} )}
onSpotlightDown={handleSpotlight(
SpotlightIds.TRENDING_NOW_BEST_SELLER
)}
spotlightId={SpotlightIds.TRENDING_NOW_PREV_INDICATOR}
ariaLabel="Move to left Button" ariaLabel="Move to left Button"
/> />
)} )}
@@ -305,9 +243,9 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
> >
<TVerticalPagenator <TVerticalPagenator
className={css.tVerticalPagenator} className={css.tVerticalPagenator}
spotlightId={"trandingnow_verticalPagenator"} spotlightId={SpotlightIds.TRENDING_NOW_VERTICAL_PAGINATOR}
defaultContainerId={panelInfo?.focusedContainerId} defaultContainerId={panelInfo?.focusedContainerId}
onScroll={_onScroll} onScroll={handleScroll}
onFocusedContainerId={onFocusedContainerId} onFocusedContainerId={onFocusedContainerId}
cbChangePageRef={cbChangePageRef} cbChangePageRef={cbChangePageRef}
topMargin={36} topMargin={36}
@@ -315,7 +253,7 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
{topInfos && topInfos?.length > 0 && ( {topInfos && topInfos?.length > 0 && (
<Container <Container
className={css.popularContainer} className={css.popularContainer}
spotlightId={"trandingnow_popularcontainer"} spotlightId={SpotlightIds.TRENDING_NOW_POPULAR_SHOW}
data-wheel-point={true} data-wheel-point={true}
> >
<SectionTitle <SectionTitle
@@ -323,72 +261,62 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
label="POPULAR SHOW, Heading1" label="POPULAR SHOW, Heading1"
/> />
<PopularShowIndicator <PopularShowIndicator
onSpotlightDown={onItemSpotlightDown}
topInfos={topInfos} topInfos={topInfos}
selectedIndex={selectedIndex} selectedIndex={selectedIndex}
onSpotlightDown={handleSpotlight(
SpotlightIds.TRENDING_NOW_BEST_SELLER
)}
onSpotlightRight={handleSpotlight(
SpotlightIds.TRENDING_NOW_NEXT_INDICATOR
)}
handleItemFocus={handleItemFocus} handleItemFocus={handleItemFocus}
handleItemClick={handleItemClick} handleItemClick={handleItemClick}
isOnTop={isOnTop} isOnTop={isOnTop}
/> />
</Container> </Container>
)} )}
{bestSellerDatas && bestSellerDatas?.length > 0 && ( {bestSeller && bestSeller?.length > 0 && (
<BestSellerContainer <BestSellerContainer
className={css.bestContainer} className={css.bestContainer}
spotlightId={"trandingnow_bestseller"} spotlightId={SpotlightIds.TRENDING_NOW_BEST_SELLER}
data-wheel-point={true} data-wheel-point
> >
<SectionTitle <SectionTitle
title={$L(STRING_CONF.BEST_SELLER)} title={$L(STRING_CONF.BEST_SELLER)}
data-title-index="TNBestSellerTitle" data-title-index="TNBestSellerTitle"
/> />
<div className={css.itemList}> <div className={css.itemList}>
{bestSellerDatas.map((item, index) => { {bestSeller.map((item, index) => (
const rankText = <TItemCard
item.rankOrd === 1 key={item.prdtId}
? item.rankOrd + "st," imageAlt={item.prdtId}
: item.rankOrd === 2 imageSource={item.imgUrl}
? item.rankOrd + "nd," priceInfo={item.priceInfo}
: item.rankOrd === 3 productName={item.prdtNm}
? item.rankOrd + "rd," isBestSeller
: item.rankOrd + "th,"; rank={item.rankOrd}
return ( onFocus={handleBestSellerFocus}
<TItemCard onClick={handleBestSellerClick(item)}
key={item.prdtId} offerInfo={item.offerInfo}
imageAlt={item.prdtId} productId={item.prdtId}
imageSource={item.imgUrl} firstLabel={getFirstLabel(item.rankOrd)}
priceInfo={item.priceInfo} label={index * 1 + 1 + " of " + bestSeller.length}
productName={item.prdtNm} lastLabel=" go to detail, button"
isBestSeller={true} data-wheel-point={index >= 5}
rank={item.rankOrd} />
onFocus={handleFocus(index)} ))}
onBlur={() => handleBlur(index)}
onClick={() => handleCardClick(item)}
offerInfo={item.offerInfo}
productId={item.prdtId}
firstLabel={rankText}
label={index * 1 + 1 + " of " + bestSellerDatas.length}
lastLabel=" go to detail, button"
spotlightId={
"bs-spotlightId-" + removeDotAndColon(item.prdtId)
}
data-wheel-point={index >= 5}
/>
);
})}
</div> </div>
</BestSellerContainer> </BestSellerContainer>
)} )}
<Container> <Container>
{((topInfos && topInfos?.length > 0) || {((topInfos && topInfos?.length > 0) ||
(bestSellerDatas && bestSellerDatas?.length > 10)) && ( (bestSeller && bestSeller?.length > 10)) && (
<TButton <TButton
onClick={handleTopButtonClick} onClick={handleTopButtonClick}
onSpotlightRight={handleSpotlightRight}
size={null} size={null}
spotlightId="spotlightId-trendingNowTopBtn" spotlightId={SpotlightIds.TRENDING_NOW_TOP_BUTTON}
ariaLabel="Move to Top Button" ariaLabel="Move to Top Button"
data-wheel-point={true} data-wheel-point
type={TYPES.topButton} type={TYPES.topButton}
/> />
)} )}
@@ -402,9 +330,11 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
showButton && ( showButton && (
<TButton <TButton
className={classNames(css.button, css.nextBtn)} className={classNames(css.button, css.nextBtn)}
onClick={handleNextClick} onClick={handleIndicatorClick("next")}
spotlightId="popular-next-arrow" onSpotlightDown={handleSpotlight(
onSpotlightDown={onItemSpotlightDown} SpotlightIds.TRENDING_NOW_BEST_SELLER
)}
spotlightId={SpotlightIds.TRENDING_NOW_NEXT_INDICATOR}
ariaLabel="Move to right Button" ariaLabel="Move to right Button"
/> />
)} )}