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

Changed files:
1. deepLinkHandler.js
2. TrendingNowPanel.jsx
3. PopularShowIndicator.jsx
4. PopularShowIndicator.module.less
5. PopularProductList.jsx
6. PopularVideoCard.jsx

Detail Note:
1. Component optimization
2. Removal of duplicate functions and effects
3. Deletion of unnecessary props and imports
This commit is contained in:
younghoon100.park
2024-11-14 16:14:54 +09:00
parent 234eb819e9
commit 2d2d01c53c
6 changed files with 161 additions and 219 deletions

View File

@@ -1,6 +1,7 @@
import { updateHomeInfo } from "../actions/homeActions"; import { updateHomeInfo } from "../actions/homeActions";
import { pushPanel } from "../actions/panelActions"; import { pushPanel } from "../actions/panelActions";
import { LOG_MENU, panel_names } from "../utils/Config"; import { LOG_MENU, panel_names } from "../utils/Config";
import { SpotlightIds } from "../utils/SpotlightIds";
//V2_진입경로코드_진입경로명_MT_노출순번 //V2_진입경로코드_진입경로명_MT_노출순번
export const handleDeepLink = (contentTarget) => (dispatch, getState) => { export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
@@ -177,6 +178,7 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
panelName = panel_names.TRENDING_NOW_PANEL; panelName = panel_names.TRENDING_NOW_PANEL;
panelInfo = { panelInfo = {
pageName: "BS", pageName: "BS",
focusedContainerId: SpotlightIds.TRENDING_NOW_BEST_SELLER,
}; };
break; break;
@@ -186,6 +188,7 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
panelName = panel_names.TRENDING_NOW_PANEL; panelName = panel_names.TRENDING_NOW_PANEL;
panelInfo = { panelInfo = {
pageName: "PS", pageName: "PS",
focusedContainerId: SpotlightIds.TRENDING_NOW_POPULAR_SHOW,
}; };
break; break;

View File

@@ -27,12 +27,8 @@ const PopularShowIndicator = ({
showNm, showNm,
disclaimer, disclaimer,
expsOrd, expsOrd,
orderPhnNo,
productInfos,
patnrId, patnrId,
selectedPatnrId,
vtctpYn, vtctpYn,
showUrl,
catCd, catCd,
showId, showId,
patncNm, patncNm,
@@ -41,58 +37,40 @@ const PopularShowIndicator = ({
const isVertical = Boolean(vtctpYn === "Y"); const isVertical = Boolean(vtctpYn === "Y");
const _handleItemFocus = useCallback(() => { const _handleItemFocus = useCallback(() => {
if (handleItemFocus) { if (handleItemFocus) handleItemFocus(LOG_MENU.TRENDING_NOW_POPULAR_SHOWS);
handleItemFocus(LOG_MENU.TRENDING_NOW_POPULAR_SHOWS);
}
}, [handleItemFocus]); }, [handleItemFocus]);
const _handleItemClick = useCallback(() => { const _handleItemClick = useCallback(() => {
if (handleItemClick) { if (handleItemClick) handleItemClick();
handleItemClick();
}
}, [handleItemClick]); }, [handleItemClick]);
return ( return (
<div className={css.popularContainer}> <Container className={css.popularContainer}>
<div className={css.popularContents}> <PopularVideoCard
<Container> disclaimer={disclaimer}
<PopularVideoCard expsOrd={expsOrd}
thumbnailImgPath={thumbnailUrl960} handleItemClick={_handleItemClick}
showNm={showNm} handleItemFocus={_handleItemFocus}
disclaimer={disclaimer} isOnTop={isOnTop}
expsOrd={expsOrd} lgCatCd={catCd}
orderPhnNo={orderPhnNo} onSpotlightDown={onSpotlightDown}
thumbnailType={isVertical ? "vertical" : "horizontal"} patncNm={patncNm}
isVertical={isVertical} patnrId={patnrId}
popularShowInfos={topInfos[selectedIndex]} showId={showId}
showUrl={showUrl} showNm={showNm}
spotlightId={SpotlightIds.TRENDING_NOW_POPULAR_VIDEO} spotlightId={SpotlightIds.TRENDING_NOW_POPULAR_VIDEO}
onSpotlightDown={onSpotlightDown} thumbnailType={isVertical ? "vertical" : "horizontal"}
showId={showId} thumbnailImgPath={thumbnailUrl960}
patnrId={patnrId} />
lgCatCd={catCd} <PopularProductList
handleItemClick={_handleItemClick} handleItemClick={_handleItemClick}
handleItemFocus={_handleItemFocus} handleItemFocus={_handleItemFocus}
patncNm={patncNm} onSpotlightRight={onSpotlightRight}
isOnTop={isOnTop} onSpotlightDown={onSpotlightDown}
/> selectedIndex={selectedIndex}
</Container> topInfo={topInfos[selectedIndex]}
<Container className={css.popularProductListContainer}> />
<PopularProductList </Container>
brandProductInfo={productInfos}
topInfosData={topInfos[selectedIndex]}
patnrId={patnrId}
lgCatCd={catCd}
selectedPatnrId={selectedPatnrId}
onSpotlightRight={onSpotlightRight}
onSpotlightDown={onSpotlightDown}
selectedIndex={selectedIndex}
handleItemFocus={_handleItemFocus}
handleItemClick={_handleItemClick}
/>
</Container>
</div>
</div>
); );
}; };

View File

@@ -2,9 +2,12 @@
@import "../../../style/utils.module.less"; @import "../../../style/utils.module.less";
.popularContainer { .popularContainer {
.size(@w:1638px,@h:564px);
position: relative; position: relative;
display: flex;
justify-content: space-between;
.size(@w:1638px,@h:564px);
margin: 42px 0 0 90px; margin: 42px 0 0 90px;
&::after { &::after {
.position(@position: absolute, @right: 18px, @bottom: -46px); .position(@position: absolute, @right: 18px, @bottom: -46px);
z-index: 12; z-index: 12;
@@ -13,42 +16,4 @@
background-image: url("../../../../assets/images/img-topdeals-list-masking.png"); background-image: url("../../../../assets/images/img-topdeals-list-masking.png");
content: ""; content: "";
} }
.popularContents {
display: flex;
justify-content: space-between;
}
.player {
.position(@position: absolute, @top: 22px, @left: 0);
z-index: 20;
height: 564px;
display: none;
overflow: hidden;
border-radius: 12px;
&.vertical {
width: 326px;
}
&.horizontal {
width: 1002px;
}
&::before {
// Video desc
// .position(@position: absolute, @top: 33px, @left: 18px);
// z-index: 20;
// .size(@w: 108px, @h: 48px);
// border-radius: 12px;
// background-image: url("../../../../../assets/images/tag/tag-liveshow.png");
// background-position: center center;
// background-repeat: no-repeat;
// content: "";
}
&::after {
.focused(@borderRadius: 12px);
}
.focusDropShadow();
}
} }

View File

@@ -1,8 +1,7 @@
import React, { memo, useCallback, useEffect, useRef } from "react"; import React, { memo, useCallback, useEffect } from "react";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { pushPanel } from "../../../../actions/panelActions";
import { startVideoPlayer } from "../../../../actions/playActions"; import { startVideoPlayer } from "../../../../actions/playActions";
import TItemCard, { import TItemCard, {
removeDotAndColon, removeDotAndColon,
@@ -10,64 +9,38 @@ import TItemCard, {
} from "../../../../components/TItemCard/TItemCard"; } from "../../../../components/TItemCard/TItemCard";
import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList"; import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
import useScrollTo from "../../../../hooks/useScrollTo"; import useScrollTo from "../../../../hooks/useScrollTo";
import { panel_names } from "../../../../utils/Config";
import { scaleH } from "../../../../utils/helperMethods"; import { scaleH } from "../../../../utils/helperMethods";
import { SpotlightIds } from "../../../../utils/SpotlightIds"; import { SpotlightIds } from "../../../../utils/SpotlightIds";
import css from "./PopularProductList.module.less"; import css from "./PopularProductList.module.less";
export default function PopularProductList({ const PopularProductList = ({
patnrId, handleItemClick,
selectedPatnrId, handleItemFocus,
onSpotlightRight, onSpotlightRight,
topInfosData,
brandProductInfo,
onFocus,
onSpotlightDown, onSpotlightDown,
selectedIndex, selectedIndex,
handleItemFocus, topInfo,
handleItemClick, }) => {
lgCatCd,
}) {
const { getScrollTo, scrollTop } = useScrollTo(); const { getScrollTo, scrollTop } = useScrollTo();
const dispatch = useDispatch(); const dispatch = useDispatch();
const timerRef = useRef();
const { catCd, patnrId, productInfos, showId } = topInfo;
useEffect(() => { useEffect(() => {
timerRef.current = setTimeout(() => scrollTop({ animate: false })); let timer = setTimeout(() => scrollTop({ animate: false }));
return () => clearTimeout(timerRef.current); return () => clearTimeout(timer);
}, [selectedIndex]); }, [selectedIndex]);
const _onSpotlightDown = useCallback( const _onSpotlightDown = useCallback(
(ev) => { (ev) => {
if (onSpotlightDown) { if (onSpotlightDown) onSpotlightDown(ev);
ev.stopPropagation();
ev.preventDefault();
onSpotlightDown(ev);
}
}, },
[onSpotlightDown] [onSpotlightDown]
); );
const handleFocus = useCallback(() => { const handleClick = useCallback(
if (handleItemFocus) { (index, offsetHour, prdtId) => () => {
handleItemFocus();
}
}, [handleItemFocus]);
const renderItem = useCallback(
({ index, ...rest }) => {
const {
offerInfo,
prdtId,
imgUrl,
prdtNm,
priceInfo,
soldoutFlag,
offsetHour,
} = brandProductInfo[index];
const { showId, patnrId } = topInfosData;
let y = let y =
index < 2 index < 2
? 0 ? 0
@@ -75,32 +48,47 @@ export default function PopularProductList({
? scaleH(208) ? scaleH(208)
: scaleH(index * 248 - 248 - 40); : scaleH(index * 248 - 248 - 40);
const handleClick = () => { dispatch(
dispatch( startVideoPlayer({
startVideoPlayer({ targetId: "spotlightId-" + removeDotAndColon(prdtId),
targetId: "spotlightId-" + removeDotAndColon(prdtId), offsetHour,
offsetHour, showId,
showId, patnrId,
patnrId, prdtId,
prdtId, lgCatCd: catCd,
lgCatCd, shptmBanrTpNm: "VOD",
shptmBanrTpNm: "VOD", index,
index, modal: false,
modal: false, y,
y, })
}) );
);
if (handleItemClick) { if (handleItemClick) handleItemClick();
handleItemClick(); },
} [catCd, patnrId, showId, handleItemClick]
}; );
const handleFocus = useCallback(() => {
if (handleItemFocus) handleItemFocus();
}, [handleItemFocus]);
const renderItem = useCallback(
({ index, ...rest }) => {
const {
imgUrl,
offerInfo,
offsetHour,
prdtId,
prdtNm,
priceInfo,
soldoutFlag,
} = productInfos[index];
return ( return (
<TItemCard <TItemCard
imageAlt={prdtNm} imageAlt={prdtNm}
imageSource={imgUrl} imageSource={imgUrl}
onClick={handleClick} onClick={handleClick(index, offsetHour, prdtId)}
onFocus={handleFocus} onFocus={handleFocus}
offerInfo={offerInfo} offerInfo={offerInfo}
priceInfo={priceInfo} priceInfo={priceInfo}
@@ -109,24 +97,26 @@ export default function PopularProductList({
className={css.itemCard} className={css.itemCard}
type={TYPES.horizontal} type={TYPES.horizontal}
onSpotlightRight={onSpotlightRight} onSpotlightRight={onSpotlightRight}
spotlightId={"popular-spotlightId-" + removeDotAndColon(prdtId)} spotlightId={
"spotlightId-" + "popularShow-" + removeDotAndColon(prdtId)
}
onSpotlightDown={_onSpotlightDown} onSpotlightDown={_onSpotlightDown}
label={index * 1 + 1 + " of " + brandProductInfo.length} label={index * 1 + 1 + " of " + productInfos.length}
lastLabel=" go to detail, button" lastLabel=" go to detail, button"
{...rest} {...rest}
/> />
); );
}, },
[brandProductInfo, dispatch, patnrId, handleFocus, handleItemClick] [productInfos, handleClick, handleFocus, _onSpotlightDown]
); );
return ( return (
<div className={css.container}> <div className={css.container}>
{brandProductInfo && ( {productInfos && (
<TVirtualGridList <TVirtualGridList
cbScrollTo={getScrollTo} cbScrollTo={getScrollTo}
className={css.tVirtualGridList} className={css.tVirtualGridList}
dataSize={brandProductInfo.length} dataSize={productInfos.length}
itemHeight={236} itemHeight={236}
itemWidth={600} itemWidth={600}
spacing={12} spacing={12}
@@ -137,4 +127,6 @@ export default function PopularProductList({
)} )}
</div> </div>
); );
} };
export default memo(PopularProductList);

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { memo, useCallback, useEffect, useRef, useState } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch } from "react-redux";
import { Job } from "@enact/core/util"; import { Job } from "@enact/core/util";
import Spotlight from "@enact/spotlight"; import Spotlight from "@enact/spotlight";
@@ -10,7 +10,7 @@ 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 { import {
finishVideoPreview, finishVideoPreview,
startVideoPlayer, startVideoPlayer,
@@ -20,7 +20,7 @@ import css from "./PopularVideoCard.module.less";
const SpottableComponent = Spottable("div"); const SpottableComponent = Spottable("div");
const PHONE_STRING = "Phone"; // const PHONE_STRING = "Phone";
const WARNING_STRING = "warning"; const WARNING_STRING = "warning";
const TYPE = { const TYPE = {
@@ -28,46 +28,39 @@ const TYPE = {
vertical: "vertical", vertical: "vertical",
}; };
export default function PopularVideoCard({ const PopularVideoCard = ({
showNm,
expsOrd,
orderPhnNo,
thumbnailImgPath,
disclaimer, disclaimer,
isVertical, expsOrd,
showUrl, handleItemClick,
handleItemFocus,
isOnTop,
lgCatCd,
onSpotlightDown,
patncNm,
patnrId,
showId,
showNm,
spotlightId, spotlightId,
thumbnailType = TYPE.horizontal, thumbnailType = TYPE.horizontal,
onSpotlightDown, thumbnailImgPath,
onSpotlightRight, }) => {
onSpotlightLeft,
showId,
patnrId,
lgCatCd,
handleItemFocus,
patncNm,
handleItemClick,
isOnTop,
}) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [isFocused, setIsFocused] = useState(false);
const videoFocusTimeoutJob = useRef(new Job((func) => func(), 1000));
const isFullScreenModeActivedRef = useRef(false);
const cursorVisible = useSelector( const [isFocused, setIsFocused] = useState(false);
(state) => state.common.appStatus.cursorVisible
); const isFullScreenModeActiveRef = useRef(false);
const videoFocusTimeoutJob = useRef(new Job((func) => func(), 1000));
useEffect(() => { useEffect(() => {
if (isFullScreenModeActivedRef.current && isOnTop) { if (isFullScreenModeActiveRef.current && isOnTop) {
setTimeout(() => { setTimeout(() => {
if (cursorVisible || Spotlight.getPointerMode()) { if (Spotlight.getPointerMode()) {
dispatch(finishVideoPreview()); dispatch(finishVideoPreview());
isFullScreenModeActivedRef.current = false; isFullScreenModeActiveRef.current = false;
} }
}); });
} }
}, [cursorVisible, isOnTop]); }, [isOnTop]);
useEffect(() => { useEffect(() => {
const videoFocusTimeoutJobValue = videoFocusTimeoutJob.current; const videoFocusTimeoutJobValue = videoFocusTimeoutJob.current;
@@ -87,7 +80,7 @@ export default function PopularVideoCard({
}) })
); );
isFullScreenModeActivedRef.current = true; isFullScreenModeActiveRef.current = true;
}); });
} else { } else {
videoFocusTimeoutJobValue.stop(); videoFocusTimeoutJobValue.stop();
@@ -97,9 +90,8 @@ export default function PopularVideoCard({
const onFocus = useCallback(() => { const onFocus = useCallback(() => {
setIsFocused(true); setIsFocused(true);
if (handleItemFocus) {
handleItemFocus(); if (handleItemFocus) handleItemFocus();
}
}, [handleItemFocus]); }, [handleItemFocus]);
const onBlur = useCallback(() => { const onBlur = useCallback(() => {
@@ -122,18 +114,12 @@ export default function PopularVideoCard({
}) })
); );
if (handleItemClick) { if (handleItemClick) handleItemClick();
handleItemClick();
}
}, [dispatch, showId, spotlightId, handleItemClick]); }, [dispatch, showId, spotlightId, handleItemClick]);
const _onSpotlightDown = useCallback( const _onSpotlightDown = useCallback(
(ev) => { (ev) => {
if (onSpotlightDown) { if (onSpotlightDown) onSpotlightDown(ev);
ev.stopPropagation();
ev.preventDefault();
onSpotlightDown(ev);
}
}, },
[onSpotlightDown] [onSpotlightDown]
); );
@@ -175,4 +161,6 @@ export default function PopularVideoCard({
</div> </div>
</SpottableComponent> </SpottableComponent>
); );
} };
export default memo(PopularVideoCard);

View File

@@ -15,10 +15,11 @@ 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 from "../../components/TItemCard/TItemCard"; import 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 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 } from "../../utils/helperMethods"; import { $L } from "../../utils/helperMethods";
@@ -91,15 +92,25 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
}, [panelInfo?.selectedIndex]); }, [panelInfo?.selectedIndex]);
useEffect(() => { useEffect(() => {
if (isOnTop && panelInfo?.focusedContainerId) { if (isOnTop) {
const menu = let menu;
panelInfo?.focusedContainerId === SpotlightIds.TRENDING_NOW_POPULAR_SHOW
? LOG_MENU.TRENDING_NOW_POPULAR_SHOWS
: LOG_MENU.TRENDING_NOW_BEST_SELLER;
dispatch(sendLogGNB(menu)); // case: entering through a deep link or the Home, and returning from the player or details
if (panelInfo?.focusedContainerId) {
menu =
panelInfo.focusedContainerId !==
SpotlightIds.TRENDING_NOW_POPULAR_SHOW
? LOG_MENU.TRENDING_NOW_BEST_SELLER
: LOG_MENU.TRENDING_NOW_POPULAR_SHOWS;
}
// case: entering through the GNB
else {
menu = LOG_MENU.TRENDING_NOW_POPULAR_SHOWS;
}
if (menu) dispatch(sendLogGNB(menu));
} }
}, [isOnTop && panelInfo?.focusedContainerId]); }, [isOnTop]);
const onFocusedContainerId = useCallback((containerId) => { const onFocusedContainerId = useCallback((containerId) => {
focusedContainerIdRef.current = containerId; focusedContainerIdRef.current = containerId;
@@ -288,21 +299,26 @@ const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => {
<div className={css.itemList}> <div className={css.itemList}>
{bestSeller.map((item, index) => ( {bestSeller.map((item, index) => (
<TItemCard <TItemCard
key={item.prdtId} data-wheel-point={index >= 5}
firstLabel={getFirstLabel(item.rankOrd)}
imageAlt={item.prdtId} imageAlt={item.prdtId}
imageSource={item.imgUrl} imageSource={item.imgUrl}
priceInfo={item.priceInfo} key={item.prdtId}
productName={item.prdtNm}
isBestSeller isBestSeller
rank={item.rankOrd}
onFocus={handleBestSellerFocus}
onClick={handleBestSellerClick(item)}
offerInfo={item.offerInfo}
productId={item.prdtId}
firstLabel={getFirstLabel(item.rankOrd)}
label={index * 1 + 1 + " of " + bestSeller.length} label={index * 1 + 1 + " of " + bestSeller.length}
lastLabel=" go to detail, button" lastLabel=" go to detail, button"
data-wheel-point={index >= 5} offerInfo={item.offerInfo}
onFocus={handleBestSellerFocus}
onClick={handleBestSellerClick(item)}
priceInfo={item.priceInfo}
productName={item.prdtNm}
productId={item.prdtId}
rank={item.rankOrd}
spotlightId={
"spotlightId-" +
"bestSeller-" +
removeDotAndColon(item.prdtId)
}
/> />
))} ))}
</div> </div>