From 6c0830f3f8e1802616846a838215afe83c5359f1 Mon Sep 17 00:00:00 2001 From: "junghoon86.park" Date: Mon, 20 Oct 2025 13:27:49 +0900 Subject: [PATCH] =?UTF-8?q?[foryou]=20foryou=ED=8C=A8=EB=84=90=20=EB=85=B8?= =?UTF-8?q?=EC=B6=9C=EA=B4=80=EB=A0=A8=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?=EC=97=90=EB=84=88=EC=A7=80=EB=9D=BC=EB=B2=A8=20=EB=85=B8?= =?UTF-8?q?=EC=B6=9C=20=EC=B2=98=EB=A6=AC#1=20=20-=20homebanner=EC=97=90?= =?UTF-8?q?=EC=84=9C=20justforyou=20dispatch=EC=B2=98=EB=A6=AC.=20=20-=20?= =?UTF-8?q?=ED=8F=AC=EC=9C=A0=EB=B6=80=EB=B6=84=20=EB=85=B8=EC=B6=9C=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=20-=20TITEMCARD=20videoshow=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=97=90=EB=84=88=EC=A7=80=EB=9D=BC=EB=B2=A8=20?= =?UTF-8?q?=EB=AF=B8=EB=85=B8=EC=B6=9C=20=EB=B3=80=EA=B2=BD.=20=20-=20fory?= =?UTF-8?q?ou=ED=8C=A8=EB=84=90=EC=97=90=EC=84=9C=2010000=EC=9E=90?= =?UTF-8?q?=EB=A6=AC=20=EB=84=98=EC=96=B4=EA=B0=80=EB=8A=94=EB=B6=80?= =?UTF-8?q?=EB=B6=84=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B8=88=EC=95=A1?= =?UTF-8?q?=EC=97=90=EB=94=B0=EB=A5=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=B2=98=EB=A6=AC=20=EB=B3=80=EA=B2=BD.?= =?UTF-8?q?=20=20-=20=EB=A1=A4=EB=A7=81=20=EB=B0=B0=EB=84=88=EC=AA=BD=20?= =?UTF-8?q?=EB=AF=B8=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TItemCard/TItemCard.module.less | 4 +- .../components/TItemCard/TItemCard.new.jsx | 243 +++++++++------ .../src/reducers/forYouReducer.js | 6 - .../views/HomePanel/HomeBanner/HomeBanner.jsx | 289 +++++++++++------- .../JustForYouTestPanel.jsx | 28 +- 5 files changed, 354 insertions(+), 216 deletions(-) diff --git a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less index ab4d4286..15cd065b 100644 --- a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less +++ b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less @@ -202,10 +202,10 @@ &.labelBox { width: calc(100% - 60px); > p { - font-size: 27px; + font-size: 25px; &.priceInfo { > span { - font-size: 16px; + font-size: 15px; } } } diff --git a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx index ca692bff..153d63ef 100644 --- a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx +++ b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx @@ -1,69 +1,92 @@ -import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { + memo, + useCallback, + useEffect, + useMemo, + 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 Spottable from '@enact/spotlight/Spottable'; -import defaultLogoImg from '../../../assets/images/ic-tab-partners-default@3x.png'; -import defaultimgHorizontal from '../../../assets/images/img-thumb-empty-hor@3x.png'; -import defaultImageItem from '../../../assets/images/img-thumb-empty-product@3x.png'; -import defaultimgVertical from '../../../assets/images/img-thumb-empty-ver@3x.png'; -import IcLiveShow from '../../../assets/images/tag/tag-liveshow.png'; // ๐Ÿงช ํ…Œ์ŠคํŠธ์šฉ ์—๋„ˆ์ง€ ๋ผ๋ฒจ (์‹ค์ œ PDF ๋ณ€ํ™˜ ํ…Œ์ŠคํŠธ) -import testEnergyIconA from '../../../assets/images/energyLabel/labelgradeA.png'; -import testEnergyIconB from '../../../assets/images/energyLabel/labelgradeB.png'; -import testEnergyIconC from '../../../assets/images/energyLabel/labelgradeC.png'; +import testEnergyIconA + from '../../../assets/images/energyLabel/labelgradeA.png'; +import testEnergyIconB + from '../../../assets/images/energyLabel/labelgradeB.png'; +import testEnergyIconC + from '../../../assets/images/energyLabel/labelgradeC.png'; +import defaultLogoImg + from '../../../assets/images/ic-tab-partners-default@3x.png'; +import defaultimgHorizontal + from '../../../assets/images/img-thumb-empty-hor@3x.png'; +import defaultImageItem + from '../../../assets/images/img-thumb-empty-product@3x.png'; +import defaultimgVertical + from '../../../assets/images/img-thumb-empty-ver@3x.png'; +import IcLiveShow from '../../../assets/images/tag/tag-liveshow.png'; import testEnergyPdf from '../../../assets/mock/EnergyLabelSample.pdf'; -import { setHidePopup, setShowPopup } from '../../actions/commonActions'; +import { + setHidePopup, + setShowPopup, +} from '../../actions/commonActions'; import { clearConvertedImage, - convertPdfToImage, convertMultiplePdfs, + convertPdfToImage, } from '../../actions/convertActions'; import { sendLogTotalRecommend } from '../../actions/logActions'; import usePriceInfo from '../../hooks/usePriceInfo'; import * as Config from '../../utils/Config'; -import { $L, getQRCodeUrl, removeSpecificTags } from '../../utils/helperMethods'; +import { + $L, + getQRCodeUrl, + removeSpecificTags, +} from '../../utils/helperMethods'; import { SpotlightIds } from '../../utils/SpotlightIds'; import CustomImage from '../CustomImage/CustomImage'; import TPopUp from '../TPopUp/TPopUp'; import css from './TItemCard.module.less'; -const SpottableComponent = Spottable('div'); -const SpottableTemp = Spottable('div'); +const SpottableComponent = Spottable("div"); +const SpottableTemp = Spottable("div"); const TYPES = { - vertical: 'vertical', - horizontal: 'horizontal', - videoShow: 'videoShow', + vertical: "vertical", + horizontal: "horizontal", + videoShow: "videoShow", }; const IMAGETYPES = { - imgHorizontal: 'imgHorizontal', - imgVertical: 'imgVertical', + imgHorizontal: "imgHorizontal", + imgVertical: "imgVertical", }; const STRING_CONF = { - SOLD_OUT: 'SOLD OUT', - ENERGY_LOADING: 'Loading energy label...', - ENERGY_ERROR: 'Failed to load energy label', + SOLD_OUT: "SOLD OUT", + ENERGY_LOADING: "Loading energy label...", + ENERGY_ERROR: "Failed to load energy label", }; const ENERGY_LABEL_MODE = { - API_ONLY: 'API_ONLY', - WITH_MOCK: 'WITH_MOCK', + API_ONLY: "API_ONLY", + WITH_MOCK: "WITH_MOCK", }; const CURRENT_ENERGY_LABEL_MODE = ENERGY_LABEL_MODE.WITH_MOCK; export const removeDotAndColon = (string) => { - return /[.:]/.test(string) ? string.replace(/[.:]/g, '') : string; + return /[.:]/.test(string) ? string.replace(/[.:]/g, "") : string; }; const parsePrice = (price) => { - return parseFloat(price?.replace(/[^0-9.-]+/g, '') || '0'); + return parseFloat(price?.replace(/[^0-9.-]+/g, "") || "0"); }; const generateMockEnergyLabels = (productId) => { @@ -77,11 +100,13 @@ const generateMockEnergyLabels = (productId) => { return Math.abs(hash); }; - const seed = productId ? hashCode(productId) : Math.floor(Math.random() * 1000); + const seed = productId + ? hashCode(productId) + : Math.floor(Math.random() * 1000); const randomCount = (seed % 3) + 1; const testIcons = [testEnergyIconA, testEnergyIconB, testEnergyIconC]; - const testGrades = ['A (TEST)', 'B (TEST)', 'C (TEST)']; + const testGrades = ["A (TEST)", "B (TEST)", "C (TEST)"]; return Array.from({ length: randomCount }, (_, index) => ({ enrgLblUrl: testEnergyPdf, @@ -144,8 +169,12 @@ export default memo(function TItemCardNew({ const [currentPdfUrl, setCurrentPdfUrl] = useState(null); const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd); - const cursorVisible = useSelector((state) => state.common.appStatus.cursorVisible); - const { activePopup, popupVisible } = useSelector((state) => state.common.popup); + const cursorVisible = useSelector( + (state) => state.common.appStatus.cursorVisible + ); + const { activePopup, popupVisible } = useSelector( + (state) => state.common.popup + ); const convert = useSelector((state) => state.convert); @@ -156,7 +185,7 @@ export default memo(function TItemCardNew({ const currentBlobUrl = convert?.convertedImage; return () => { - if (currentBlobUrl && currentBlobUrl.startsWith('blob:')) { + if (currentBlobUrl && currentBlobUrl.startsWith("blob:")) { URL.revokeObjectURL(currentBlobUrl); } }; @@ -164,9 +193,11 @@ export default memo(function TItemCardNew({ useEffect(() => { if (!imageSource) { - if (type === 'videoShow') { + if (type === "videoShow") { setDefaultImage( - imgType === IMAGETYPES.imgHorizontal ? defaultimgHorizontal : defaultimgVertical + imgType === IMAGETYPES.imgHorizontal + ? defaultimgHorizontal + : defaultimgVertical ); } else { setDefaultImage(defaultImageItem); @@ -194,7 +225,8 @@ export default memo(function TItemCardNew({ // } // }, [euEnrgLblInfos, productId, dispatch]); - const { originalPrice, discountedPrice, discountRate } = usePriceInfo(priceInfo) || {}; + const { originalPrice, discountedPrice, discountRate } = + usePriceInfo(priceInfo) || {}; const _onBlur = useCallback(() => { if (onBlur) { @@ -282,23 +314,25 @@ export default memo(function TItemCardNew({ ); const ariaLabel = useMemo(() => { - const soldOutText = soldoutFlag === 'Y' ? 'Sold Out ' : ''; - const firstLabelText = firstLabel ? `${firstLabel} ` : ''; - const discountLabel = discountRate ? `${discountRate} discount, ` : ''; - const discountPriceLabel = discountRate ? `Sale price ${discountedPrice}, ` : ''; + const soldOutText = soldoutFlag === "Y" ? "Sold Out " : ""; + const firstLabelText = firstLabel ? `${firstLabel} ` : ""; + const discountLabel = discountRate ? `${discountRate} discount, ` : ""; + const discountPriceLabel = discountRate + ? `Sale price ${discountedPrice}, ` + : ""; const parsedPrice = parsePrice(originalPrice); const priceLabel = parsedPrice === 0 ? offerInfo ? ` ${offerInfo}` - : '' + : "" : originalPrice ? ` Original price ${originalPrice}, ` - : ''; + : ""; - const productLabel = label || ''; - const lastLabelText = lastLabel || ''; + const productLabel = label || ""; + const lastLabelText = lastLabel || ""; return `${soldOutText}${firstLabelText}${discountLabel}${productName}${discountPriceLabel}${priceLabel}${productLabel}${lastLabelText}`; }, [ @@ -319,7 +353,7 @@ export default memo(function TItemCardNew({ }, [productName]); const handleClosePopup = useCallback(() => { - if (convert?.convertedImage && convert.convertedImage.startsWith('blob:')) { + if (convert?.convertedImage && convert.convertedImage.startsWith("blob:")) { URL.revokeObjectURL(convert.convertedImage); } @@ -338,10 +372,10 @@ export default memo(function TItemCardNew({ setCurrentPdfUrl(pdfUrl); // PNG ์ด๋ฏธ์ง€๋Š” ์ง์ ‘ ํ‘œ์‹œ - if (pdfUrl.endsWith('.png')) { + if (pdfUrl.endsWith(".png")) { // console.log(`๐Ÿ“ธ [EnergyLabel] Displaying PNG directly:`, pdfUrl); dispatch({ - type: 'CONVERT_PDF_TO_IMAGE_SUCCESS', + type: "CONVERT_PDF_TO_IMAGE_SUCCESS", payload: { pdfUrl, imageUrl: pdfUrl }, }); dispatch(setShowPopup(Config.ACTIVE_POPUP.energyPopup)); @@ -358,7 +392,10 @@ export default memo(function TItemCardNew({ pdfUrl, (error, imageUrl) => { if (error) { - console.error('[EnergyLabel] ์ตœ์ข… ๋ณ€ํ™˜ ์‹คํŒจ:', error.message || error); + console.error( + "[EnergyLabel] ์ตœ์ข… ๋ณ€ํ™˜ ์‹คํŒจ:", + error.message || error + ); // ์‹คํŒจํ•ด๋„ ํŒ์—…์€ ์—ด์–ด์„œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ dispatch(setShowPopup(Config.ACTIVE_POPUP.energyPopup)); setTimeout(() => { @@ -386,13 +423,15 @@ export default memo(function TItemCardNew({ className={classNames( css[type], nonPosition && css.nonPosition, - type === 'videoShow' && css[imgType], + type === "videoShow" && css[imgType], className && className )} onBlur={_onBlur} onClick={_onClick} onFocus={_onFocus} - spotlightId={spotlightId ?? 'spotlightId-' + removeDotAndColon(productId)} + spotlightId={ + spotlightId ?? "spotlightId-" + removeDotAndColon(productId) + } aria-label={ariaLabel} role="button" {...rest} @@ -403,7 +442,7 @@ export default memo(function TItemCardNew({ delay={0} src={imageSource} fallbackSrc={ - type === 'videoShow' + type === "videoShow" ? imgType === IMAGETYPES.imgHorizontal ? defaultimgHorizontal : defaultimgVertical @@ -411,24 +450,32 @@ export default memo(function TItemCardNew({ } onError={addDefaultImg} /> - {priceInfo && discountRate && Number(discountRate.replace('%', '')) > 4 && ( - {discountRate} - )} - {soldoutFlag && soldoutFlag === 'Y' && ( -
+ {priceInfo && + discountRate && + Number(discountRate.replace("%", "")) > 4 && ( + {discountRate} + )} + {soldoutFlag && soldoutFlag === "Y" && ( +
{$L(STRING_CONF.SOLD_OUT)}
)} - {isLive && Live Show} + {isLive && ( + Live Show + )}
0 && - euEnrgLblInfos[0]?.enrgLblIcnUrl !== null && + parsePrice(originPrice) >= 1000 && + parsePrice(dcPrice) >= 1000 && css.labelBox )} > @@ -447,14 +494,17 @@ export default memo(function TItemCardNew({ {children} {priceInfo ? (

- {parseFloat(originalPrice?.replace(/[^0-9.-]+/g, '') || '0') === 0 ? ( + {parseFloat(originalPrice?.replace(/[^0-9.-]+/g, "") || "0") === + 0 ? ( {offerInfo} ) : discountRate ? ( discountedPrice ) : ( originalPrice )} - {discountRate && {originalPrice}} + {discountRate && ( + {originalPrice} + )}

) : (

{offerInfo}

@@ -463,7 +513,9 @@ export default memo(function TItemCardNew({ {originPrice && (

{dcPrice ? dcPrice : originPrice} - {dcPrice && {originPrice}} + {dcPrice && ( + {originPrice} + )}

)}
@@ -480,7 +532,9 @@ export default memo(function TItemCardNew({ return null; } energyLabels = euEnrgLblInfos; - } else if (CURRENT_ENERGY_LABEL_MODE === ENERGY_LABEL_MODE.WITH_MOCK) { + } else if ( + CURRENT_ENERGY_LABEL_MODE === ENERGY_LABEL_MODE.WITH_MOCK + ) { if (hasValidApiData) { energyLabels = euEnrgLblInfos; } else { @@ -492,22 +546,23 @@ export default memo(function TItemCardNew({ return (
- {energyLabels - .filter((info, index) => index < 3) - .map((info, index) => ( - onEnergyClick(e, info.enrgLblUrl)} - aria-label={`Energy Efficiency ${info.enrgGrade || ''}`} - > - - - ))} + {type !== "videoShow" && + energyLabels + .filter((info, index) => index < 3) + .map((info, index) => ( + onEnergyClick(e, info.enrgLblUrl)} + aria-label={`Energy Efficiency ${info.enrgGrade || ""}`} + > + + + ))}
); })()} @@ -546,11 +601,11 @@ export default memo(function TItemCardNew({ return (
@@ -566,21 +621,33 @@ export default memo(function TItemCardNew({ ) : convert.error ? (

{$L(STRING_CONF.ENERGY_ERROR)}

-

+

{convert.error?.message || String(convert.error)}

) : convert.isConverting ? (

{$L(STRING_CONF.ENERGY_LOADING)}

-

+

Converting PDF to image... (attempt in progress)

) : (

{$L(STRING_CONF.ENERGY_ERROR)}

-

+

Unknown state - no image or error

@@ -590,7 +657,13 @@ export default memo(function TItemCardNew({ ) : (

{$L(STRING_CONF.ENERGY_ERROR)}

-

+

Convert reducer state not found

diff --git a/com.twin.app.shoptime/src/reducers/forYouReducer.js b/com.twin.app.shoptime/src/reducers/forYouReducer.js index 573bd4bf..c899f5d4 100644 --- a/com.twin.app.shoptime/src/reducers/forYouReducer.js +++ b/com.twin.app.shoptime/src/reducers/forYouReducer.js @@ -13,7 +13,6 @@ import { // }; const initialState = { justForYouInfo: {}, - shelfInfos: {}, }; // const foryouReducer = (state = initialState, action) => { @@ -48,13 +47,8 @@ const justForYouInfo = curry((state, action) => set("justForYouInfo", get("payload", action), state) ); -const shelfInfos = curry((state, action) => - set("shelfInfos", get("payload", action), state) -); - const handlers = { [types.GET_JUSTFORYOU_INFO]: justForYouInfo, - [types.GET_SHELFINFOS]: shelfInfos, }; export const foryouReducer = (state = initialState, action = {}) => { diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx index 644e4f7c..2d6eb242 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx @@ -1,11 +1,21 @@ // src/views/HomePanel/HomeBanner/HomeBanner.jsx -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; -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 { types } from '../../../actions/actionTypes'; @@ -17,9 +27,16 @@ import { setOptionalTermsUserDecision, updateOptionalTermsAgreement, } from '../../../actions/commonActions'; -import { fetchCurrentUserHomeTerms, setDefaultFocus } from '../../../actions/homeActions'; +import { getJustForYouInfo } from '../../../actions/forYouActions'; +import { + fetchCurrentUserHomeTerms, + setDefaultFocus, +} from '../../../actions/homeActions'; import { setMyPageTermsAgree } from '../../../actions/myPageActions'; -import { popPanel, pushPanel } from '../../../actions/panelActions'; +import { + popPanel, + pushPanel, +} from '../../../actions/panelActions'; import { releasePlayControl, requestPlayControl, @@ -29,6 +46,11 @@ import CustomImage from '../../../components/CustomImage/CustomImage'; // import TButtonScroller from "../../../components/TButtonScroller/TButtonScroller"; import OptionalConfirm from '../../../components/Optional/OptionalConfirm'; import TNewPopUp from '../../../components/TPopUp/TNewPopUp'; +import { + useFocusHistory, +} from '../../../hooks/useFocusHistory/useFocusHistory'; +import { useVideoPlay } from '../../../hooks/useVideoPlay/useVideoPlay'; +import { useVideoMove } from '../../../hooks/useVideoTransition/useVideoMove'; import { panel_names } from '../../../utils/Config'; import { $L } from '../../../utils/helperMethods'; import css from './HomeBanner.module.less'; @@ -40,38 +62,53 @@ import Random from './RandomUnit'; import RandomUnitNew from './RandomUnit'; import Rolling from './RollingUnit'; import SimpleVideoContainer from './SimpleVideoContainer'; -import { useFocusHistory } from '../../../hooks/useFocusHistory/useFocusHistory'; -import { useVideoPlay } from '../../../hooks/useVideoPlay/useVideoPlay'; -import { useVideoMove } from '../../../hooks/useVideoTransition/useVideoMove'; -const SpottableComponent = Spottable('div'); -const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); -const ContainerBasic = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); +const SpottableComponent = Spottable("div"); +const Container = SpotlightContainerDecorator( + { enterTo: "last-focused" }, + "div" +); +const ContainerBasic = SpotlightContainerDecorator( + { enterTo: "last-focused" }, + "div" +); -export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, handleShelfFocus }) { +export default function HomeBanner({ + firstSpot, + spotlightId, + handleItemFocus, + handleShelfFocus, +}) { const dispatch = useDispatch(); - const homeTopDisplayInfo = useSelector((state) => state.home.homeTopDisplayInfo); + useEffect(() => { + dispatch(getJustForYouInfo()); + }, [dispatch]); + const homeTopDisplayInfo = useSelector( + (state) => state.home.homeTopDisplayInfo + ); - const bannerDataList = useSelector((state) => state.home.bannerData?.bannerInfos); + const bannerDataList = useSelector( + (state) => state.home.bannerData?.bannerInfos + ); const popupVisible = useSelector((state) => state.common.popup.popupVisible); // ๐Ÿ”ฝ useFocusHistory - ๊ฒฝ๋Ÿ‰ํ™”๋œ ๋ฒ”์šฉ ํฌ์ปค์Šค ํžˆ์Šคํ† ๋ฆฌ const focusHistory = useFocusHistory({ enableLogging: true, useGlobalState: true, - logPrefix: '[HomeBanner-Focus]', + logPrefix: "[HomeBanner-Focus]", }); // ๐Ÿ”ฝ useVideoPlay - ๋™์˜์ƒ ์žฌ์ƒ ์ œ์–ด const videoPlay = useVideoPlay({ enableLogging: true, - logPrefix: '[HomeBanner-VideoPlay]', + logPrefix: "[HomeBanner-VideoPlay]", }); // ๐Ÿ”ฝ useVideoMove - ํฌ์ปค์Šค ์ „ํ™˜ ๊ธฐ๋ฐ˜ ๋™์˜์ƒ ์ œ์–ด const { playByTransition, cleanup } = useVideoMove({ enableLogging: true, - logPrefix: '[HomeBanner-VideoMove]', + logPrefix: "[HomeBanner-VideoMove]", }); const selectTemplate = useMemo(() => { @@ -86,11 +123,19 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha const termsData = useSelector((state) => state.home.termsData); const termsIdMap = useSelector((state) => state.home.termsIdMap); - const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable); + const optionalTermsAvailable = useSelector( + (state) => state.home.optionalTermsAvailable + ); const optionalTermsData = useSelector((state) => { // Chromium68 ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด Optional Chaining ์ œ๊ฑฐ - if (state.home.termsData && state.home.termsData.data && state.home.termsData.data.terms) { - return state.home.termsData.data.terms.find((term) => term.trmsTpCd === 'MST00405'); + if ( + state.home.termsData && + state.home.termsData.data && + state.home.termsData.data.terms + ) { + return state.home.termsData.data.terms.find( + (term) => term.trmsTpCd === "MST00405" + ); } return null; }); @@ -98,22 +143,27 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha const isGnbOpened = useSelector((state) => state.common.isGnbOpened); const currentTermsFlag = useSelector((state) => state.common.termsFlag); // ์„ ํƒ์•ฝ๊ด€ ๋™์˜์—ฌ๋ถ€ - const introTermsAgree = useSelector((state) => state.common.termsFlag.optionalTerms); + const introTermsAgree = useSelector( + (state) => state.common.termsFlag.optionalTerms + ); // ์ƒˆ๋กœ์šด Redux ์ƒํƒœ: ์„ ํƒ์•ฝ๊ด€ ํŒ์—… ํ”Œ๋กœ์šฐ ๊ด€๋ฆฌ - const optionalTermsPopupFlow = useSelector((state) => state.common.optionalTermsPopupFlow); + const optionalTermsPopupFlow = useSelector( + (state) => state.common.optionalTermsPopupFlow + ); //------------------------------------------------------------------------------ // ํŒ์—…ํ‘œ์‹œ ์ƒํƒœ - const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = useState(false); + const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = + useState(false); const [isOptionalTermsVisible, setIsOptionalTermsVisible] = useState(false); const [optionalTermsAgreed, setOptionalTermsAgreed] = useState(false); // ์„ ํƒ์•ฝ๊ด€ ํŒ์—… ํ‘œ์‹œ ์—ฌ๋ถ€ =================================================== const shouldShowOptionalTermsPopup = useMemo(() => { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Step 1: ์ƒํƒœ ํ™•์ธ', { + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] Step 1: ์ƒํƒœ ํ™•์ธ", { termsLoading, isGnbOpened, optionalTermsAvailable, @@ -123,8 +173,8 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha // 1. ๊ธฐ๋ณธ ์กฐ๊ฑด ํ™•์ธ if (termsLoading || isGnbOpened || !optionalTermsAvailable) { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Early return: ๊ธฐ๋ณธ ์กฐ๊ฑด ๋ถˆ๋งŒ์กฑ'); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] Early return: ๊ธฐ๋ณธ ์กฐ๊ฑด ๋ถˆ๋งŒ์กฑ"); } return false; } @@ -135,35 +185,38 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha optionalTermsPopupFlow.userDecision || optionalTermsPopupFlow.agreedInSession ) { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Early return: ์ด๋ฏธ ์ฒ˜๋ฆฌ๋จ', optionalTermsPopupFlow); + if (process.env.NODE_ENV === "development") { + console.log( + "[HomeBanner] Early return: ์ด๋ฏธ ์ฒ˜๋ฆฌ๋จ", + optionalTermsPopupFlow + ); } return false; } // 3. ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ํ™•์ธ const terms = termsData && termsData.data && termsData.data.terms; - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Step 2: termsData ํ™•์ธ', terms); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] Step 2: termsData ํ™•์ธ", terms); } if (!terms) { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Early return: terms๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Œ'); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] Early return: terms๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Œ"); } return false; } - const optionalTerm = terms.find((term) => term.trmsTpCd === 'MST00405'); - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Step 3: optionalTerm ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ', optionalTerm); + const optionalTerm = terms.find((term) => term.trmsTpCd === "MST00405"); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] Step 3: optionalTerm ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ", optionalTerm); } const result = optionalTerm - ? optionalTerm.trmsPopFlag === 'Y' && optionalTerm.trmsAgrFlag === 'N' + ? optionalTerm.trmsPopFlag === "Y" && optionalTerm.trmsAgrFlag === "N" : false; - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] Step 4: ์ตœ์ข… ๊ฒฐ๊ณผ', result); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] Step 4: ์ตœ์ข… ๊ฒฐ๊ณผ", result); } return result; }, [ @@ -177,67 +230,67 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha // ์„ ํƒ์•ฝ๊ด€ ํŒ์—… ํ‘œ์‹œ ์—ฌ๋ถ€ =================================================== const handleOptionalAgree = useCallback(() => { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] handleAgree Click'); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] handleAgree Click"); } if (!termsIdMap || Object.keys(termsIdMap).length === 0) { - if (process.env.NODE_ENV === 'development') { - console.error('[HomeBanner] termsIdMap์ด ์—†์Šต๋‹ˆ๋‹ค:', termsIdMap); + if (process.env.NODE_ENV === "development") { + console.error("[HomeBanner] termsIdMap์ด ์—†์Šต๋‹ˆ๋‹ค:", termsIdMap); } return; } - const requiredTermTypes = ['MST00401', 'MST00402', 'MST00405']; + const requiredTermTypes = ["MST00401", "MST00402", "MST00405"]; const missingTerms = requiredTermTypes.filter((type) => !termsIdMap[type]); if (missingTerms.length > 0) { - if (process.env.NODE_ENV === 'development') { - console.error('[HomeBanner] ๋ˆ„๋ฝ๋œ ์•ฝ๊ด€ ํƒ€์ž…:', missingTerms); + if (process.env.NODE_ENV === "development") { + console.error("[HomeBanner] ๋ˆ„๋ฝ๋œ ์•ฝ๊ด€ ํƒ€์ž…:", missingTerms); } return; } const termsList = []; - if (termsIdMap['MST00401']) { - termsList.push(termsIdMap['MST00401']); // ๊ฐœ์ธ์ •๋ณด์ฒ˜๋ฆฌ๋ฐฉ์นจ + if (termsIdMap["MST00401"]) { + termsList.push(termsIdMap["MST00401"]); // ๊ฐœ์ธ์ •๋ณด์ฒ˜๋ฆฌ๋ฐฉ์นจ } - if (termsIdMap['MST00402']) { - termsList.push(termsIdMap['MST00402']); // ์ด์šฉ์•ฝ๊ด€ + if (termsIdMap["MST00402"]) { + termsList.push(termsIdMap["MST00402"]); // ์ด์šฉ์•ฝ๊ด€ } - if (termsIdMap['MST00405']) { - termsList.push(termsIdMap['MST00405']); // ์„ ํƒ์•ฝ๊ด€ + if (termsIdMap["MST00405"]) { + termsList.push(termsIdMap["MST00405"]); // ์„ ํƒ์•ฝ๊ด€ } const notTermsList = []; - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] ํ˜„์žฌ termsIdMap:', termsIdMap); - console.log('[HomeBanner] ์•ฝ๊ด€ ๋™์˜ API ํ˜ธ์ถœ ํŒŒ๋ผ๋ฏธํ„ฐ:', { + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] ํ˜„์žฌ termsIdMap:", termsIdMap); + console.log("[HomeBanner] ์•ฝ๊ด€ ๋™์˜ API ํ˜ธ์ถœ ํŒŒ๋ผ๋ฏธํ„ฐ:", { termsList, notTermsList, }); } const callback = (response) => { - if (response.retCode === '000' || response.retCode === 0) { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] ์•ฝ๊ด€ ๋™์˜ ์„ฑ๊ณต:', response); + if (response.retCode === "000" || response.retCode === 0) { + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] ์•ฝ๊ด€ ๋™์˜ ์„ฑ๊ณต:", response); } // โœ… IntroPanel๊ณผ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ Redux ์ƒํƒœ ์ง์ ‘ ์—…๋ฐ์ดํŠธ (API ํ˜ธ์ถœ ์—†์ด) dispatch(updateOptionalTermsAgreement(true)); // ๋กœ์ปฌ ์ƒํƒœ๋„ ์—…๋ฐ์ดํŠธ (๊ธฐ์กด ๋กœ์ง ์œ ์ง€) setOptionalTermsAgreed(true); } else { - if (process.env.NODE_ENV === 'development') { - console.error('[HomeBanner] ์•ฝ๊ด€ ๋™์˜ ์‹คํŒจ:', response); + if (process.env.NODE_ENV === "development") { + console.error("[HomeBanner] ์•ฝ๊ด€ ๋™์˜ ์‹คํŒจ:", response); } } }; - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] ์•ฝ๊ด€ ๋™์˜ API ํ˜ธ์ถœ payload:', { + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] ์•ฝ๊ด€ ๋™์˜ API ํ˜ธ์ถœ payload:", { termsList, notTermsList, }); @@ -247,8 +300,8 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha }, [dispatch, termsIdMap]); const handleOptionalTermsClick = useCallback(() => { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] ์•ฝ๊ด€ ์ž์„ธํžˆ ๋ณด๊ธฐ ํด๋ฆญ'); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] ์•ฝ๊ด€ ์ž์„ธํžˆ ๋ณด๊ธฐ ํด๋ฆญ"); } setIsOptionalConfirmVisible(false); setIsOptionalTermsVisible(true); @@ -262,14 +315,14 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha type: types.GET_TERMS_AGREE_YN_SUCCESS, payload: { ...currentTermsFlag, - optionalTerms: 'Y', + optionalTerms: "Y", }, }); }, [handleOptionalAgree]); const handleOptionalDeclineClick = useCallback(() => { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] ๊ฑฐ์ ˆ/๋‹ค์Œ์— ํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ'); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] ๊ฑฐ์ ˆ/๋‹ค์Œ์— ํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ"); } // โœ… ๊ฑฐ์ ˆ ์ƒํƒœ ์—…๋ฐ์ดํŠธ dispatch(updateOptionalTermsAgreement(false)); @@ -280,13 +333,13 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha const handleTermsPopupClosed = useCallback(() => { setIsOptionalTermsVisible(false); setIsOptionalConfirmVisible(true); - Spotlight.focus('optional-confirm-popup'); + Spotlight.focus("optional-confirm-popup"); }, []); // ์„ ํƒ์•ฝ๊ด€ ํŒ์—… Agree const handleTermsPopupAgree = useCallback(() => { - if (process.env.NODE_ENV === 'development') { - console.log('[HomeBanner] handleTermsPopupAgree'); + if (process.env.NODE_ENV === "development") { + console.log("[HomeBanner] handleTermsPopupAgree"); } handleOptionalAgree(); setIsOptionalTermsVisible(false); @@ -306,22 +359,24 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha const data = bannerDataList[i]; let bannerDetailInfos = data.bannerDetailInfos; - if (data.shptmDspyTpNm === 'Random') { + if (data.shptmDspyTpNm === "Random") { if ( - bannerDetailInfos[data.randomIndex].shptmBanrTpNm === 'LIVE' || - bannerDetailInfos[data.randomIndex].shptmBanrTpNm === 'VOD' + bannerDetailInfos[data.randomIndex].shptmBanrTpNm === "LIVE" || + bannerDetailInfos[data.randomIndex].shptmBanrTpNm === "VOD" ) { targetIndex = i; break; } } else if ( - bannerDetailInfos.find((el) => el.shptmBanrTpNm === 'LIVE' || el.shptmBanrTpNm === 'VOD') + bannerDetailInfos.find( + (el) => el.shptmBanrTpNm === "LIVE" || el.shptmBanrTpNm === "VOD" + ) ) { targetIndex = i; break; } } - return 'banner' + targetIndex; + return "banner" + targetIndex; } return null; @@ -336,8 +391,8 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha // ์„ ํƒ ์•ฝ๊ด€ ํŒ์—…์„ ๋„์›Œ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ if (shouldShowOptionalTermsPopup && !isOptionalConfirmVisible) { - console.log('shouldShowOptionalTermsPopup', shouldShowOptionalTermsPopup); - console.log('App.js optionalTermsConfirm ํŒ์—… ํ‘œ์‹œ'); + console.log("shouldShowOptionalTermsPopup", shouldShowOptionalTermsPopup); + console.log("App.js optionalTermsConfirm ํŒ์—… ํ‘œ์‹œ"); const timer = setTimeout(() => { setIsOptionalConfirmVisible(true); @@ -348,36 +403,41 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha // ์ปดํฌ๋„ŒํŠธ ์–ธ๋งˆ์šดํŠธ ์‹œ ํƒ€์ด๋จธ ํด๋ฆฌ์–ด return () => clearTimeout(timer); } - }, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]); + }, [ + shouldShowOptionalTermsPopup, + termsLoading, + isOptionalConfirmVisible, + dispatch, + ]); const renderItem = useCallback( (index, isHorizontal, videoPlayerable = false) => { const data = bannerDataList?.[index] ?? {}; return (
- {data.shptmDspyTpNm === 'Rolling' ? ( + {data.shptmDspyTpNm === "Rolling" ? ( - ) : data.shptmDspyTpNm === 'Random' ? ( + ) : data.shptmDspyTpNm === "Random" ? ( ) : ( - + @@ -403,14 +465,14 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha const data = bannerDataList?.[index] ?? {}; // DSP00201 ๋ ˆ์ด์•„์›ƒ์˜ ๋‘ ๋ฒˆ์งธ ๋ฐฐ๋„ˆ๋Š” ์ƒˆ๋กœ์šด RandomUnitNew๋ฅผ ์‚ฌ์šฉ - if (selectTemplate === 'DSP00201' && index === 1) { + if (selectTemplate === "DSP00201" && index === 1) { return (
@@ -436,8 +498,11 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha } // ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๋งŒ ์žˆ๋Š” ๋ฐฐ๋„ˆ ๋“ฑ ๋‹ค๋ฅธ ์ผ€์ด์Šค ์ฒ˜๋ฆฌ return ( -
- +
+ {/* ... ์ •์  ์ด๋ฏธ์ง€ ๋ Œ๋”๋ง ๋กœ์ง ... */}
@@ -452,7 +517,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha return (
@@ -467,7 +532,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha return (
@@ -478,12 +543,12 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha ); useEffect(() => { - console.log('####introTermsAgree', introTermsAgree); + console.log("####introTermsAgree", introTermsAgree); }, [introTermsAgree]); const renderLayout = useCallback(() => { switch (selectTemplate) { - case 'DSP00201': { + case "DSP00201": { return ( <> @@ -492,14 +557,14 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha {renderItem(2, false, false)} {/* //NOTE - ์•ฝ๊ด€ ๋™์˜ ์—ฌ๋ถ€ & ์ถ”ํ›„ API ๋”ฐ๋ผ ํŒ์—… ํ‘œ์‹œ ์—ฌ๋ถ€ ๊ฒฐ์ • */} - {introTermsAgree === 'Y' ? ( + {introTermsAgree === "Y" ? (
) : ( @@ -508,7 +573,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha ); } - case 'DSP00202': { + case "DSP00202": { return ( <> {renderItem(0, false, false)} @@ -520,7 +585,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha ); } - case 'DSP00203': { + case "DSP00203": { return ( <> {renderItem(0, false, false)} @@ -538,7 +603,11 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha return ( <> - +
{renderLayout()}
{/* ์„ ํƒ์•ฝ๊ด€ ๋™์˜ ํŒ์—… */} @@ -551,19 +620,19 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha onOptionalDeclineClick={handleOptionalDeclineClick} customPosition={true} position={{ - position: 'absolute', - top: '342px', // ๊ฐ€์šด๋ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•œ ์ขŒํ‘œ (1080/2) - 198 - left: '0px', - bottom: 'unset', - transform: 'none', + position: "absolute", + top: "342px", // ๊ฐ€์šด๋ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•œ ์ขŒํ‘œ (1080/2) - 198 + left: "0px", + bottom: "unset", + transform: "none", }} /> {/* ์„ ํƒ์•ฝ๊ด€ ์ž์„ธํžˆ ๋ณด๊ธฐ ํŒ์—… */} { const [showButton, setShowButton] = useState("showButton", true); const cbChangePageRef = useRef(null); - const shelfInfos = useSelector((state) => state.foryou?.shelfInfos); - - useEffect(() => { - dispatch(getJustForYouInfo()); - }, [dispatch]); - - useEffect(() => { - console.log("###shelfInfos updated", shelfInfos); - }, [dispatch, shelfInfos]); + const shelfInfos = useSelector( + (state) => state.foryou?.justForYouInfo?.shelfInfos + ); const onClick = useCallback(() => { dispatch(popPanel(panel_names.JUST_FOR_YOU_TEST_PANEL)); @@ -109,17 +104,23 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => { const handleItemClick = () => { // Extract product ID from contentId if needed - const prdtId = contentId.split("_").pop(); + const tokens = contentId.split("_"); + const patnrId = tokens?.[4] || ""; + const prdtId = tokens?.[5] || ""; dispatch( pushPanel({ name: panel_names.DETAIL_PANEL, - panelInfo: { prdtId: contentId }, + // panelInfo: { prdtId: contentId }, + panelInfo: { + patnrId: patnrId, + prdtId: prdtId, + }, }) ); }; return ( - = 5} @@ -127,7 +128,8 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => { imageSource={thumbnail} label={`${index + 1} of ${productInfos.length}`} lastLabel=" go to detail, button" - priceInfo={{ price, dcPrice }} + dcPrice={dcPrice} + originPrice={price} productName={title} productId={contentId} onClick={handleItemClick}