[홈패널] 랜돔 수정 / LIVE, 투데이즈딜, 이미지 배너 컴포넌트 제커

This commit is contained in:
sungmin.in
2024-03-20 20:17:17 +09:00
parent 6df7cc8034
commit d96d030d6f
8 changed files with 358 additions and 900 deletions

View File

@@ -1,186 +0,0 @@
import React, { useCallback, useEffect, useState } from "react";
import classNames from "classnames";
import { useDispatch } from "react-redux";
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import { pushPanel } from "../../../actions/panelActions";
import useScrollReset from "../../../hooks/useScrollReset";
import { panel_names } from "../../../utils/Config";
import css from "../HomeBanner/ImageBannerUnit.module.less";
const SpottableComponent = Spottable("div");
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
export default function ImageBannerUnit({
imageBannerData,
isHorizontal,
spotlightId,
scrollTop,
rolling,
lastIndex,
currentIndex,
getIndex,
rollingStart,
componentsFocus,
indicateFocusId,
}) {
const dispatch = useDispatch();
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
const [focusDown, setFocusDown] = useState(false);
const [indicateId, setIndicateId] = useState("");
const handleClick = useCallback(() => {
let panelName = "";
if (imageBannerData.shptmLnkTpNm === "Featured Brands") {
panelName = panel_names.FEATURED_BRANDS_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "Trending now") {
panelName = panel_names.TRENDING_NOW_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "HOT PICKS") {
panelName = panel_names.HOT_PICKS_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "ON SALE") {
panelName = panel_names.ON_SALE_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "CATEGORY") {
panelName = panel_names.CATEGORY_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "Product Detail") {
panelName = panel_names.DETAIL_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "VOD") {
panelName = panel_names.HOME_PANEL;
} else if (imageBannerData.shptmLnkTpNm === "Show Detail") {
panelName = panel_names.HOME_PANEL;
} else {
panelName = panel_names.HOME_PANEL;
}
// panel_names.DETAIL_PANEL,
dispatch(
pushPanel(
{
name: panelName,
panelInfo: {
patnrId: imageBannerData.patnrId,
prdtId: imageBannerData.prdtId,
},
},
[]
)
);
}, [dispatch, imageBannerData.patnrId, imageBannerData.prdtId]);
const handlePrev = useCallback(() => {
if (currentIndex === 0) {
getIndex(lastIndex);
return;
}
getIndex(currentIndex - 1);
}, [getIndex]);
const handleNext = useCallback(() => {
if (lastIndex === currentIndex) {
getIndex(0);
return;
}
getIndex(currentIndex + 1);
}, [getIndex]);
const onFocus = () => {
handleScrollReset();
rollingStart(true);
};
const onBlur = () => {
setFocusDown(false);
rollingStart(false);
handleStopScrolling();
};
const indicatePrevFocus = () => {
componentsFocus(spotlightId + "Prev");
handleScrollReset();
};
const indicateNextFocus = () => {
componentsFocus(spotlightId + "Next");
handleScrollReset();
};
const indiecateBlur = () => {
handleStopScrolling();
};
const onKeyDown = useCallback(
(event) => {
if (event.key === "ArrowDown") {
setFocusDown(true);
}
},
[focusDown]
);
useEffect(() => {
Spotlight.focus(indicateFocusId);
}, [indicateFocusId]);
return (
<Container
className={classNames(
css.rollingWrap,
isHorizontal && css.isHorizontalWrap
)}
>
{rolling === true && focusDown === true ? (
<div
className={classNames(css.arrow, css.leftBtn)}
onClick={handlePrev}
></div>
) : rolling === true ? (
<SpottableComponent
className={classNames(css.arrow, css.leftBtn)}
onClick={handlePrev}
onFocus={indicatePrevFocus}
onBlur={indiecateBlur}
spotlightId={spotlightId + "Prev"}
/>
) : null}
<SpottableComponent
className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
onClick={handleClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
onKeyDown={onKeyDown}
>
<div className={css.imgBanner}>
<img src={imageBannerData.tmnlImgPath} />
</div>
<p className={css.brandIcon}>
<img src={imageBannerData.patncLogoPath} />
</p>
</SpottableComponent>
{rolling === true && focusDown === true ? (
<div
className={classNames(css.arrow, css.rightBtn)}
onClick={handlePrev}
></div>
) : rolling === true ? (
<SpottableComponent
className={classNames(css.arrow, css.rightBtn)}
onClick={handleNext}
onFocus={indicateNextFocus}
onBlur={indiecateBlur}
spotlightId={spotlightId + "Next"}
/>
) : null}
</Container>
);
}

View File

@@ -1,66 +0,0 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.rollingWrap {
position: relative;
.itemBox {
.size(@w: 486px, @h: 858px);
position: relative;
.imgBanner {
> img {
border-radius: 12px;
.size(@w: 486px, @h: 858px);
}
}
&.isHorizontal {
.size(@w: 744px, @h: 420px);
.imgBanner {
> img {
.size(@w: 744px, @h: 420px);
}
}
}
&:focus {
&::after {
.focused(@boxShadow:22px, @borderRadius: 12px);
}
}
.brandIcon {
overflow: hidden;
position: absolute;
right: 30px;
bottom: 30px;
}
}
.arrow {
z-index: 10;
.size(@w: 42px, @h: 42px);
background-size: 42px 42px;
background-position: center center;
&.leftBtn {
.position(@position: absolute, @top: 429px, @left: 18px);
background-image: url("../../../../assets/images/btn/btn_prev_thumb_nor.png");
&:focus {
background-image: url("../../../../assets/images/btn/btn_prev_thumb_foc.png");
}
}
&.rightBtn {
.position(@position: absolute, @top: 429px, @right: 18px);
background-image: url("../../../../assets/images/btn/btn_next_thumb_nor.png");
&:focus {
background-image: url("../../../../assets/images/btn/btn_next_thumb_foc.png");
}
}
}
&.isHorizontalWrap {
.arrow {
&.leftBtn {
.position(@position: absolute, @top: 189px, @left: 18px);
}
&.rightBtn {
.position(@position: absolute, @top: 189px, @right: 18px);
}
}
}
}

View File

@@ -1,192 +0,0 @@
import React, { useCallback, useEffect, useState } from "react";
import classNames from "classnames";
import { useDispatch } from "react-redux";
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import liveShow from "../../../../assets/images/tag-liveshow.png";
import { pushPanel } from "../../../actions/panelActions";
import TVideoPlayer from "../../../components/TVideoPlayer/TVideoPlayer";
import useScrollReset from "../../../hooks/useScrollReset";
import { panel_names } from "../../../utils/Config";
import css from "./LiveUnit.module.less";
const SpottableComponent = Spottable("div");
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
export default function LiveUnit({
liveData,
isHorizontal,
spotlightId,
scrollTop,
rolling,
lastIndex,
currentIndex,
getIndex,
rollingStart,
componentsFocus,
indicateFocusId,
}) {
const dispatch = useDispatch();
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
const [autoPlay, setAutoPlay] = useState(false);
const [focusDown, setFocusDown] = useState(false);
// 비디오 클릭
const handleClick = useCallback(() => {
dispatch(
pushPanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
playInfo: { url: liveData.showUrl, autoPlay: autoPlay },
},
})
);
}, [liveData, autoPlay, dispatch]);
const handlePrev = useCallback(() => {
if (currentIndex === 0) {
getIndex(lastIndex);
return;
}
getIndex(currentIndex - 1);
}, [getIndex]);
const handleNext = useCallback(() => {
if (lastIndex === currentIndex) {
getIndex(0);
return;
}
getIndex(currentIndex + 1);
}, [getIndex]);
const onFocus = () => {
rollingStart(true);
setAutoPlay(true);
setFocusDown(false);
handleScrollReset();
};
const onBlur = () => {
rollingStart(false);
setAutoPlay(false);
setFocusDown(false);
handleStopScrolling();
};
const indicatePrevFocus = () => {
componentsFocus(spotlightId + "Prev");
handleScrollReset();
};
const indicateNextFocus = () => {
componentsFocus(spotlightId + "Next");
handleScrollReset();
};
const indiecateBlur = () => {
handleStopScrolling();
};
useEffect(() => {
Spotlight.focus(indicateFocusId);
}, [indicateFocusId]);
const onKeyDown = useCallback(
(event) => {
if (event.key === "ArrowDown") {
setFocusDown(true);
}
},
[focusDown]
);
return (
<Container
className={classNames(
css.rollingWrap,
isHorizontal && css.isHorizontalWrap
)}
>
{rolling === true && focusDown === true ? (
<div
className={classNames(css.arrow, css.leftBtn)}
onClick={handlePrev}
></div>
) : rolling === true ? (
<SpottableComponent
className={classNames(css.arrow, css.leftBtn)}
onClick={handlePrev}
onFocus={indicatePrevFocus}
onBlur={indiecateBlur}
spotlightId={spotlightId + "Prev"}
/>
) : null}
<SpottableComponent
className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
onClick={handleClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
onKeyDown={onKeyDown}
>
{liveData.shptmBanrTpNm === "LIVE" ? (
<p className={css.liveIcon}>
<img src={liveShow} />
</p>
) : null}
{autoPlay === false ? (
<div
className={classNames(
css.itemBox,
isHorizontal && css.isHorizontal
)}
>
{liveData.tmnlImgPath !== null ? (
<img src={liveData.tmnlImgPath} />
) : (
""
)}
</div>
) : (
<TVideoPlayer
url={liveData.showUrl}
className={classNames(css.videoMain)}
thumbNail={liveData.tmnlImgPath}
autoPlay={autoPlay}
width={autoPlay === true ? "486" : "744"}
height={autoPlay === true ? "858" : "420"}
/>
)}
<p className={css.brandIcon}>
<img src={liveData.patncLogoPath} />
</p>
</SpottableComponent>
{rolling === true && focusDown === true ? (
<div
className={classNames(css.arrow, css.rightBtn)}
onClick={handlePrev}
></div>
) : rolling === true ? (
<SpottableComponent
className={classNames(css.arrow, css.rightBtn)}
onClick={handleNext}
onFocus={indicateNextFocus}
onBlur={indiecateBlur}
spotlightId={spotlightId + "Next"}
/>
) : null}
</Container>
);
}

View File

@@ -1,91 +0,0 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.videoMain {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
right: 0;
background-color: black;
border-radius: 12px;
video {
width: 100%;
height: 100%;
background-color: transparent;
object-fit: contain;
position: absolute;
}
}
.rollingWrap {
position: relative;
.itemBox {
.size(@w: 486px, @h: 858px);
position: relative;
.imgBanner {
> img {
border-radius: 12px;
.size(@w: 486px, @h: 858px);
}
}
&.isHorizontal {
.size(@w: 744px, @h: 420px);
.imgBanner {
> img {
.size(@w: 744px, @h: 420px);
}
}
}
&:focus {
&::after {
.focused(@boxShadow:22px, @borderRadius: 12px);
}
}
.brandIcon {
overflow: hidden;
position: absolute;
right: 30px;
bottom: 30px;
}
.liveIcon {
z-index: 2;
position: absolute;
left: 18px;
top: 18px;
}
}
.arrow {
z-index: 10;
.size(@w: 42px, @h: 42px);
background-size: 42px 42px;
background-position: center center;
&.leftBtn {
.position(@position: absolute, @top: 429px, @left: 18px);
background-image: url("../../../../assets/images/btn/btn_prev_thumb_nor.png");
&:focus {
background-image: url("../../../../assets/images/btn/btn_prev_thumb_foc.png");
}
}
&.rightBtn {
.position(@position: absolute, @top: 429px, @right: 18px);
background-image: url("../../../../assets/images/btn/btn_next_thumb_nor.png");
&:focus {
background-image: url("../../../../assets/images/btn/btn_next_thumb_foc.png");
}
}
}
&.isHorizontalWrap {
.arrow {
&.leftBtn {
.position(@position: absolute, @top: 189px, @left: 18px);
}
&.rightBtn {
.position(@position: absolute, @top: 189px, @right: 18px);
}
}
}
}

View File

@@ -1,12 +1,25 @@
import React, {
useCallback,
useEffect,
useState,
} from 'react';
import React, { useCallback, useEffect, useState } from "react";
import HomeTodayDeal from '../HomeTodayDeal/HomeTodayDeal';
import ImageBanner from './ImageBannerUnit';
import Live from './LiveUnit';
import classNames from "classnames";
import { useDispatch } from "react-redux";
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import liveShow from "../../../../assets/images/tag-liveshow.png";
import { pushPanel } from "../../../actions/panelActions";
import TVideoPlayer from "../../../components/TVideoPlayer/TVideoPlayer";
import useScrollReset from "../../../hooks/useScrollReset";
import { panel_names } from "../../../utils/Config";
import css from "./RandomUnit.module.less";
const SpottableComponent = Spottable("div");
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
export default function RandomUnit({
bannerData,
@@ -17,59 +30,227 @@ export default function RandomUnit({
const bannerDetailInfos = bannerData.bannerDetailInfos;
const bannerDetailLength = bannerData.bannerDetailInfos.length;
const [startIndex, setStartIndex] = useState(0);
const [lastIndex, setLastIndex] = useState(bannerDetailLength - 1);
const [randomData, setRandomData] = useState([]);
const [onFocus, setOnFocus] = useState(false);
const [autoPlay, setAutoPlay] = useState(false);
const [randomData, setRandomData] = useState("");
// 비디오 처리
const getIndex = useCallback(
(index) => {
setStartIndex(index);
},
[startIndex]
);
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
const getFocus = useCallback(
(focus) => {
setOnFocus(focus);
},
[onFocus]
);
const dispatch = useDispatch();
// 포커스 인
const onFocus = () => {
setAutoPlay(true);
handleScrollReset();
};
// 포커스 아웃
const onBlur = () => {
setAutoPlay(false);
handleStopScrolling();
};
// 투데이즈 딜
// const parsePriceInfo = useCallback((priceInfo) => {
// const priceParts = priceInfo
// .split("|")
// .filter((part) => part !== "N")
// .map((item) => item.trim());
// let originalPrice, discountedPrice, discountRate;
// if (priceParts.length === 4) {
// [originalPrice, discountedPrice, , discountRate] = priceParts;
// } else if (priceParts.length === 2) {
// [originalPrice, discountedPrice] = priceParts;
// discountRate = null;
// } else {
// originalPrice = null;
// discountedPrice = null;
// discountRate = null;
// }
// return { originalPrice, discountedPrice, discountRate };
// }, []);
// const { originalPrice, discountedPrice, discountRate } = parsePriceInfo();
// 이미지 배너 클릭
const imageBannerClick = useCallback(() => {
console.log("이미지 배너 클릭");
let panelName = "";
if (randomData.shptmLnkTpNm === "Featured Brands") {
panelName = panel_names.FEATURED_BRANDS_PANEL;
} else if (randomData.shptmLnkTpNm === "Trending now") {
panelName = panel_names.TRENDING_NOW_PANEL;
} else if (randomData.shptmLnkTpNm === "HOT PICKS") {
panelName = panel_names.HOT_PICKS_PANEL;
} else if (randomData.shptmLnkTpNm === "ON SALE") {
panelName = panel_names.ON_SALE_PANEL;
} else if (randomData.shptmLnkTpNm === "CATEGORY") {
panelName = panel_names.CATEGORY_PANEL;
} else if (randomData.shptmLnkTpNm === "Product Detail") {
panelName = panel_names.DETAIL_PANEL;
} else if (randomData.shptmLnkTpNm === "VOD") {
panelName = panel_names.HOME_PANEL;
} else if (randomData.shptmLnkTpNm === "Show Detail") {
panelName = panel_names.HOME_PANEL;
} else {
panelName = panel_names.HOME_PANEL;
}
dispatch(
pushPanel(
{
name: panelName,
panelInfo: {
patnrId: randomData.patnrId,
prdtId: randomData.prdtId,
},
},
[]
)
);
}, [dispatch, randomData.patnrId, randomData.prdtId]);
// 투데이즈딜 클릭
const todayDealClick = () => {
console.log("파트너ID", randomData.patnrId);
console.log("상품", randomData.prdtId);
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: {
patnrId: randomData.patnrId,
prdtId: randomData.prdtId,
},
})
);
};
// 비디오 클릭
const videoClick = () => {
console.log("비디오");
dispatch(
pushPanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
playInfo: {
url: randomData.showUrl,
autoPlay: autoPlay,
},
},
})
);
};
useEffect(() => {
if (bannerData) {
const leng = bannerDetailInfos.length;
const num = Math.floor(Math.random() * leng);
setRandomData(bannerDetailInfos[num]);
// console.log(randomData.priceInfo);
}
}, [bannerData]);
console.log(randomData.priceInfo);
return (
<>
{randomData.shptmBanrTpNm == "Image Banner" ? (
<ImageBanner
imageBannerData={randomData}
isHorizontal={isHorizontal} // WIDTH = TRUE / FALSE
spotlightId={spotlightId}
scrollTop={scrollTop}
/>
) : randomData.shptmBanrTpNm == "LIVE" ||
randomData.shptmBanrTpNm == "VOD" ? (
<Live
liveData={randomData}
isHorizontal={isHorizontal} // WIDTH = TRUE / FALSE
spotlightId={spotlightId}
scrollTop={scrollTop}
/>
) : randomData.shptmBanrTpNm == "Today's Deals" ? (
<HomeTodayDeal
todayDealData={randomData}
isHorizontal={isHorizontal} // WIDTH = TRUE / FALSE
spotlightId={spotlightId}
scrollTop={scrollTop}
/>
) : null}
<Container
className={classNames(
css.rollingWrap,
isHorizontal && css.isHorizontalWrap
)}
>
{randomData.shptmBanrTpNm == "Image Banner" ? (
<SpottableComponent
className={classNames(
css.itemBox,
isHorizontal && css.isHorizontal
)}
onClick={imageBannerClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
>
<div className={css.imgBanner}>
<img src={randomData.tmnlImgPath} />
</div>
<p className={css.brandIcon}>
<img src={randomData.patncLogoPath} />
</p>
</SpottableComponent>
) : randomData.shptmBanrTpNm == "LIVE" ||
randomData.shptmBanrTpNm == "VOD" ? (
<SpottableComponent
className={classNames(
css.itemBox,
isHorizontal && css.isHorizontal
)}
onClick={videoClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
>
{randomData.shptmBanrTpNm === "LIVE" ? (
<p className={css.liveIcon}>
<img src={liveShow} />
</p>
) : null}
{autoPlay === false ? (
<div
className={classNames(
css.itemBox,
isHorizontal && css.isHorizontal
)}
>
{randomData.tmnlImgPath !== null ? (
<img src={randomData.tmnlImgPath} />
) : null}
</div>
) : (
<TVideoPlayer
url={randomData.showUrl}
className={classNames(css.videoMain)}
thumbNail={randomData.tmnlImgPath}
autoPlay={autoPlay}
width={autoPlay === true ? "486" : "744"}
height={autoPlay === true ? "858" : "420"}
/>
)}
<p className={css.brandIcon}>
<img src={randomData.patncLogoPath} />
</p>
</SpottableComponent>
) : randomData.shptmBanrTpNm == "Today's Deals" ? (
<SpottableComponent
className={classNames(
css.itemBox,
css.todaysDeals,
isHorizontal && css.isHorizontal
)}
onClick={todayDealClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
>
<div>
<div className={css.textBox}>{randomData.prdtNm}</div>
<div className={css.accBox}>{}</div>
{/* {discountedPrice != originalPrice ? (
<span className={css.saleAccBox}>{originalPrice}</span>
) : null} */}
</div>
<div className={css.itemImgBox}>
<img src={randomData.tmnlImgPath} />
</div>
</SpottableComponent>
) : null}
</Container>
</>
);
}

View File

@@ -0,0 +1,129 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.rollingWrap {
position: relative;
.itemBox {
.size(@w: 486px, @h: 858px);
position: relative;
text-align: center;
.textBox {
.size(@w: 100%, @h: 80px);
.elip(@clamp:2);
font-weight: bold;
font-size: 30px;
color: @COLOR_GRAY06;
line-height: 1.27;
margin-bottom: 6px;
}
.accBox {
.size(@w: 100%, @h: 50px);
font-weight: bold;
font-size: 42px;
color: @PRIMARY_COLOR_RED;
line-height: 1.14;
}
.saleAccBox {
font-weight: normal;
font-size: 24px;
color: @COLOR_GRAY04;
vertical-align: middle;
text-decoration: line-through;
margin-left: 9px;
width: 100%;
}
.itemImgBox {
> img {
.size(@w: 354px, @h: 354px);
}
}
.brandIcon {
overflow: hidden;
position: absolute;
right: 30px;
bottom: 30px;
}
.liveIcon {
z-index: 2;
position: absolute;
left: 18px;
top: 18px;
}
.imgBanner {
> img {
border-radius: 12px;
.size(@w: 486px, @h: 858px);
}
}
&.isHorizontal {
.size(@w: 744px, @h: 420px);
.imgBanner {
> img {
.size(@w: 744px, @h: 420px);
}
}
}
&.todaysDeals {
background-image: url(../../../../assets/images/img_home_banner_td_ver.png);
background-size: 486px 858px;
background-position: left top;
border-radius: 12px;
padding: 268px 36px 0;
img {
width: 100%;
object-fit: contain;
}
&.isHorizontal {
background-image: url(../../../../assets/images/img_home_banner_td_hor.png);
background-size: 744px 420px;
background-position: center center;
display: flex;
padding: 0 30px 0 0;
> div {
flex: none;
}
.textBox {
.size(@w: 294px, @h: 80px);
margin: 234px 0 5px 50px;
text-align: left;
}
.accBox {
.size(@w: 320px, @h: 50px);
margin-left: 50px;
text-align: left;
}
.saleAccBox {
color: #767676;
display: block;
text-align: left;
margin: 5px 0 0 55px;
}
.itemImgBox {
margin: 47px 0 0 8px;
> img {
.size(@w: 324px, @h: 324px);
}
}
}
}
&:focus {
&::after {
.focused(@boxShadow:22px, @borderRadius: 12px);
}
}
}
&.isHorizontalWrap {
.arrow {
&.leftBtn {
.position(@position: absolute, @top: 189px, @left: 18px);
}
&.rightBtn {
.position(@position: absolute, @top: 189px, @right: 18px);
}
}
}
}

View File

@@ -1,194 +0,0 @@
import React, { useCallback, useEffect, useState } from "react";
import classNames from "classnames";
import { useDispatch } from "react-redux";
import Spotlight from "@enact/spotlight";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import Spottable from "@enact/spotlight/Spottable";
import { pushPanel } from "../../../actions/panelActions";
import useScrollReset from "../../../hooks/useScrollReset";
import { panel_names } from "../../../utils/Config";
import css from "./HomeTodayDeal.module.less";
const SpottableComponent = Spottable("div");
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
export default function HomeTodayDeal({
todayDealData,
isHorizontal,
spotlightId,
scrollTop,
rolling,
lastIndex,
currentIndex,
getIndex,
rollingStart,
componentsFocus,
indicateFocusId,
}) {
const dispatch = useDispatch();
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
const [focusDown, setFocusDown] = useState(false);
const handleClick = useCallback(() => {
console.log("파트너ID", todayDealData.patnrId);
console.log("상품", todayDealData.prdtId);
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: {
patnrId: todayDealData.patnrId,
prdtId: todayDealData.prdtId,
},
})
);
}, [dispatch, todayDealData.patnrId, todayDealData.prdtId]);
const handlePrev = useCallback(() => {
if (currentIndex === 0) {
getIndex(lastIndex);
return;
}
getIndex(currentIndex - 1);
}, [getIndex]);
const handleNext = useCallback(() => {
if (lastIndex === currentIndex) {
getIndex(0);
return;
}
getIndex(currentIndex + 1);
}, [getIndex]);
const onFocus = useCallback(() => {
rollingStart(true);
handleScrollReset();
}, []);
const onBlur = useCallback(() => {
setFocusDown(false);
rollingStart(false);
handleStopScrolling();
}, []);
const indicatePrevFocus = () => {
componentsFocus(spotlightId + "Prev");
handleScrollReset();
};
const indicateNextFocus = () => {
componentsFocus(spotlightId + "Next");
handleScrollReset();
};
const indiecateBlur = () => {
handleStopScrolling();
};
const onKeyDown = useCallback(
(event) => {
if (event.key === "ArrowDown") {
setFocusDown(true);
}
},
[focusDown]
);
useEffect(() => {
Spotlight.focus(indicateFocusId);
}, [indicateFocusId]);
const parsePriceInfo = useCallback(
(priceInfo) => {
const priceParts = priceInfo
.split("|")
.filter((part) => part !== "N")
.map((item) => item.trim());
let originalPrice, discountedPrice, discountRate;
if (priceParts.length === 4) {
[originalPrice, discountedPrice, , discountRate] = priceParts;
} else if (priceParts.length === 2) {
[originalPrice, discountedPrice] = priceParts;
discountRate = null;
} else {
originalPrice = null;
discountedPrice = null;
discountRate = null;
}
return { originalPrice, discountedPrice, discountRate };
},
[todayDealData.priceInfo]
);
const { originalPrice, discountedPrice, discountRate } = parsePriceInfo(
todayDealData.priceInfo
);
return (
<Container
className={classNames(
css.rollingWrap,
isHorizontal && css.isHorizontalWrap
)}
>
{rolling === true && focusDown === true ? (
<div
className={classNames(css.arrow, css.leftBtn)}
onClick={handlePrev}
></div>
) : rolling === true ? (
<SpottableComponent
className={classNames(css.arrow, css.leftBtn)}
onClick={handlePrev}
onFocus={indicatePrevFocus}
onBlur={indiecateBlur}
spotlightId={spotlightId + "Prev"}
/>
) : null}
<SpottableComponent
className={classNames(css.itemBox, isHorizontal && css.isHorizontal)}
onClick={handleClick}
onFocus={onFocus}
onBlur={onBlur}
spotlightId={spotlightId}
onKeyDown={onKeyDown}
>
<div>
<div className={css.textBox}>{todayDealData.prdtNm}</div>
<div className={css.accBox}>{discountedPrice}</div>
{discountedPrice != originalPrice ? (
<span className={css.saleAccBox}>{originalPrice}</span>
) : null}
</div>
<div className={css.itemImgBox}>
<img src={todayDealData.tmnlImgPath} />
</div>
</SpottableComponent>
{rolling === true && focusDown === true ? (
<div
className={classNames(css.arrow, css.rightBtn)}
onClick={handlePrev}
></div>
) : rolling === true ? (
<SpottableComponent
className={classNames(css.arrow, css.rightBtn)}
onClick={handleNext}
onFocus={indicateNextFocus}
onBlur={indiecateBlur}
spotlightId={spotlightId + "Next"}
/>
) : null}
</Container>
);
}

View File

@@ -1,123 +0,0 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.rollingWrap {
position: relative;
.itemBox {
.size(@w: 486px, @h: 858px);
background-image: url(../../../../assets/images/img_home_banner_td_ver.png);
background-size: 486px 858px;
background-position: left top;
border-radius: 12px;
position: relative;
padding: 268px 36px 0;
img {
width: 100%;
object-fit: contain;
}
text-align: center;
.textBox {
.size(@w: 100%, @h: 80px);
.elip(@clamp:2);
font-weight: bold;
font-size: 30px;
color: @COLOR_GRAY06;
line-height: 1.27;
margin-bottom: 6px;
}
.accBox {
.size(@w: 100%, @h: 50px);
font-weight: bold;
font-size: 42px;
color: @PRIMARY_COLOR_RED;
line-height: 1.14;
}
.saleAccBox {
font-weight: normal;
font-size: 24px;
color: @COLOR_GRAY04;
vertical-align: middle;
text-decoration: line-through;
margin-left: 9px;
width: 100%;
}
.itemImgBox {
> img {
.size(@w: 354px, @h: 354px);
}
}
&.isHorizontal {
.size(@w: 744px, @h: 420px);
background-image: url(../../../../assets/images/img_home_banner_td_hor.png);
background-size: 744px 420px;
background-position: center center;
display: flex;
padding: 0 30px 0 0;
> div {
flex: none;
}
.textBox {
.size(@w: 294px, @h: 80px);
margin: 234px 0 5px 50px;
.elip(@clamp:2);
text-align: left;
}
.accBox {
.size(@w: 320px, @h: 50px);
margin-left: 50px;
text-align: left;
}
.saleAccBox {
color: #767676;
display: block;
text-align: left;
margin: 5px 0 0 55px;
}
.itemImgBox {
margin: 47px 0 0 8px;
> img {
.size(@w: 324px, @h: 324px);
}
}
}
&:focus {
&::after {
.focused(@boxShadow:22px, @borderRadius: 12px);
}
}
}
.arrow {
z-index: 10;
.size(@w: 42px, @h: 42px);
background-size: 42px 42px;
background-position: center center;
&.leftBtn {
.position(@position: absolute, @top: 429px, @left: 18px);
background-image: url("../../../../assets/images/btn/btn_prev_thumb_nor.png");
&:focus {
background-image: url("../../../../assets/images/btn/btn_prev_thumb_foc.png");
}
}
&.rightBtn {
.position(@position: absolute, @top: 429px, @right: 18px);
background-image: url("../../../../assets/images/btn/btn_next_thumb_nor.png");
&:focus {
background-image: url("../../../../assets/images/btn/btn_next_thumb_foc.png");
}
}
}
&.isHorizontalWrap {
.arrow {
&.leftBtn {
.position(@position: absolute, @top: 189px, @left: 18px);
}
&.rightBtn {
.position(@position: absolute, @top: 189px, @right: 18px);
}
}
}
}