From 4e2014ae4168cf2298a78a247bc8136e7beaa4d8 Mon Sep 17 00:00:00 2001 From: "opacity@t-win.kr" Date: Fri, 5 Dec 2025 15:55:21 +0900 Subject: [PATCH] =?UTF-8?q?[=ED=86=B5=ED=95=A9=EB=A1=9C=EA=B7=B8]ShopNowCo?= =?UTF-8?q?ntents=20=EB=A1=9C=EA=B7=B8=20=EC=A0=95=EB=B3=B4=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TabContents/ShopNowContents.jsx | 148 +++++++++++------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx index 440d6077..40af25e0 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx @@ -1,38 +1,60 @@ -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 classNames from "classnames"; +import { useDispatch, useSelector } from "react-redux"; -import { Job } from '@enact/core/util'; -import Spotlight from '@enact/spotlight'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; -import { getContainerNode, setContainerLastFocusedElement } from '@enact/spotlight/src/container'; +import { Job } from "@enact/core/util"; +import Spotlight from "@enact/spotlight"; +import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; +import { + getContainerNode, + setContainerLastFocusedElement, +} from "@enact/spotlight/src/container"; -import { sendLogTotalRecommend } from '../../../../actions/logActions'; -import { navigateToDetail, SOURCE_MENUS, pushPanel } from '../../../../actions/panelActions'; -import { hidePlayerOverlays } from '../../../../actions/videoPlayActions'; -import TItemCard, { TYPES } from '../../../../components/TItemCard/TItemCard'; -import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList'; -import useScrollTo from '../../../../hooks/useScrollTo'; -import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, panel_names } from '../../../../utils/Config'; -import { scaleH } from '../../../../utils/helperMethods'; -import ListEmptyContents from '../TabContents/ListEmptyContents/ListEmptyContents'; -import css1 from './ShopNowContents.module.less'; -import cssV2 from './ShopNowContents.v2.module.less'; +import { sendLogTotalRecommend } from "../../../../actions/logActions"; +import { + navigateToDetail, + SOURCE_MENUS, + pushPanel, +} from "../../../../actions/panelActions"; +import { hidePlayerOverlays } from "../../../../actions/videoPlayActions"; +import TItemCard, { TYPES } from "../../../../components/TItemCard/TItemCard"; +import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList"; +import useScrollTo from "../../../../hooks/useScrollTo"; +import { + LOG_CONTEXT_NAME, + LOG_MENU, + LOG_MESSAGE_ID, + panel_names, +} from "../../../../utils/Config"; +import { scaleH } from "../../../../utils/helperMethods"; +import ListEmptyContents from "../TabContents/ListEmptyContents/ListEmptyContents"; +import css1 from "./ShopNowContents.module.less"; +import cssV2 from "./ShopNowContents.v2.module.less"; const extractPriceInfo = (priceInfo) => { - if (!priceInfo) return { originalPrice: '', discountedPrice: '', discountRate: '' }; + if (!priceInfo) + return { originalPrice: "", discountedPrice: "", discountRate: "" }; - const parts = priceInfo.split('|').map((part) => part.trim()); + const parts = priceInfo.split("|").map((part) => part.trim()); return { - originalPrice: parts[0] || '', - discountedPrice: parts[1] || '', - discountRate: parts[4] || '', + originalPrice: parts[0] || "", + discountedPrice: parts[1] || "", + discountRate: parts[4] || "", }; }; -const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); +const Container = SpotlightContainerDecorator( + { enterTo: "last-focused" }, + "div" +); export default function ShopNowContents({ shopNowInfo, videoVerticalVisible, @@ -42,7 +64,7 @@ export default function ShopNowContents({ panelInfo, tabTitle, version = 1, - direction = 'vertical', + direction = "vertical", }) { const css = version === 2 ? cssV2 : css1; const { getScrollTo, scrollTop } = useScrollTo(); @@ -54,12 +76,12 @@ export default function ShopNowContents({ const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]); useEffect(() => { - console.log('=== [ShopNow] Component Rendered ==='); - console.log('[ShopNow] shopNowInfo:', shopNowInfo); - console.log('[ShopNow] youmaylikeInfos:', youmaylikeInfos); - console.log('[ShopNow] version:', version); - console.log('[ShopNow] tabIndex:', tabIndex); - console.log('====================================='); + console.log("=== [ShopNow] Component Rendered ==="); + console.log("[ShopNow] shopNowInfo:", shopNowInfo); + console.log("[ShopNow] youmaylikeInfos:", youmaylikeInfos); + console.log("[ShopNow] version:", version); + console.log("[ShopNow] tabIndex:", tabIndex); + console.log("====================================="); }, [shopNowInfo, youmaylikeInfos, version, tabIndex]); // ShopNow + YouMayLike 통합 아이템 (v2이고 shopNow < 3일 때만) @@ -69,17 +91,17 @@ export default function ShopNowContents({ // 기본: ShopNow 아이템 let items = shopNowInfo.map((item) => ({ ...item, - _type: 'shopnow', + _type: "shopnow", })); // v2 + ShopNow < 3 + YouMayLike 데이터 존재 시 통합 - // for Test => + // for Test => if (version === 2 && youmaylikeInfos && youmaylikeInfos.length > 0) { - // if (version === 2 && shopNowInfo.length < 3 && youmaylikeInfos && youmaylikeInfos.length > 0) { + // if (version === 2 && shopNowInfo.length < 3 && youmaylikeInfos && youmaylikeInfos.length > 0) { items = items.concat( youmaylikeInfos.map((item) => ({ ...item, - _type: 'youmaylike', + _type: "youmaylike", })) ); } @@ -102,7 +124,7 @@ export default function ShopNowContents({ useEffect(() => { return () => { - const gridListId = 'playVideoShopNowBox'; + const gridListId = "playVideoShopNowBox"; const girdList = getContainerNode(gridListId); if (girdList) setContainerLastFocusedElement(null, [gridListId]); @@ -144,14 +166,17 @@ export default function ShopNowContents({ const item = combinedItems[index]; // ===== YouMayLike 아이템 처리 ===== - if (item._type === 'youmaylike') { + if (item._type === "youmaylike") { const { imgUrl, patnrId, prdtId, prdtNm, priceInfo, offerInfo } = item; // YouMayLike 시작 지점 여부 (구분선 표시) const isYouMayLikeStart = shopNowInfo && index === shopNowInfo.length; const handleYouMayLikeItemClick = () => { - console.log('[ShopNowContents] DetailPanel 진입 - sourceMenu:', SOURCE_MENUS.PLAYER_SHOP_NOW); + console.log( + "[ShopNowContents] DetailPanel 진입 - sourceMenu:", + SOURCE_MENUS.PLAYER_SHOP_NOW + ); dispatch( navigateToDetail({ @@ -195,7 +220,7 @@ export default function ShopNowContents({ onSpotlightUp={(e) => { e.stopPropagation(); e.preventDefault(); - Spotlight.focus('shownow_close_button'); + Spotlight.focus("shownow_close_button"); }} type={TYPES.horizontal} version={version} @@ -216,10 +241,12 @@ export default function ShopNowContents({ patncNm, brndNm, catNm, + lgCatNm, } = item; // 미리 계산된 가격 정보를 사용 - const { originalPrice, discountedPrice, discountRate } = priceInfoMap[index] || {}; + const { originalPrice, discountedPrice, discountRate } = + priceInfoMap[index] || {}; const handleShopNowItemClick = () => { // ===== 기존 코드 (코멘트 처리) ===== @@ -228,20 +255,20 @@ export default function ShopNowContents({ // const currentSpotlightId = currentFocusedElement?.getAttribute('data-spotlight-id'); // console.log('[ShopNowContents] 현재 포커스된 spotlightId:', currentSpotlightId); - // const params = { - // tabTitle: tabTitle[tabIndex], - // productId: prdtId, - // productTitle: prdtNm, - // partner: patncNm, - // brand: brndNm, - // price: discountRate ? discountedPrice : originalPrice, - // showType: panelInfo?.shptmBanrTpNm, - // category: catNm, - // discount: discountRate, - // contextName: LOG_CONTEXT_NAME.SHOW, - // messageId: LOG_MESSAGE_ID.CONTENTCLICK, - // }; - // dispatch(sendLogTotalRecommend(params)); + const params = { + tabTitle: tabTitle[tabIndex], + productId: prdtId, + productTitle: prdtNm, + partner: patncNm, + brand: brndNm, + price: discountRate ? discountedPrice : originalPrice, + showType: panelInfo?.shptmBanrTpNm, + category: catNm ?? lgCatNm, + discount: discountRate, + contextName: LOG_CONTEXT_NAME.SHOW, + messageId: LOG_MESSAGE_ID.CONTENTCLICK, + }; + dispatch(sendLogTotalRecommend(params)); // // DetailPanel push 전에 VideoPlayer 오버레이 숨김 // dispatch(hidePlayerOverlays()); @@ -264,7 +291,10 @@ export default function ShopNowContents({ // ); // ===== navigateToDetail 방식 (handleYouMayLikeItemClick 참고) ===== - console.log('[ShopNowContents] ShopNow DetailPanel 진입 - sourceMenu:', SOURCE_MENUS.PLAYER_SHOP_NOW); + console.log( + "[ShopNowContents] ShopNow DetailPanel 진입 - sourceMenu:", + SOURCE_MENUS.PLAYER_SHOP_NOW + ); dispatch( navigateToDetail({ @@ -276,7 +306,7 @@ export default function ShopNowContents({ showId: playListInfo?.showId, liveFlag: playListInfo?.liveFlag, thumbnailUrl: playListInfo?.thumbnailUrl, - liveReqFlag: panelInfo?.shptmBanrTpNm === 'LIVE' && 'Y', + liveReqFlag: panelInfo?.shptmBanrTpNm === "LIVE" && "Y", launchedFromPlayer: true, }, }) @@ -304,7 +334,7 @@ export default function ShopNowContents({ // v2에서 첫 번째 아이템일 때 위로 가면 Close 버튼으로 e.stopPropagation(); e.preventDefault(); - Spotlight.focus('shownow_close_button'); + Spotlight.focus("shownow_close_button"); } : undefined } @@ -341,7 +371,9 @@ export default function ShopNowContents({ itemWidth={version === 2 ? 310 : videoVerticalVisible ? 540 : 600} itemHeight={version === 2 ? 445 : 236} spacing={version === 2 ? 30 : 12} - className={videoVerticalVisible ? css.verticalItemList : css.itemList} + className={ + videoVerticalVisible ? css.verticalItemList : css.itemList + } noScrollByWheel={false} spotlightId="playVideoShopNowBox" />