[HomePanel]SubCategory 상품 부분 VirtualGridList 적용
- SubCategoryItem생성.
This commit is contained in:
@@ -1,15 +1,19 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
|
import VirtualGridList from "@enact/sandstone/VirtualList";
|
||||||
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 ri from "@enact/ui/resolution";
|
||||||
|
|
||||||
import { getSubCategory } from "../../../actions/mainActions";
|
import { getSubCategory } from "../../../actions/mainActions";
|
||||||
import { getOnSaleInfo } from "../../../actions/onSaleActions";
|
import { getOnSaleInfo } from "../../../actions/onSaleActions";
|
||||||
import TGrid from "../../../components/TGrid/TGrid";
|
import TGrid from "../../../components/TGrid/TGrid";
|
||||||
import TItemCard from "../../../components/TItemCard/TItemCard";
|
import TItemCard from "../../../components/TItemCard/TItemCard";
|
||||||
|
import css from "../../HomePanel/SubCategory/SubCategory.module.less";
|
||||||
import CategoryNav from "../../OnSalePanel/CategoryNav/CategoryNav";
|
import CategoryNav from "../../OnSalePanel/CategoryNav/CategoryNav";
|
||||||
|
import SubCategoryItem from "../SubCategoryItem/SubCategoryItem";
|
||||||
|
|
||||||
const Container = SpotlightContainerDecorator(
|
const Container = SpotlightContainerDecorator(
|
||||||
{
|
{
|
||||||
@@ -25,7 +29,7 @@ const SubCategory = () => {
|
|||||||
const categoryInfos = useSelector(
|
const categoryInfos = useSelector(
|
||||||
(state) => state.onSale.onSaleData.categoryInfos
|
(state) => state.onSale.onSaleData.categoryInfos
|
||||||
);
|
);
|
||||||
const subCategoryData = useSelector(
|
const categoryItemInfos = useSelector(
|
||||||
(state) => state.main.subCategoryData.categoryItemInfos
|
(state) => state.main.subCategoryData.categoryItemInfos
|
||||||
);
|
);
|
||||||
const [currentLgCatCd, setCurrentLgCatCd] = useState();
|
const [currentLgCatCd, setCurrentLgCatCd] = useState();
|
||||||
@@ -58,28 +62,46 @@ const SubCategory = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [currentLgCatCd]);
|
}, [currentLgCatCd]);
|
||||||
|
const renderItem = useCallback(
|
||||||
|
({ index, ...rest }) => {
|
||||||
|
const itemData = categoryItemInfos[index];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SubCategoryItem
|
||||||
|
subCategoryData={categoryItemInfos}
|
||||||
|
currentLgCatCd={currentLgCatCd}
|
||||||
|
itemNum={itemData}
|
||||||
|
key={itemData.rankOrd}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[categoryItemInfos]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<CategoryNav
|
<CategoryNav
|
||||||
categoryInfos={categoryInfos}
|
categoryInfos={categoryInfos}
|
||||||
currentCategoryCode={currentLgCatCd}
|
currentLgCatCd={currentLgCatCd}
|
||||||
onCategoryNavClick={handleCategoryNav}
|
onCategoryNavClick={handleCategoryNav}
|
||||||
type="home"
|
type="home"
|
||||||
/>
|
/>
|
||||||
<TGrid type="home">
|
<TGrid type="home">
|
||||||
{subCategoryData &&
|
{categoryItemInfos && categoryItemInfos.length > 0 && (
|
||||||
subCategoryData.slice(0, 9).map((item) => {
|
<VirtualGridList
|
||||||
return (
|
className={css.virtualGridList}
|
||||||
<TItemCard
|
dataSize={categoryItemInfos.length}
|
||||||
key={item.rankOrd}
|
direction="horizontal"
|
||||||
imageSource={item.imgUrl}
|
horizontalScrollbar="hidden"
|
||||||
imageAlt={item.prdtNm}
|
itemRenderer={renderItem}
|
||||||
productName={item.prdtNm}
|
itemSize={{
|
||||||
priceInfo={item.priceInfo}
|
minWidth: ri.scale(324 * 2),
|
||||||
/>
|
minHeight: ri.scale(438 * 2),
|
||||||
);
|
}}
|
||||||
})}
|
noScrollByWheel
|
||||||
|
scrollMode="translate"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</TGrid>
|
</TGrid>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import React, { useCallback } from "react";
|
||||||
|
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
import Spottable from "@enact/spotlight/Spottable";
|
||||||
|
|
||||||
|
import css from "./SubCategoryItem.module.less";
|
||||||
|
|
||||||
|
const SpottableComponent = Spottable("li");
|
||||||
|
|
||||||
|
export default function SubCategoryItem({
|
||||||
|
subCategoryData,
|
||||||
|
itemNum,
|
||||||
|
currentLgCatCd,
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
const parsePriceInfo = useCallback(
|
||||||
|
(priceInfo) => {
|
||||||
|
const priceParts = itemNum.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 };
|
||||||
|
},
|
||||||
|
[itemNum.priceInfo]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { originalPrice, discountedPrice, discountRate } = parsePriceInfo(
|
||||||
|
itemNum.priceInfo
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<SpottableComponent {...rest} className={css.vertical}>
|
||||||
|
<div>
|
||||||
|
<img src={itemNum.imgUrl} alt={itemNum.prdtNm} />
|
||||||
|
|
||||||
|
{discountRate && <span>{discountRate}</span>}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>{itemNum.prdtNm}</h3>
|
||||||
|
<p>
|
||||||
|
{discountRate ? discountedPrice : originalPrice}
|
||||||
|
{discountRate && <span>{originalPrice}</span>}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</SpottableComponent>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
@import "../../../style/CommonStyle.module.less";
|
||||||
|
@import "../../../style/utils.module.less";
|
||||||
|
.vertical {
|
||||||
|
/* normal */
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
.size(@w: 324px, @h: 438px);
|
||||||
|
padding: 18px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: solid 1px @COLOR_GRAY02;
|
||||||
|
background-color: @COLOR_WHITE;
|
||||||
|
|
||||||
|
// top contents (image contetns)
|
||||||
|
> div:nth-child(1) {
|
||||||
|
position: relative;
|
||||||
|
.size(@w: 288px, @h: 288px);
|
||||||
|
color: @COLOR_WHITE;
|
||||||
|
|
||||||
|
img {
|
||||||
|
.size(@w: 288px, @h: 288px);
|
||||||
|
object-fit: contain;
|
||||||
|
border: solid 1px #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// discount rate
|
||||||
|
span {
|
||||||
|
.position(@position: absolute, @right: 12px, @bottom: 12px);
|
||||||
|
.size(@w: 60px, @h: 60px);
|
||||||
|
border-radius: 60px;
|
||||||
|
background-color: @PRIMARY_COLOR_RED;
|
||||||
|
.font(@fontFamily: "ArialBold", @fontSize:26px);
|
||||||
|
text-align: center;
|
||||||
|
line-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sold out
|
||||||
|
> div:nth-child(3) {
|
||||||
|
.position(@position: absolute, @top: 0, @right: 0);
|
||||||
|
.flex();
|
||||||
|
.size(@w: 288px, @h: 288px);
|
||||||
|
background-color: rgba(26, 26, 26, 0.6);
|
||||||
|
.font(@fontFamily: @baseFontBold, @fontSize: 36px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom contents
|
||||||
|
> div:nth-child(2) {
|
||||||
|
.flex(@direction: column, @alignCenter: flex-start);
|
||||||
|
gap: 6px;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
.font(@fontFamily: @baseFontBold, @fontSize: 24px);
|
||||||
|
color: @COLOR_GRAY06;
|
||||||
|
.elip(@clamp:2);
|
||||||
|
word-break: break-all;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
.flex(@justifyCenter: flex-start);
|
||||||
|
gap: 5px;
|
||||||
|
.font(@fontFamily: @baseFontBold, @fontSize: 30px);
|
||||||
|
color: @PRIMARY_COLOR_RED;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
span {
|
||||||
|
.font(@fontFamily: @baseFont, @fontSize: 18px);
|
||||||
|
color: @COLOR_GRAY04;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* focused */
|
||||||
|
&:focus-within {
|
||||||
|
border: solid 1px @PRIMARY_COLOR_RED;
|
||||||
|
box-shadow: inset 0 0 0 4px @PRIMARY_COLOR_RED,
|
||||||
|
0 0 50px 0 rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
|
// best seller
|
||||||
|
div:nth-child(3) {
|
||||||
|
background-color: @PRIMARY_COLOR_RED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user