[Home] 화면 노출 순서 추가, Template 변경시 데이터 연동

Detail Notes :

1. 관리자에서 홈 컨텐츠 순서 변경 시 변경 안됨
- order 추가하여 변경
2. Template 변경시 데이터 꼬임
- Template 첫번째 레이아웃에만 정상적으로 데이터가 연동이 되며, 다른 레이아웃에서는 데이터가 꼬이는 현상이 있어서 각 레이아웃에 데이터를 연동함
This commit is contained in:
jangheon Pyo
2024-03-22 15:19:12 +09:00
parent 12b64f3ca7
commit 94bdbf0a51
15 changed files with 227 additions and 120 deletions

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useState } from "react";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
@@ -21,7 +21,7 @@ const Container = SpotlightContainerDecorator(
"div"
);
const BestSeller = () => {
const BestSeller = ({ order }) => {
const dispatch = useDispatch();
const bestSellerDatas = useSelector(
(state) => state.product.bestSellerData.bestSeller
@@ -56,8 +56,9 @@ const BestSeller = () => {
)
);
});
const orderStyle = useMemo(() => ({ order: order }), [order]);
return (
<Container className={css.bestSellerWrap}>
<Container className={css.bestSellerWrap} style={orderStyle}>
<SectionTitle title={$L(`BEST SELLER`)} />
<TScroller

View File

@@ -2,8 +2,7 @@
@import "../../../style/utils.module.less";
.bestSellerWrap {
height: 538px;
margin-top: 30px;
height: 512px;
> h2 {
margin-left: 60px;
font-size: 42px;

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useState } from "react";
import React, { useEffect, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
@@ -25,7 +25,7 @@ const ContainerBasic = SpotlightContainerDecorator(
"div"
);
export default function HomeBanner({ scrollTop, selectTemplate }) {
export default function HomeBanner({ scrollTop, selectTemplate, order }) {
const dispatch = useDispatch();
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
@@ -37,20 +37,8 @@ export default function HomeBanner({ scrollTop, selectTemplate }) {
(state) => state.home.mainContentsData.homeTopDisplayInfos[0]
);
const banner01Data = useSelector(
(state) => state.home.bannerData.bannerInfos[0]
);
const banner02Data = useSelector(
(state) => state.home.bannerData.bannerInfos[1]
);
const banner03Data = useSelector(
(state) => state.home.bannerData.bannerInfos[2]
);
const banner04Data = useSelector(
(state) => state.home.bannerData.bannerInfos[3]
const bannerDataList = useSelector(
(state) => state.home.bannerData.bannerInfos
);
const startFocus = () => {
@@ -104,8 +92,35 @@ export default function HomeBanner({ scrollTop, selectTemplate }) {
}, 1000);
}, []);
const templateBanner = (index) => {
switch (selectTemplate) {
case "DSP00201":
return bannerDataList[index];
case "DSP00202":
return index === 2
? bannerDataList[0]
: index === 3
? bannerDataList[3]
: bannerDataList[index + 1];
case "DSP00203":
return index === 2
? bannerDataList[0]
: index === 3
? bannerDataList[1]
: bannerDataList[index + 2];
default:
return bannerDataList[index];
}
};
const firstBanner = templateBanner(0);
const secondBanner = templateBanner(1);
const thirdBanner = templateBanner(2);
const forthBanner = templateBanner(3);
const orderStyle = useMemo(() => ({ order: order }), [order]);
return (
<Container className={css.container} spotlightId={"top"}>
<Container className={css.container} spotlightId={"top"} style={orderStyle}>
<div className={css.homeTemplateBox}>
<ContainerBasic
className={css.smallBox}
@@ -119,16 +134,16 @@ export default function HomeBanner({ scrollTop, selectTemplate }) {
>
{/* 배너1 */}
<div>
{banner01Data.shptmDspyTpNm === "Rolling" ? (
{firstBanner.shptmDspyTpNm === "Rolling" ? (
<Rolling
bannerData={banner01Data}
bannerData={firstBanner}
isHorizontal={true}
spotlightId={"banner01"}
scrollTop={scrollTop}
/>
) : banner01Data.shptmDspyTpNm === "Random" ? (
) : firstBanner.shptmDspyTpNm === "Random" ? (
<Random
bannerData={banner01Data}
bannerData={firstBanner}
isHorizontal={true}
spotlightId={"banner01"}
scrollTop={scrollTop}
@@ -146,16 +161,16 @@ export default function HomeBanner({ scrollTop, selectTemplate }) {
{/* 배너2 */}
<div>
{banner02Data.shptmDspyTpNm === "Rolling" ? (
{secondBanner.shptmDspyTpNm === "Rolling" ? (
<Rolling
bannerData={banner02Data}
bannerData={secondBanner}
isHorizontal={true}
spotlightId={"banner02"}
scrollTop={scrollTop}
/>
) : banner02Data.shptmDspyTpNm === "Random" ? (
) : secondBanner.shptmDspyTpNm === "Random" ? (
<Random
bannerData={banner02Data}
bannerData={secondBanner}
isHorizontal={true}
spotlightId={"banner02"}
scrollTop={scrollTop}
@@ -183,16 +198,16 @@ export default function HomeBanner({ scrollTop, selectTemplate }) {
: { order: 1 }
}
>
{banner03Data.shptmDspyTpNm === "Rolling" ? (
{thirdBanner.shptmDspyTpNm === "Rolling" ? (
<Rolling
bannerData={banner03Data}
bannerData={thirdBanner}
isHorizontal={false}
spotlightId={"banner03"}
scrollTop={scrollTop}
/>
) : banner03Data.shptmDspyTpNm === "Random" ? (
) : thirdBanner.shptmDspyTpNm === "Random" ? (
<Random
bannerData={banner03Data}
bannerData={thirdBanner}
isHorizontal={false}
spotlightId={"banner03"}
scrollTop={scrollTop}
@@ -219,16 +234,16 @@ export default function HomeBanner({ scrollTop, selectTemplate }) {
: { order: 2 }
}
>
{banner04Data.shptmDspyTpNm === "Rolling" ? (
{forthBanner.shptmDspyTpNm === "Rolling" ? (
<Rolling
bannerData={banner04Data}
bannerData={forthBanner}
isHorizontal={false}
spotlightId={"banner04"}
scrollTop={scrollTop}
/>
) : banner04Data.shptmDspyTpNm === "Random" ? (
) : forthBanner.shptmDspyTpNm === "Random" ? (
<Random
bannerData={banner04Data}
bannerData={forthBanner}
isHorizontal={false}
spotlightId={"banner04"}
scrollTop={scrollTop}

View File

@@ -3,6 +3,7 @@
.container {
padding: 24px;
margin-bottom: 26px !important;
.homeTemplateBox {
display: flex;
justify-content: space-between;

View File

@@ -329,7 +329,7 @@ export default function RollingUnit({
spotlightId={spotlightId}
onKeyDown={onKeyDown}
>
<div>
<div className={css.productInfo}>
<div className={css.textBox}>{rollingData[startIndex].prdtNm}</div>
<div className={css.accBox}>{discountedPrice}</div>
{discountedPrice != originalPrice ? (

View File

@@ -7,37 +7,6 @@
.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;
@@ -70,11 +39,39 @@
background-position: left top;
border-radius: 12px;
padding: 268px 36px 0;
img {
width: 100%;
object-fit: contain;
.productInfo {
margin-bottom: 33px;
.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 {
height: 50px;
font-weight: bold;
font-size: 42px;
color: @PRIMARY_COLOR_RED;
line-height: 1.14;
display: inline-block;
}
.saleAccBox {
font-weight: normal;
font-size: 24px;
color: @COLOR_GRAY04;
vertical-align: middle;
text-decoration: line-through;
margin-left: 9px;
}
}
.itemImgBox {
> img {
.size(@w: 354px, @h: 354px);
}
}
&.isHorizontal {
background-image: url(../../../../assets/images/img_home_banner_td_hor.png);
background-size: 744px 420px;
@@ -84,23 +81,26 @@
> div {
flex: none;
}
.textBox {
.size(@w: 294px, @h: 80px);
margin: 234px 0 5px 50px;
text-align: left;
.productInfo {
margin-bottom: 0;
.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;
display: block;
}
.saleAccBox {
color: #767676;
display: block;
text-align: left;
margin: 5px 0 0 55px;
}
}
.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 {

View File

@@ -1,4 +1,4 @@
import React, { useCallback } from "react";
import React, { useCallback, useMemo } from "react";
import { useSelector } from "react-redux";
@@ -15,11 +15,10 @@ const Container = SpotlightContainerDecorator(
"div"
);
const HomeOnSale = ({ ...rest }) => {
const HomeOnSale = ({ order, ...rest }) => {
const homeOnSaleInfos = useSelector(
(state) => state.onSale.onSaleData.data.homeOnSaleInfos
);
const renderItem = useCallback(
({ index, ...rest }) => {
const itemData = homeOnSaleInfos[index];
@@ -35,10 +34,11 @@ const HomeOnSale = ({ ...rest }) => {
},
[homeOnSaleInfos]
);
const orderStyle = useMemo(() => ({ order: order }), [order]);
return (
<Container {...rest} className={css.container}>
<div className={css.bestSeller}>
<Container {...rest} className={css.container} style={orderStyle}>
<div className={css.onSaleWrap}>
<SectionTitle className={css.subTitle} title={$L(`ON SALE`)} />
<div className={css.onSaleItem}>
{homeOnSaleInfos && homeOnSaleInfos.length > 0 && (

View File

@@ -1,8 +1,7 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.bestSeller {
.size(@w: 100%, @h:430px);
padding: 60px 0px 0px 0px;
.onSaleWrap {
.size(@w: 100%, @h:374px);
.subTitle {
margin: 0 0 20px 60px;

View File

@@ -1,10 +1,17 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { useDispatch, useSelector } from "react-redux";
import Spotlight from "@enact/spotlight";
import {
changeAppStatus,
setExitApp,
setHidePopup,
setShowPopup,
@@ -23,18 +30,38 @@ import css from "../HomePanel/HomePanel.module.less";
import PopularShow from "../HomePanel/PopularShow/PopularShow";
import SubCategory from "../HomePanel/SubCategory/SubCategory";
const TEMPLATE_CODE_CONF = {
TOP: "DSP00101",
CATEGORY_ITEM: "DSP00102",
ON_SALE: "DSP00103",
POPULAR_SHOW: "DSP00104",
BEST_SELLER: "DSP00105",
};
const getOrderByValue = (array, value) =>
array.find((obj) => obj["shptmApphmDspyOptCd"] === value)?.expsOrd;
const hasTemplateCodeWithValue = (array, value) =>
Array.isArray(array) &&
array.some(
(obj) =>
Object.prototype.hasOwnProperty.call(obj, "shptmApphmDspyOptCd") &&
obj["shptmApphmDspyOptCd"] === value
);
export default function HomePanel({ isOnTop }) {
const dispatch = useDispatch();
const { getScrollTo, scrollTop } = useScrollTo();
useDebugKey({ isLandingPage: true });
const homeLayoutInfo = useSelector((state) => state.home.layoutData);
const homeTopDisplayInfos = useSelector(
(state) => state.home.mainContentsData.homeTopDisplayInfos
);
const popupVisible = useSelector((state) => state.common.popup.popupVisible);
const isGnbOpened = useSelector((state) => state.common.isGnbOpened);
const [selectTemplate, setSelectTemplate] = useState(null);
const [homeLayoutInfoDetail, setHomeLayoutInfoDetail] = useState([]);
const isGnbOpened = useSelector((state) => state.common.isGnbOpened);
useEffect(() => {
if (homeTopDisplayInfos) {
setSelectTemplate(homeTopDisplayInfos[0].shptmTmplCd);
@@ -76,13 +103,69 @@ export default function HomePanel({ isOnTop }) {
return (
<TPanel className={css.panel} onCancel={onCancel}>
<TBody className={css.tBody} cbScrollTo={getScrollTo}>
{selectTemplate && (
<HomeBanner selectTemplate={selectTemplate} scrollTop={scrollTop} />
{homeLayoutInfo && (
<div className={css.orderableFlexContainer}>
{hasTemplateCodeWithValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.TOP
) &&
selectTemplate && (
<HomeBanner
selectTemplate={selectTemplate}
scrollTop={scrollTop}
order={getOrderByValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.TOP
)}
className={css.homeBannerWrap}
/>
)}
{hasTemplateCodeWithValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.CATEGORY_ITEM
) && (
<SubCategory
order={getOrderByValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.CATEGORY_ITEM
)}
/>
)}
{hasTemplateCodeWithValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.ON_SALE
) && (
<HomeOnSale
order={getOrderByValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.ON_SALE
)}
/>
)}
{hasTemplateCodeWithValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.POPULAR_SHOW
) && (
<PopularShow
order={getOrderByValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.POPULAR_SHOW
)}
/>
)}
{hasTemplateCodeWithValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.BEST_SELLER
) && (
<BestSeller
order={getOrderByValue(
homeLayoutInfoDetail,
TEMPLATE_CODE_CONF.BEST_SELLER
)}
/>
)}
</div>
)}
<SubCategory />
<HomeOnSale />
<PopularShow />
<BestSeller />
<TButton
className={css.tButton}
onClick={handleTopButtonClick}

View File

@@ -6,4 +6,14 @@
}
.tBody {
height: @globalHeight;
.orderableFlexContainer {
display: flex;
flex-direction: column;
> div {
margin-bottom: 70px;
}
}
.tButton {
margin-top: 30px;
}
}

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useState } from "react";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
@@ -24,7 +24,7 @@ const Container = SpotlightContainerDecorator(
"div"
);
const PopularShow = ({ homeChk = true, ...rest }) => {
const PopularShow = ({ homeChk = true, order, ...rest }) => {
const dispatch = useDispatch();
const topInfos = useSelector((state) => state.main.top20ShowData.topInfos);
const [drawChk, setDrawChk] = useState(false);
@@ -46,8 +46,9 @@ const PopularShow = ({ homeChk = true, ...rest }) => {
)
);
});
const orderStyle = useMemo(() => ({ order: order }), [order]);
return (
<Container className={css.popularShow}>
<Container className={css.popularShow} style={orderStyle}>
<SectionTitle className={css.subTitle} title={$L(`POPULAR SHOW`)} />
<TScroller
className={css.showList}

View File

@@ -1,9 +1,9 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.popularShow {
height: 538px;
height: 512px;
> h2 {
margin: 60px 0 0px 60px;
margin: 0 0 0px 60px;
font-size: 42px;
}
.showList {

View File

@@ -2,15 +2,15 @@
@import "../../../../style/utils.module.less";
.container {
.size(@w: 100%, @h:210px);
.size(@w: 100%, @h:186px);
z-index: 10;
background-color: @BG_COLOR_01;
font-weight: bold;
font-size: 28px;
.tVirtualGridList {
height: 210px;
height: 186px;
> div {
height: 210px;
height: 186px;
}
}
}

View File

@@ -5,7 +5,6 @@
/* normal */
position: relative;
.flex(@direction: column);
margin-top: 25px;
color: @COLOR_GRAY08;
text-align: center;

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useState } from "react";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
@@ -23,9 +23,8 @@ const Container = SpotlightContainerDecorator(
"div"
);
const SubCategory = () => {
const SubCategory = ({ order }) => {
const dispatch = useDispatch();
const categoryInfos = useSelector(
(state) => state.onSale.onSaleData.data.categoryInfos
);
@@ -104,9 +103,9 @@ const SubCategory = () => {
setDrawChk(true);
}
}, [currentLgCatCd, dispatch]);
const orderStyle = useMemo(() => ({ order: order }), [order]);
return (
<Container>
<Container style={orderStyle}>
<CategoryNav
categoryInfos={categoryInfos}
currentCategoryCode={currentLgCatCd}