[저스트포유 배너 변경]

- 기존 image banner로들어가는부분이 아닌 today deals와 같은 포맷으로 들어가도록 변경.
 - 이미지, 데이터 불러오는부분 추가
This commit is contained in:
junghoon86.park
2025-12-09 13:54:06 +09:00
parent 439e5f46e3
commit 7f7b413aa5
4 changed files with 294 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

View File

@@ -1,23 +1,49 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useDispatch, useSelector } from 'react-redux'; import {
useDispatch,
useSelector,
} from 'react-redux';
import Spotlight from '@enact/spotlight'; import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable'; import Spottable from '@enact/spotlight/Spottable';
import { getContainerId } from '@enact/spotlight/src/container'; import { getContainerId } from '@enact/spotlight/src/container';
import btnPlay from '../../../../assets/images/btn/btn-play-thumb-nor.png'; import btnPlay from '../../../../assets/images/btn/btn-play-thumb-nor.png';
import defaultLogoImg from '../../../../assets/images/ic-tab-partners-default@3x.png'; import defaultLogoImg
import emptyHorImage from '../../../../assets/images/img-home-banner-empty-hor.png'; from '../../../../assets/images/ic-tab-partners-default@3x.png';
import emptyVerImage from '../../../../assets/images/img-home-banner-empty-ver.png'; import emptyHorImage
import defaultImageItem from '../../../../assets/images/img-thumb-empty-product@3x.png'; from '../../../../assets/images/img-home-banner-empty-hor.png';
import emptyVerImage
from '../../../../assets/images/img-home-banner-empty-ver.png';
import defaultImageItem
from '../../../../assets/images/img-thumb-empty-product@3x.png';
import liveShow from '../../../../assets/images/tag-liveshow.png'; import liveShow from '../../../../assets/images/tag-liveshow.png';
import { setBannerIndex, updateHomeInfo } from '../../../actions/homeActions'; import {
import { sendLogTopContents, sendLogTotalRecommend } from '../../../actions/logActions'; setBannerIndex,
import { pushPanel, SOURCE_MENUS } from '../../../actions/panelActions'; updateHomeInfo,
import { startVideoPlayer, finishVideoPreview } from '../../../actions/playActions'; } from '../../../actions/homeActions';
import {
sendLogTopContents,
sendLogTotalRecommend,
} from '../../../actions/logActions';
import {
pushPanel,
SOURCE_MENUS,
} from '../../../actions/panelActions';
import {
finishVideoPreview,
startVideoPlayer,
} from '../../../actions/playActions';
import CustomImage from '../../../components/CustomImage/CustomImage'; import CustomImage from '../../../components/CustomImage/CustomImage';
import usePriceInfo from '../../../hooks/usePriceInfo'; import usePriceInfo from '../../../hooks/usePriceInfo';
import { import {
@@ -27,7 +53,10 @@ import {
LOG_TP_NO, LOG_TP_NO,
panel_names, panel_names,
} from '../../../utils/Config'; } from '../../../utils/Config';
import { $L, formatGMTString } from '../../../utils/helperMethods'; import {
$L,
formatGMTString,
} from '../../../utils/helperMethods';
import { TEMPLATE_CODE_CONF } from '../HomePanel'; import { TEMPLATE_CODE_CONF } from '../HomePanel';
import css from './RollingUnit.module.less'; import css from './RollingUnit.module.less';
@@ -81,6 +110,7 @@ export default function RollingUnit({
const introTermsAgree = useSelector((state) => state.common.optionalTermsAgree); const introTermsAgree = useSelector((state) => state.common.optionalTermsAgree);
const homeCategory = useSelector((state) => state.home.menuData?.data?.homeCategory); const homeCategory = useSelector((state) => state.home.menuData?.data?.homeCategory);
const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd); const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd);
const foryouInfos = useSelector((state) => state.foryou.recommendInfo.recommendProduct);
const { userNumber } = useSelector((state) => state.common.appStatus.loginUserData); const { userNumber } = useSelector((state) => state.common.appStatus.loginUserData);
@@ -333,6 +363,29 @@ export default function RollingUnit({
const { originalPrice, discountedPrice, discountRate, offerInfo } = const { originalPrice, discountedPrice, discountRate, offerInfo } =
usePriceInfo(filteredRollingData.length > 0 ? filteredRollingData[startIndex].priceInfo : {}) || {}; usePriceInfo(filteredRollingData.length > 0 ? filteredRollingData[startIndex].priceInfo : {}) || {};
// Just For You 데이터에서 첫 번째 상품 추출
const justForYouProduct = useMemo(() => {
if (foryouInfos && foryouInfos.length > 0) {
const justForYouShelf = foryouInfos.find(
(shelf) => shelf.recommendTpCd === 'JUSTFORYOU'
);
if (justForYouShelf && justForYouShelf.productInfos && justForYouShelf.productInfos.length > 0) {
return justForYouShelf.productInfos[0];
}
}
return null;
}, [foryouInfos]);
// Just For You 상품의 가격 정보
const justForYouPriceInfo = usePriceInfo(
justForYouProduct && justForYouProduct.priceInfo ? justForYouProduct.priceInfo : ''
) || {
originalPrice: '',
discountedPrice: '',
discountRate: null,
offerInfo: '',
};
const handlePushPanel = useCallback( const handlePushPanel = useCallback(
(name, panelInfo) => { (name, panelInfo) => {
const isDetailPanel = name === panel_names.DETAIL_PANEL; const isDetailPanel = name === panel_names.DETAIL_PANEL;
@@ -582,7 +635,8 @@ export default function RollingUnit({
/> />
) : null} ) : null}
{filteredRollingData && filteredRollingData.length > 0 && filteredRollingData[startIndex].shptmBanrTpNm === 'Image Banner' ? ( {/* 일반 Image Banner (Just For You, Today's Deals 제외) */}
{filteredRollingData && filteredRollingData.length > 0 && filteredRollingData[startIndex].shptmBanrTpNm === 'Image Banner' && filteredRollingData[startIndex].shptmLnkTpNm !== 'Just For You' && filteredRollingData[startIndex].shptmLnkTpNm !== "Today's Deals" ? (
<SpottableComponent <SpottableComponent
className={classNames(css.itemBox, isHorizontal && css.isHorizontal)} className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
onClick={imageBannerClick} onClick={imageBannerClick}
@@ -700,7 +754,7 @@ export default function RollingUnit({
)} )}
</div> </div>
</SpottableComponent> </SpottableComponent>
) : filteredRollingData && filteredRollingData.length > 0 && filteredRollingData[startIndex].shptmBanrTpNm === "Today's Deals" ? ( ) : filteredRollingData && filteredRollingData.length > 0 && (filteredRollingData[startIndex].shptmBanrTpNm === "Today's Deals" || filteredRollingData[startIndex].shptmLnkTpNm === "Today's Deals") ? (
<SpottableComponent <SpottableComponent
className={classNames( className={classNames(
css.itemBox, css.itemBox,
@@ -754,6 +808,75 @@ export default function RollingUnit({
/> />
</div> </div>
</SpottableComponent> </SpottableComponent>
) : filteredRollingData && filteredRollingData.length > 0 && filteredRollingData[startIndex].shptmLnkTpNm === "Just For You" ? (
<SpottableComponent
className={classNames(
css.itemBox,
css.justforyou,
countryCode === 'RU' ? css.ru : '',
countryCode === 'DE' ? css.de : '',
isHorizontal && css.isHorizontal
)}
onClick={imageBannerClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
spotlightDisabled={contentsFocus}
aria-label={
justForYouProduct?.prdtNm
? justForYouProduct.prdtNm
: filteredRollingData[startIndex].tmnlImgNm
}
>
<div className={css.productInfo}>
<div className={css.justforyouTitle}>{$L("Just For You")}</div>
<div
className={css.textBox}
dangerouslySetInnerHTML={{
__html: `${justForYouProduct?.prdtNm || filteredRollingData[startIndex].prdtNm}`,
}}
/>
<div className={css.accBox}>
{justForYouProduct ? (
<>
{parseFloat(justForYouPriceInfo.originalPrice?.replace('$', '') || '0') === 0
? justForYouProduct.offerInfo
: justForYouPriceInfo.discountRate
? justForYouPriceInfo.discountedPrice
: justForYouPriceInfo.originalPrice}
{justForYouPriceInfo.discountRate && !isHorizontal && (
<span className={css.saleAccBox}>{justForYouPriceInfo.originalPrice}</span>
)}
</>
) : (
<>
{parseFloat(originalPrice?.replace('$', '') || '0') === 0
? filteredRollingData[startIndex]?.offerInfo
: discountRate
? discountedPrice
: originalPrice}
{discountRate && !isHorizontal && (
<span className={css.saleAccBox}>{originalPrice}</span>
)}
</>
)}
</div>
{isHorizontal && justForYouProduct && parseFloat(justForYouPriceInfo.originalPrice?.replace('$', '') || '0') !== 0 && (
<span className={css.saleAccBox}>{justForYouPriceInfo.originalPrice}</span>
)}
</div>
<div className={css.itemImgBox}>
<CustomImage
alt=""
delay={0}
animationSpeed="fast"
src={justForYouProduct?.imgUrl || filteredRollingData[startIndex]?.tmnlImgPath}
fallbackSrc={defaultImageItem}
ariaLabel={justForYouProduct?.prdtNm || filteredRollingData[startIndex]?.tmnlImgNm}
/>
</div>
</SpottableComponent>
) : null} ) : null}
{filteredRollingData.length !== 1 ? ( {filteredRollingData.length !== 1 ? (

View File

@@ -237,6 +237,162 @@
left: -4px; left: -4px;
} }
} }
&.justforyou {
background-image: url(../../../../assets/images/img-home-banner-jfy-ver@3x.png);
background-size: 486px 858px;
background-position: left top;
border-radius: 10px;
padding: 75px 51px 0;
&.ru {
.productInfo {
.justforyouTitle {
font-size: 58px;
line-height: 60px;
font-family: @arialFontBold;
}
}
}
&.de {
.productInfo {
.justforyouTitle {
font-size: 74px !important;
line-height: 63px !important;
letter-spacing: -1px !important;
}
}
}
.productInfo {
margin-bottom: 31px;
.justforyouTitle {
.size(@w:100%,@h:132px);
font-family: Arial;
font-weight: bold;
font-size: 80px;
word-break: break-word;
font-stretch: normal;
color: #151515;
text-align: center;
line-height: 76px;
font-family: @arialFontBold;
}
.textBox {
.size(@w: 100%, @h: 80px);
margin-top: 71px;
.elip(@clamp:2);
font-weight: bold;
font-size: 30px;
color: @COLOR_GRAY06;
line-height: 1.27;
margin-bottom: 6px;
}
.accBox {
width: 100%;
text-align: center;
font-weight: bold;
font-size: 42px;
color: @PRIMARY_COLOR_RED;
line-height: 1.14;
display: inline-block;
.elip(@clamp:1);
> strong {
width: 260px;
font-size: 30px;
line-height: 1.27;
display: block;
.elip(@clamp:2);
}
.saleAccBox {
font-weight: normal;
font-size: 24px;
color: @COLOR_GRAY04;
vertical-align: middle;
text-decoration: line-through;
margin-left: 9px;
display: inline-block;
}
}
}
.itemImgBox {
> img {
.size(@w: 356px, @h: 356px);
border-radius: 12px;
border:6px solid #000;
box-sizing: content-box;
}
}
&.isHorizontal {
background-image: url(../../../../assets/images/img-home-banner-jfy-hor@3x.png);
background-size: 744px 420px;
background-position: center center;
display: flex;
padding: 0 30px 0 0;
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
> div {
flex: none;
}
&.ru {
.productInfo {
.justforyouTitle {
font-size: 58px;
line-height: 60px;
font-family: @arialFontBold;
}
}
}
&.de {
.productInfo {
.justforyouTitle {
font-size: 59px !important;
line-height: 63px !important;
letter-spacing: -2px !important;
}
}
}
.productInfo {
margin-bottom: 0;
.justforyouTitle {
.size(@w:305px,@h:114px);
margin-top: 53px;
margin-left: 49px;
font-size: 66px;
word-break: break-word;
color: #151515;
text-align: left;
line-height: 57px;
font-family: @arialBlack;
}
.textBox {
.size(@w: 294px, @h: 80px);
margin: 67px 0 5px 50px;
text-align: left;
}
.accBox {
.size(@w: 320px, @h: 50px);
margin-left: 50px;
text-align: left;
display: block;
.elip(@clamp:1);
}
.saleAccBox {
color: #767676;
display: block;
text-align: left;
margin: 5px 0 0 55px;
text-decoration: line-through;
}
}
.itemImgBox {
.position(@position: absolute, @top: 47px, @left: 389px);
.size(@w: 326px, @h: 326px);
> img {
.size(@w: inherit, @h: inherit);
}
}
}
}
} }
.arrow { .arrow {