[foryou] foryou패널 노출관련 처리 및 에너지라벨 노출 처리#1
- homebanner에서 justforyou dispatch처리. - 포유부분 노출 처리 - TITEMCARD videoshow 부분 에너지라벨 미노출 변경. - foryou패널에서 10000자리 넘어가는부분에 대한 스타일 수정 및 금액에따른 스타일변경 처리 변경. - 롤링 배너쪽 미작업
This commit is contained in:
@@ -202,10 +202,10 @@
|
||||
&.labelBox {
|
||||
width: calc(100% - 60px);
|
||||
> p {
|
||||
font-size: 27px;
|
||||
font-size: 25px;
|
||||
&.priceInfo {
|
||||
> span {
|
||||
font-size: 16px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 && (
|
||||
<span className={css.discount}>{discountRate}</span>
|
||||
)}
|
||||
{soldoutFlag && soldoutFlag === 'Y' && (
|
||||
<div className={classNames(css.soldout, countryCode === 'DE' && css.de)}>
|
||||
{priceInfo &&
|
||||
discountRate &&
|
||||
Number(discountRate.replace("%", "")) > 4 && (
|
||||
<span className={css.discount}>{discountRate}</span>
|
||||
)}
|
||||
{soldoutFlag && soldoutFlag === "Y" && (
|
||||
<div
|
||||
className={classNames(
|
||||
css.soldout,
|
||||
countryCode === "DE" && css.de
|
||||
)}
|
||||
>
|
||||
{$L(STRING_CONF.SOLD_OUT)}
|
||||
</div>
|
||||
)}
|
||||
{isLive && <img className={css.liveTag} src={IcLiveShow} alt="Live Show" />}
|
||||
{isLive && (
|
||||
<img className={css.liveTag} src={IcLiveShow} alt="Live Show" />
|
||||
)}
|
||||
</div>
|
||||
<div className={css.flexBox}>
|
||||
<div
|
||||
className={classNames(
|
||||
css.descWrap,
|
||||
catNm && css.hstNmWrap,
|
||||
euEnrgLblInfos &&
|
||||
euEnrgLblInfos.length > 0 &&
|
||||
euEnrgLblInfos[0]?.enrgLblIcnUrl !== null &&
|
||||
parsePrice(originPrice) >= 1000 &&
|
||||
parsePrice(dcPrice) >= 1000 &&
|
||||
css.labelBox
|
||||
)}
|
||||
>
|
||||
@@ -447,14 +494,17 @@ export default memo(function TItemCardNew({
|
||||
{children}
|
||||
{priceInfo ? (
|
||||
<p className={css.priceInfo}>
|
||||
{parseFloat(originalPrice?.replace(/[^0-9.-]+/g, '') || '0') === 0 ? (
|
||||
{parseFloat(originalPrice?.replace(/[^0-9.-]+/g, "") || "0") ===
|
||||
0 ? (
|
||||
<strong>{offerInfo}</strong>
|
||||
) : discountRate ? (
|
||||
discountedPrice
|
||||
) : (
|
||||
originalPrice
|
||||
)}
|
||||
{discountRate && <span className={css.originalPrice}>{originalPrice}</span>}
|
||||
{discountRate && (
|
||||
<span className={css.originalPrice}>{originalPrice}</span>
|
||||
)}
|
||||
</p>
|
||||
) : (
|
||||
<p className={css.offerInfo}>{offerInfo}</p>
|
||||
@@ -463,7 +513,9 @@ export default memo(function TItemCardNew({
|
||||
{originPrice && (
|
||||
<p className={css.priceInfo}>
|
||||
{dcPrice ? dcPrice : originPrice}
|
||||
{dcPrice && <span className={css.originalPrice}>{originPrice}</span>}
|
||||
{dcPrice && (
|
||||
<span className={css.originalPrice}>{originPrice}</span>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -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 (
|
||||
<div className={css.labelImgBox}>
|
||||
{energyLabels
|
||||
.filter((info, index) => index < 3)
|
||||
.map((info, index) => (
|
||||
<SpottableTemp
|
||||
key={index}
|
||||
spotlightDisabled={Boolean(!cursorVisible)}
|
||||
onClick={(e) => onEnergyClick(e, info.enrgLblUrl)}
|
||||
aria-label={`Energy Efficiency ${info.enrgGrade || ''}`}
|
||||
>
|
||||
<CustomImage
|
||||
alt={`Energy Label ${info.enrgGrade || index + 1}`}
|
||||
delay={0}
|
||||
src={info.enrgLblIcnUrl}
|
||||
/>
|
||||
</SpottableTemp>
|
||||
))}
|
||||
{type !== "videoShow" &&
|
||||
energyLabels
|
||||
.filter((info, index) => index < 3)
|
||||
.map((info, index) => (
|
||||
<SpottableTemp
|
||||
key={index}
|
||||
spotlightDisabled={Boolean(!cursorVisible)}
|
||||
onClick={(e) => onEnergyClick(e, info.enrgLblUrl)}
|
||||
aria-label={`Energy Efficiency ${info.enrgGrade || ""}`}
|
||||
>
|
||||
<CustomImage
|
||||
alt={`Energy Label ${info.enrgGrade || index + 1}`}
|
||||
delay={0}
|
||||
src={info.enrgLblIcnUrl}
|
||||
/>
|
||||
</SpottableTemp>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
@@ -546,11 +601,11 @@ export default memo(function TItemCardNew({
|
||||
return (
|
||||
<TPopUp
|
||||
kind="energyPopup"
|
||||
title={$L('Energy Efficiency')}
|
||||
title={$L("Energy Efficiency")}
|
||||
hasText
|
||||
open={popupVisible}
|
||||
hasButton
|
||||
button1Text={$L('CLOSE')}
|
||||
button1Text={$L("CLOSE")}
|
||||
onClose={handleClosePopup}
|
||||
>
|
||||
<div className={css.energyPopupContent}>
|
||||
@@ -566,21 +621,33 @@ export default memo(function TItemCardNew({
|
||||
) : convert.error ? (
|
||||
<div>
|
||||
<p>{$L(STRING_CONF.ENERGY_ERROR)}</p>
|
||||
<p style={{ fontSize: '0.8em', marginTop: '10px' }}>
|
||||
<p style={{ fontSize: "0.8em", marginTop: "10px" }}>
|
||||
{convert.error?.message || String(convert.error)}
|
||||
</p>
|
||||
</div>
|
||||
) : convert.isConverting ? (
|
||||
<div>
|
||||
<p>{$L(STRING_CONF.ENERGY_LOADING)}</p>
|
||||
<p style={{ fontSize: '0.8em', marginTop: '10px', color: '#999' }}>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "0.8em",
|
||||
marginTop: "10px",
|
||||
color: "#999",
|
||||
}}
|
||||
>
|
||||
Converting PDF to image... (attempt in progress)
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<p>{$L(STRING_CONF.ENERGY_ERROR)}</p>
|
||||
<p style={{ fontSize: '0.8em', marginTop: '10px', color: '#999' }}>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "0.8em",
|
||||
marginTop: "10px",
|
||||
color: "#999",
|
||||
}}
|
||||
>
|
||||
Unknown state - no image or error
|
||||
</p>
|
||||
</div>
|
||||
@@ -590,7 +657,13 @@ export default memo(function TItemCardNew({
|
||||
) : (
|
||||
<div>
|
||||
<p>{$L(STRING_CONF.ENERGY_ERROR)}</p>
|
||||
<p style={{ fontSize: '0.8em', marginTop: '10px', color: '#999' }}>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "0.8em",
|
||||
marginTop: "10px",
|
||||
color: "#999",
|
||||
}}
|
||||
>
|
||||
Convert reducer state not found
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -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 = {}) => {
|
||||
|
||||
@@ -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 (
|
||||
<div className={!isHorizontal ? css.imgBox : undefined}>
|
||||
{data.shptmDspyTpNm === 'Rolling' ? (
|
||||
{data.shptmDspyTpNm === "Rolling" ? (
|
||||
<Rolling
|
||||
bannerData={data}
|
||||
isHorizontal={isHorizontal}
|
||||
key={'banner' + index}
|
||||
spotlightId={'banner' + index}
|
||||
key={"banner" + index}
|
||||
spotlightId={"banner" + index}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
handleItemFocus={_handleItemFocus}
|
||||
videoPlayerable={videoPlayerable}
|
||||
/>
|
||||
) : data.shptmDspyTpNm === 'Random' ? (
|
||||
) : data.shptmDspyTpNm === "Random" ? (
|
||||
<Random
|
||||
bannerData={data}
|
||||
isHorizontal={isHorizontal}
|
||||
key={'banner' + index}
|
||||
spotlightId={'banner' + index}
|
||||
key={"banner" + index}
|
||||
spotlightId={"banner" + index}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
handleItemFocus={_handleItemFocus}
|
||||
randomNumber={data.randomIndex}
|
||||
videoPlayerable={videoPlayerable}
|
||||
/>
|
||||
) : (
|
||||
<SpottableComponent spotlightId={'banner' + index}>
|
||||
<SpottableComponent spotlightId={"banner" + index}>
|
||||
<CustomImage
|
||||
delay={0}
|
||||
src={
|
||||
@@ -386,7 +446,9 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
: homeTopDisplayInfo.vtctpImgPath1
|
||||
}
|
||||
aria-label={
|
||||
isHorizontal ? homeTopDisplayInfo.wdthtpImgNm1 : homeTopDisplayInfo.vtctpImgNm1
|
||||
isHorizontal
|
||||
? homeTopDisplayInfo.wdthtpImgNm1
|
||||
: homeTopDisplayInfo.vtctpImgNm1
|
||||
}
|
||||
/>
|
||||
</SpottableComponent>
|
||||
@@ -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 (
|
||||
<div className={!isHorizontal ? css.imgBox : undefined}>
|
||||
<RandomUnitNew
|
||||
bannerData={data}
|
||||
isHorizontal={isHorizontal}
|
||||
key={'banner' + index}
|
||||
spotlightId={'banner' + index}
|
||||
key={"banner" + index}
|
||||
spotlightId={"banner" + index}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
handleItemFocus={_handleItemFocus}
|
||||
randomNumber={data.randomIndex}
|
||||
@@ -420,14 +482,14 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
}
|
||||
|
||||
// 다른 타입의 유닛 렌더링 (예: RollingUnit)
|
||||
if (data.shptmDspyTpNm === 'Rolling') {
|
||||
if (data.shptmDspyTpNm === "Rolling") {
|
||||
return (
|
||||
<div className={!isHorizontal ? css.imgBox : undefined}>
|
||||
<RollingUnit
|
||||
bannerData={data}
|
||||
isHorizontal={isHorizontal}
|
||||
key={'banner' + index}
|
||||
spotlightId={'banner' + index}
|
||||
key={"banner" + index}
|
||||
spotlightId={"banner" + index}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
handleItemFocus={_handleItemFocus}
|
||||
/>
|
||||
@@ -436,8 +498,11 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
}
|
||||
// 기본 이미지만 있는 배너 등 다른 케이스 처리
|
||||
return (
|
||||
<div className={!isHorizontal ? css.imgBox : undefined} key={'banner' + index}>
|
||||
<SpottableComponent spotlightId={'banner' + index}>
|
||||
<div
|
||||
className={!isHorizontal ? css.imgBox : undefined}
|
||||
key={"banner" + index}
|
||||
>
|
||||
<SpottableComponent spotlightId={"banner" + index}>
|
||||
{/* ... 정적 이미지 렌더링 로직 ... */}
|
||||
</SpottableComponent>
|
||||
</div>
|
||||
@@ -452,7 +517,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
return (
|
||||
<div className={!isHorizontal ? css.imgBox : undefined}>
|
||||
<SimpleVideoContainer
|
||||
spotlightId={'banner' + index} // "banner0"
|
||||
spotlightId={"banner" + index} // "banner0"
|
||||
isHorizontal={isHorizontal}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
/>
|
||||
@@ -467,7 +532,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
return (
|
||||
<div className={!isHorizontal ? css.imgBox : undefined}>
|
||||
<SimpleVideoContainer
|
||||
spotlightId={'banner' + index}
|
||||
spotlightId={"banner" + index}
|
||||
isHorizontal={isHorizontal}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
/>
|
||||
@@ -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 (
|
||||
<>
|
||||
<ContainerBasic className={css.smallBox}>
|
||||
@@ -492,14 +557,14 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
</ContainerBasic>
|
||||
{renderItem(2, false, false)}
|
||||
{/* //NOTE - 약관 동의 여부 & 추후 API 따라 팝업 표시 여부 결정 */}
|
||||
{introTermsAgree === 'Y' ? (
|
||||
{introTermsAgree === "Y" ? (
|
||||
<div className={css.imgBox}>
|
||||
<JustForSwitchBanner
|
||||
renderItem={renderItem}
|
||||
handleShelfFocus={_handleShelfFocus}
|
||||
handleItemFocus={_handleItemFocus}
|
||||
isHorizontal={false}
|
||||
spotlightId={'banner3'}
|
||||
spotlightId={"banner3"}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
@@ -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 (
|
||||
<>
|
||||
<Container className={css.container} spotlightId={spotlightId} data-wheel-point={true}>
|
||||
<Container
|
||||
className={css.container}
|
||||
spotlightId={spotlightId}
|
||||
data-wheel-point={true}
|
||||
>
|
||||
<div className={css.homeTemplateBox}>{renderLayout()}</div>
|
||||
</Container>
|
||||
{/* 선택약관 동의 팝업 */}
|
||||
@@ -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",
|
||||
}}
|
||||
/>
|
||||
{/* 선택약관 자세히 보기 팝업 */}
|
||||
<TNewPopUp
|
||||
kind="figmaTermsPopup"
|
||||
open={isOptionalTermsVisible}
|
||||
title={$L('Optional Terms')}
|
||||
text={optionalTermsData?.trmsCntt || ''}
|
||||
title={$L("Optional Terms")}
|
||||
text={optionalTermsData?.trmsCntt || ""}
|
||||
onClose={handleTermsPopupClosed}
|
||||
onAgreeClick={handleTermsPopupAgree}
|
||||
showAgreeButton={true}
|
||||
|
||||
@@ -31,6 +31,7 @@ import TButton, { TYPES } from '../../components/TButton/TButton';
|
||||
import TItemCard, {
|
||||
removeDotAndColon,
|
||||
} from '../../components/TItemCard/TItemCard';
|
||||
import TItemCardNew from '../../components/TItemCard/TItemCard.new';
|
||||
import TPanel from '../../components/TPanel/TPanel';
|
||||
import TVerticalPagenator
|
||||
from '../../components/TVerticalPagenator/TVerticalPagenator';
|
||||
@@ -52,15 +53,9 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
||||
|
||||
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 (
|
||||
<TItemCard
|
||||
<TItemCardNew
|
||||
key={contentId}
|
||||
patnerName={partnerName}
|
||||
data-wheel-point={index >= 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}
|
||||
|
||||
Reference in New Issue
Block a user