[251019] fix: TabContainerV2 , ShopNowContents YouMayAlsoConents처리
🕐 커밋 시간: 2025. 10. 19. 15:45:14 📊 변경 통계: • 총 파일: 6개 • 추가: +220줄 • 삭제: -62줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.v2.module.less ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/ShopNowContainer.module.less ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/ShopNowItem.module.less ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.module.less 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx (javascript): ✅ Added: handleItemClick()
This commit is contained in:
@@ -1,61 +1,37 @@
|
|||||||
import React, {
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
|
|
||||||
import {
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
useDispatch,
|
|
||||||
useSelector,
|
|
||||||
} 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';
|
||||||
import SpotlightContainerDecorator
|
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
from '@enact/spotlight/SpotlightContainerDecorator';
|
import { getContainerNode, setContainerLastFocusedElement } from '@enact/spotlight/src/container';
|
||||||
import {
|
|
||||||
getContainerNode,
|
|
||||||
setContainerLastFocusedElement,
|
|
||||||
} from '@enact/spotlight/src/container';
|
|
||||||
|
|
||||||
import { sendLogTotalRecommend } from '../../../../actions/logActions';
|
import { sendLogTotalRecommend } from '../../../../actions/logActions';
|
||||||
import { pushPanel } from '../../../../actions/panelActions';
|
import { pushPanel } from '../../../../actions/panelActions';
|
||||||
import { hidePlayerOverlays } from '../../../../actions/videoPlayActions';
|
import { hidePlayerOverlays } from '../../../../actions/videoPlayActions';
|
||||||
import TItemCard, { TYPES } from '../../../../components/TItemCard/TItemCard';
|
import TItemCard, { TYPES } from '../../../../components/TItemCard/TItemCard';
|
||||||
import TVirtualGridList
|
import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList';
|
||||||
from '../../../../components/TVirtualGridList/TVirtualGridList';
|
|
||||||
import useScrollTo from '../../../../hooks/useScrollTo';
|
import useScrollTo from '../../../../hooks/useScrollTo';
|
||||||
import {
|
import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, panel_names } from '../../../../utils/Config';
|
||||||
LOG_CONTEXT_NAME,
|
|
||||||
LOG_MENU,
|
|
||||||
LOG_MESSAGE_ID,
|
|
||||||
panel_names,
|
|
||||||
} from '../../../../utils/Config';
|
|
||||||
import { scaleH } from '../../../../utils/helperMethods';
|
import { scaleH } from '../../../../utils/helperMethods';
|
||||||
import ListEmptyContents
|
import ListEmptyContents from '../TabContents/ListEmptyContents/ListEmptyContents';
|
||||||
from '../TabContents/ListEmptyContents/ListEmptyContents';
|
|
||||||
import css1 from './ShopNowContents.module.less';
|
import css1 from './ShopNowContents.module.less';
|
||||||
import cssV2 from './ShopNowContents.v2.module.less';
|
import cssV2 from './ShopNowContents.v2.module.less';
|
||||||
|
|
||||||
const extractPriceInfo = (priceInfo) => {
|
const extractPriceInfo = (priceInfo) => {
|
||||||
if (!priceInfo)
|
if (!priceInfo) return { originalPrice: '', discountedPrice: '', discountRate: '' };
|
||||||
return { originalPrice: "", discountedPrice: "", discountRate: "" };
|
|
||||||
|
|
||||||
const parts = priceInfo.split("|").map((part) => part.trim());
|
const parts = priceInfo.split('|').map((part) => part.trim());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
originalPrice: parts[0] || "",
|
originalPrice: parts[0] || '',
|
||||||
discountedPrice: parts[1] || "",
|
discountedPrice: parts[1] || '',
|
||||||
discountRate: parts[4] || "",
|
discountRate: parts[4] || '',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const Container = SpotlightContainerDecorator(
|
const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||||
{ enterTo: "last-focused" },
|
|
||||||
"div"
|
|
||||||
);
|
|
||||||
export default function ShopNowContents({
|
export default function ShopNowContents({
|
||||||
shopNowInfo,
|
shopNowInfo,
|
||||||
videoVerticalVisible,
|
videoVerticalVisible,
|
||||||
@@ -65,16 +41,40 @@ export default function ShopNowContents({
|
|||||||
panelInfo,
|
panelInfo,
|
||||||
tabTitle,
|
tabTitle,
|
||||||
version = 1,
|
version = 1,
|
||||||
direction = "vertical",
|
direction = 'vertical',
|
||||||
}) {
|
}) {
|
||||||
const css = version === 2 ? cssV2 : css1;
|
const css = version === 2 ? cssV2 : css1;
|
||||||
const { getScrollTo, scrollTop } = useScrollTo();
|
const { getScrollTo, scrollTop } = useScrollTo();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const paenls = useSelector((state) => state.panels.panels[1]?.panelInfo);
|
const paenls = useSelector((state) => state.panels.panels[1]?.panelInfo);
|
||||||
|
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
|
||||||
const scrollTopJob = useRef(new Job((func) => func(), 0));
|
const scrollTopJob = useRef(new Job((func) => func(), 0));
|
||||||
const [height, setHeight] = useState();
|
const [height, setHeight] = useState();
|
||||||
const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]);
|
const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]);
|
||||||
|
|
||||||
|
// ShopNow + YouMayLike 통합 아이템 (v2이고 shopNow < 3일 때만)
|
||||||
|
const combinedItems = useMemo(() => {
|
||||||
|
if (!shopNowInfo) return [];
|
||||||
|
|
||||||
|
// 기본: ShopNow 아이템
|
||||||
|
let items = shopNowInfo.map((item) => ({
|
||||||
|
...item,
|
||||||
|
_type: 'shopnow',
|
||||||
|
}));
|
||||||
|
|
||||||
|
// v2 + ShopNow < 3 + YouMayLike 데이터 존재 시 통합
|
||||||
|
if (version === 2 && shopNowInfo.length < 3 && youmaylikeInfos && youmaylikeInfos.length > 0) {
|
||||||
|
items = items.concat(
|
||||||
|
youmaylikeInfos.map((item) => ({
|
||||||
|
...item,
|
||||||
|
_type: 'youmaylike',
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}, [shopNowInfo, youmaylikeInfos, version]);
|
||||||
|
|
||||||
// 각 상품별 가격 정보를 미리 계산
|
// 각 상품별 가격 정보를 미리 계산
|
||||||
const priceInfoMap = useMemo(() => {
|
const priceInfoMap = useMemo(() => {
|
||||||
if (!shopNowInfo) return {};
|
if (!shopNowInfo) return {};
|
||||||
@@ -90,7 +90,7 @@ export default function ShopNowContents({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
const gridListId = "playVideoShopNowBox";
|
const gridListId = 'playVideoShopNowBox';
|
||||||
const girdList = getContainerNode(gridListId);
|
const girdList = getContainerNode(gridListId);
|
||||||
|
|
||||||
if (girdList) setContainerLastFocusedElement(null, [gridListId]);
|
if (girdList) setContainerLastFocusedElement(null, [gridListId]);
|
||||||
@@ -129,6 +129,59 @@ export default function ShopNowContents({
|
|||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
({ index, ...rest }) => {
|
({ index, ...rest }) => {
|
||||||
|
const item = combinedItems[index];
|
||||||
|
|
||||||
|
// ===== YouMayLike 아이템 처리 =====
|
||||||
|
if (item._type === 'youmaylike') {
|
||||||
|
const { imgUrl, patnrId, prdtId, prdtNm, priceInfo, offerInfo } = item;
|
||||||
|
|
||||||
|
// YouMayLike 시작 지점 여부 (구분선 표시)
|
||||||
|
const isYouMayLikeStart = shopNowInfo && index === shopNowInfo.length;
|
||||||
|
|
||||||
|
const handleItemClick = () => {
|
||||||
|
dispatch(
|
||||||
|
pushPanel({
|
||||||
|
name: panel_names.DETAIL_PANEL,
|
||||||
|
panelInfo: {
|
||||||
|
showNm: playListInfo?.showNm,
|
||||||
|
showId: playListInfo?.showId,
|
||||||
|
liveFlag: playListInfo?.liveFlag,
|
||||||
|
thumbnailUrl: playListInfo?.thumbnailUrl,
|
||||||
|
patnrId,
|
||||||
|
prdtId,
|
||||||
|
launchedFromPlayer: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isYouMayLikeStart && <div className={css.youMayLikeDivider} />}
|
||||||
|
<TItemCard
|
||||||
|
{...rest}
|
||||||
|
key={prdtId}
|
||||||
|
imageAlt={prdtId}
|
||||||
|
imageSource={imgUrl}
|
||||||
|
priceInfo={priceInfo}
|
||||||
|
offerInfo={offerInfo}
|
||||||
|
productName={prdtNm}
|
||||||
|
productId={prdtId}
|
||||||
|
onClick={handleItemClick}
|
||||||
|
onFocus={() => {
|
||||||
|
if (handleItemFocus) {
|
||||||
|
handleItemFocus(LOG_MENU.FULL_YOU_MAY_LIKE);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
spotlightId={`you-may-like-item-${index}`}
|
||||||
|
type={TYPES.horizontal}
|
||||||
|
version={version}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== ShopNow 아이템 처리 (기존 로직) =====
|
||||||
const {
|
const {
|
||||||
imgUrls,
|
imgUrls,
|
||||||
patnrId,
|
patnrId,
|
||||||
@@ -140,11 +193,10 @@ export default function ShopNowContents({
|
|||||||
patncNm,
|
patncNm,
|
||||||
brndNm,
|
brndNm,
|
||||||
catNm,
|
catNm,
|
||||||
} = shopNowInfo[index];
|
} = item;
|
||||||
|
|
||||||
// 미리 계산된 가격 정보를 사용
|
// 미리 계산된 가격 정보를 사용
|
||||||
const { originalPrice, discountedPrice, discountRate } =
|
const { originalPrice, discountedPrice, discountRate } = priceInfoMap[index] || {};
|
||||||
priceInfoMap[index] || {};
|
|
||||||
|
|
||||||
const handleItemClick = () => {
|
const handleItemClick = () => {
|
||||||
const params = {
|
const params = {
|
||||||
@@ -173,7 +225,7 @@ export default function ShopNowContents({
|
|||||||
showId: playListInfo?.showId,
|
showId: playListInfo?.showId,
|
||||||
liveFlag: playListInfo?.liveFlag,
|
liveFlag: playListInfo?.liveFlag,
|
||||||
thumbnailUrl: playListInfo?.thumbnailUrl,
|
thumbnailUrl: playListInfo?.thumbnailUrl,
|
||||||
liveReqFlag: panelInfo?.shptmBanrTpNm === "LIVE" && "Y",
|
liveReqFlag: panelInfo?.shptmBanrTpNm === 'LIVE' && 'Y',
|
||||||
patnrId,
|
patnrId,
|
||||||
prdtId,
|
prdtId,
|
||||||
launchedFromPlayer: true,
|
launchedFromPlayer: true,
|
||||||
@@ -202,7 +254,7 @@ export default function ShopNowContents({
|
|||||||
// v2에서 첫 번째 아이템일 때 위로 가면 Close 버튼으로
|
// v2에서 첫 번째 아이템일 때 위로 가면 Close 버튼으로
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Spotlight.focus("shownow_close_button");
|
Spotlight.focus('shownow_close_button');
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
@@ -212,7 +264,7 @@ export default function ShopNowContents({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
shopNowInfo,
|
combinedItems,
|
||||||
videoVerticalVisible,
|
videoVerticalVisible,
|
||||||
panelInfo?.shptmBanrTpNm,
|
panelInfo?.shptmBanrTpNm,
|
||||||
priceInfoMap,
|
priceInfoMap,
|
||||||
@@ -221,25 +273,25 @@ export default function ShopNowContents({
|
|||||||
playListInfo,
|
playListInfo,
|
||||||
dispatch,
|
dispatch,
|
||||||
version,
|
version,
|
||||||
|
handleItemFocus,
|
||||||
|
handleFocus,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Container className={css.container}>
|
<Container className={css.container}>
|
||||||
{shopNowInfo && shopNowInfo.length > 0 ? (
|
{combinedItems && combinedItems.length > 0 ? (
|
||||||
<TVirtualGridList
|
<TVirtualGridList
|
||||||
style={version === 2 ? undefined : gridStyle}
|
style={version === 2 ? undefined : gridStyle}
|
||||||
cbScrollTo={getScrollTo}
|
cbScrollTo={getScrollTo}
|
||||||
dataSize={shopNowInfo.length}
|
dataSize={combinedItems.length}
|
||||||
direction={direction}
|
direction={direction}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
itemWidth={version === 2 ? 310 : videoVerticalVisible ? 540 : 600}
|
itemWidth={version === 2 ? 310 : videoVerticalVisible ? 540 : 600}
|
||||||
itemHeight={version === 2 ? 445 : 236}
|
itemHeight={version === 2 ? 445 : 236}
|
||||||
spacing={version === 2 ? 30 : 12}
|
spacing={version === 2 ? 30 : 12}
|
||||||
className={
|
className={videoVerticalVisible ? css.verticalItemList : css.itemList}
|
||||||
videoVerticalVisible ? css.verticalItemList : css.itemList
|
|
||||||
}
|
|
||||||
noScrollByWheel={false}
|
noScrollByWheel={false}
|
||||||
spotlightId="playVideoShopNowBox"
|
spotlightId="playVideoShopNowBox"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -51,3 +51,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YouMayLike 시작 지점 구분선
|
||||||
|
.youMayLikeDivider {
|
||||||
|
width: 2px !important;
|
||||||
|
height: 445px;
|
||||||
|
background: rgba(234, 234, 234, 0.3);
|
||||||
|
margin-right: 15px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,11 @@
|
|||||||
border-top: 1px solid rgba(234, 234, 234, 0.8);
|
border-top: 1px solid rgba(234, 234, 234, 0.8);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start, @direction: column);
|
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start, @direction: column);
|
||||||
gap: 40px;
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
|
||||||
|
> * + * {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@@ -23,7 +26,10 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: center);
|
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: center);
|
||||||
gap: 15px;
|
|
||||||
|
> * + * {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconWrapper {
|
.iconWrapper {
|
||||||
@@ -51,11 +57,14 @@
|
|||||||
.productList {
|
.productList {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start);
|
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start);
|
||||||
gap: 30px;
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
||||||
> * + * {
|
> * {
|
||||||
margin-left: 0;
|
margin-right: 30px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,13 @@
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start, @direction: column);
|
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start, @direction: column);
|
||||||
gap: 15px;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
> * + * {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: @PRIMARY_COLOR_RED;
|
border-color: @PRIMARY_COLOR_RED;
|
||||||
outline: 4px @PRIMARY_COLOR_RED solid;
|
outline: 4px @PRIMARY_COLOR_RED solid;
|
||||||
@@ -33,7 +36,10 @@
|
|||||||
.productInfo {
|
.productInfo {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
.flex(@display: flex, @justifyCenter: center, @alignCenter: flex-start, @direction: column);
|
.flex(@display: flex, @justifyCenter: center, @alignCenter: flex-start, @direction: column);
|
||||||
gap: 15px;
|
|
||||||
|
> * + * {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.productName {
|
.productName {
|
||||||
@@ -49,13 +55,19 @@
|
|||||||
.priceWrapper {
|
.priceWrapper {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start);
|
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: flex-start);
|
||||||
gap: 10px;
|
|
||||||
|
> * + * {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.priceContainer {
|
.priceContainer {
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: center);
|
.flex(@display: flex, @justifyCenter: flex-start, @alignCenter: center);
|
||||||
gap: 11px;
|
|
||||||
|
> * + * {
|
||||||
|
margin-left: 11px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.salePrice {
|
.salePrice {
|
||||||
|
|||||||
@@ -1,35 +1,26 @@
|
|||||||
import React, {
|
import React, { useCallback, useEffect } from 'react';
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
} from 'react';
|
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import Spotlight from '@enact/spotlight';
|
import Spotlight from '@enact/spotlight';
|
||||||
import SpotlightContainerDecorator
|
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
from '@enact/spotlight/SpotlightContainerDecorator';
|
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
|
|
||||||
// import icon_arrow_right from '../../../../../assets/images/icons';
|
// import icon_arrow_right from '../../../../../assets/images/icons';
|
||||||
import icon_arrow_dwon
|
import icon_arrow_dwon from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png';
|
||||||
from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png';
|
import icon_shop_now from '../../../../../assets/images/player/icon_tabcontainer_shopnow.png';
|
||||||
import icon_shop_now
|
|
||||||
from '../../../../../assets/images/player/icon_tabcontainer_shopnow.png';
|
|
||||||
import { LOG_MENU } from '../../../../utils/Config';
|
import { LOG_MENU } from '../../../../utils/Config';
|
||||||
import { $L } from '../../../../utils/helperMethods';
|
import { $L } from '../../../../utils/helperMethods';
|
||||||
import { SpotlightIds } from '../../../../utils/SpotlightIds';
|
import { SpotlightIds } from '../../../../utils/SpotlightIds';
|
||||||
import LiveChannelContents from '../TabContents/LiveChannelContents';
|
import LiveChannelContents from '../TabContents/LiveChannelContents';
|
||||||
import ShopNowContents from '../TabContents/ShopNowContents';
|
import ShopNowContents from '../TabContents/ShopNowContents';
|
||||||
import YouMayLikeContents from '../TabContents/YouMayLikeContents';
|
|
||||||
import ShopNowButton from './ShopNowButton';
|
import ShopNowButton from './ShopNowButton';
|
||||||
import css from './TabContainer.v2.module.less';
|
import css from './TabContainer.v2.module.less';
|
||||||
|
|
||||||
const Container = SpotlightContainerDecorator(
|
const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||||
{ enterTo: "last-focused" },
|
|
||||||
"div"
|
|
||||||
);
|
|
||||||
|
|
||||||
const SpottableDiv = Spottable("div");
|
const SpottableDiv = Spottable('div');
|
||||||
|
|
||||||
export default function TabContainerV2({
|
export default function TabContainerV2({
|
||||||
panelInfo,
|
panelInfo,
|
||||||
@@ -49,11 +40,11 @@ export default function TabContainerV2({
|
|||||||
onTabClose, // 탭 닫기 콜백 함수
|
onTabClose, // 탭 닫기 콜백 함수
|
||||||
tabVisible,
|
tabVisible,
|
||||||
}) {
|
}) {
|
||||||
|
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
|
||||||
|
|
||||||
const tabList = [
|
const tabList = [
|
||||||
$L("SHOP NOW"),
|
$L('SHOP NOW'),
|
||||||
panelInfo?.shptmBanrTpNm === "LIVE"
|
panelInfo?.shptmBanrTpNm === 'LIVE' ? $L('LIVE CHANNEL') : $L('FEATURED SHOWS'),
|
||||||
? $L("LIVE CHANNEL")
|
|
||||||
: $L("FEATURED SHOWS"),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -64,10 +55,8 @@ export default function TabContainerV2({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tabIndex === 1) {
|
if (tabIndex === 1) {
|
||||||
const isLive = panelInfo?.shptmBanrTpNm === "LIVE";
|
const isLive = panelInfo?.shptmBanrTpNm === 'LIVE';
|
||||||
nowMenu = isLive
|
nowMenu = isLive ? LOG_MENU.FULL_LIVE_CHANNELS : LOG_MENU.FULL_FEATURED_SHOWS;
|
||||||
? LOG_MENU.FULL_LIVE_CHANNELS
|
|
||||||
: LOG_MENU.FULL_FEATURED_SHOWS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nowMenu) {
|
if (nowMenu) {
|
||||||
@@ -89,7 +78,7 @@ export default function TabContainerV2({
|
|||||||
if (videoVerticalVisible) {
|
if (videoVerticalVisible) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Spotlight.focus("spotlightId-video-contaienr");
|
Spotlight.focus('spotlightId-video-contaienr');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[videoVerticalVisible]
|
[videoVerticalVisible]
|
||||||
@@ -120,7 +109,7 @@ export default function TabContainerV2({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (tabIndex === 2) {
|
if (tabIndex === 2) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Spotlight.focus("below-tab-shop-now-button");
|
Spotlight.focus('below-tab-shop-now-button');
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
}, [tabIndex]);
|
}, [tabIndex]);
|
||||||
@@ -136,45 +125,53 @@ export default function TabContainerV2({
|
|||||||
>
|
>
|
||||||
{tabVisible && tabIndex === 0 && (
|
{tabVisible && tabIndex === 0 && (
|
||||||
<>
|
<>
|
||||||
<div className={css.shopNowHeader}>
|
<div className={css.shopNowHeaderContainer}>
|
||||||
<SpottableDiv
|
<div className={css.shopNowHeader}>
|
||||||
className={css.shopNowHeaderLeft}
|
<SpottableDiv
|
||||||
spotlightId="shownow_close_button"
|
className={css.shopNowHeaderLeft}
|
||||||
onClick={handleCloseButtonClick}
|
spotlightId="shownow_close_button"
|
||||||
onSpotlightUp={handleSpotlightUpToBackButton}
|
onClick={handleCloseButtonClick}
|
||||||
onSpotlightDown={(e) => {
|
onSpotlightUp={handleSpotlightUpToBackButton}
|
||||||
// 첫 번째 ShopNow 아이템으로 포커스 이동
|
onSpotlightDown={(e) => {
|
||||||
e.stopPropagation();
|
// 첫 번째 ShopNow 아이템으로 포커스 이동
|
||||||
e.preventDefault();
|
e.stopPropagation();
|
||||||
Spotlight.focus("shop-now-item-0");
|
e.preventDefault();
|
||||||
}}
|
Spotlight.focus('shop-now-item-0');
|
||||||
>
|
}}
|
||||||
<div className={css.shopNowIconWrapper}>
|
>
|
||||||
<img
|
<div className={css.shopNowIconWrapper}>
|
||||||
src={icon_shop_now}
|
<img src={icon_shop_now} alt="shop now icon" className={css.shopNowIcon} />
|
||||||
alt="shop now icon"
|
</div>
|
||||||
className={css.shopNowIcon}
|
<div className={css.shopNowHeaderText}>SHOP NOW</div>
|
||||||
/>
|
<div className={css.arrowIcon}>
|
||||||
</div>
|
<img src={icon_arrow_dwon} alt="arrow down" />
|
||||||
<div className={css.shopNowHeaderText}>SHOP NOW</div>
|
</div>
|
||||||
<div className={css.arrowIcon}>
|
</SpottableDiv>
|
||||||
<img src={icon_arrow_dwon} alt="arrow down" />
|
{/* <SpottableDiv
|
||||||
</div>
|
className={css.closeButton}
|
||||||
</SpottableDiv>
|
spotlightId="below-tab-close-button"
|
||||||
{/* <SpottableDiv
|
onClick={handleCloseButtonClick}
|
||||||
className={css.closeButton}
|
onSpotlightUp={handleSpotlightUpToBackButton}
|
||||||
spotlightId="below-tab-close-button"
|
onSpotlightDown={(e) => {
|
||||||
onClick={handleCloseButtonClick}
|
// 첫 번째 ShopNow 아이템으로 포커스 이동
|
||||||
onSpotlightUp={handleSpotlightUpToBackButton}
|
e.stopPropagation();
|
||||||
onSpotlightDown={(e) => {
|
e.preventDefault();
|
||||||
// 첫 번째 ShopNow 아이템으로 포커스 이동
|
Spotlight.focus("shop-now-item-0");
|
||||||
e.stopPropagation();
|
}}
|
||||||
e.preventDefault();
|
>
|
||||||
Spotlight.focus("shop-now-item-0");
|
×
|
||||||
}}
|
</SpottableDiv> */}
|
||||||
>
|
</div>
|
||||||
×
|
|
||||||
</SpottableDiv> */}
|
{/* YouMayAlso Like 헤더 (ShopNow 아이템 < 3 && YouMayLike 데이터 존재) */}
|
||||||
|
{shopNowInfo &&
|
||||||
|
shopNowInfo.length < 3 &&
|
||||||
|
youmaylikeInfos &&
|
||||||
|
youmaylikeInfos.length > 0 && (
|
||||||
|
<div className={css.youMayAlsoLikeHeader}>
|
||||||
|
<div className={css.youMayAlsoLikeText}>You may also like</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ShopNowContents
|
<ShopNowContents
|
||||||
tabTitle={tabList}
|
tabTitle={tabList}
|
||||||
@@ -187,15 +184,6 @@ export default function TabContainerV2({
|
|||||||
version={2}
|
version={2}
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
/>
|
/>
|
||||||
{shopNowInfo && shopNowInfo.length < 3 && (
|
|
||||||
<YouMayLikeContents
|
|
||||||
shopNowInfo={shopNowInfo}
|
|
||||||
handleItemFocus={_handleItemFocus}
|
|
||||||
playListInfo={playListInfo && playListInfo[selectedIndex]}
|
|
||||||
version={2}
|
|
||||||
direction="horizontal"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -208,7 +196,7 @@ export default function TabContainerV2({
|
|||||||
onSpotlightUp={handleSpotlightUpToBackButton}
|
onSpotlightUp={handleSpotlightUpToBackButton}
|
||||||
onSpotlightDown={(e) => {
|
onSpotlightDown={(e) => {
|
||||||
// 첫 번째 PlayerItem으로 포커스 이동
|
// 첫 번째 PlayerItem으로 포커스 이동
|
||||||
Spotlight.focus("tabChannel-video-0");
|
Spotlight.focus('tabChannel-video-0');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={css.buttonText}>LIVE CHANNEL</span>
|
<span className={css.buttonText}>LIVE CHANNEL</span>
|
||||||
@@ -217,7 +205,7 @@ export default function TabContainerV2({
|
|||||||
</div>
|
</div>
|
||||||
</SpottableDiv>
|
</SpottableDiv>
|
||||||
|
|
||||||
{panelInfo?.shptmBanrTpNm === "LIVE" && playListInfo && (
|
{panelInfo?.shptmBanrTpNm === 'LIVE' && playListInfo && (
|
||||||
<LiveChannelContents
|
<LiveChannelContents
|
||||||
tabTitle={tabList}
|
tabTitle={tabList}
|
||||||
selectedIndex={selectedIndex}
|
selectedIndex={selectedIndex}
|
||||||
@@ -236,9 +224,7 @@ export default function TabContainerV2({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tabVisible && tabIndex === 2 && (
|
{tabVisible && tabIndex === 2 && <ShopNowButton onClick={onShopNowButtonClick} />}
|
||||||
<ShopNowButton onClick={onShopNowButtonClick} />
|
|
||||||
)}
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,14 +89,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShopNow 헤더 컨테이너 (ShopNow + YouMayAlsoLike 헤더를 같은 라인에 배치)
|
||||||
|
.shopNowHeaderContainer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
// SHOP NOW 헤더 스타일 (ShopNowContainer 참고)
|
// SHOP NOW 헤더 스타일 (ShopNowContainer 참고)
|
||||||
.shopNowHeader {
|
.shopNowHeader {
|
||||||
width: 100%;
|
width: auto;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
.flex(@display: flex, @justifyCenter: space-between, @alignCenter: center);
|
.flex(@display: flex, @justifyCenter: space-between, @alignCenter: center);
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shopNowIconWrapper {
|
.shopNowIconWrapper {
|
||||||
@@ -239,6 +247,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YOU MAY ALSO LIKE 헤더 스타일
|
||||||
|
.youMayAlsoLikeHeader {
|
||||||
|
margin-left: 90px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 20px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 100px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.youMayAlsoLikeText {
|
||||||
|
margin-right: 15px;
|
||||||
|
color: #EAEAEA;
|
||||||
|
font-size: 24px;
|
||||||
|
font-family: @baseFont;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 31px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* 애니메이션 정의 */
|
/* 애니메이션 정의 */
|
||||||
@keyframes slideInFromRight {
|
@keyframes slideInFromRight {
|
||||||
from {
|
from {
|
||||||
|
|||||||
Reference in New Issue
Block a user