카테고리 브랜드 데이터 전달

This commit is contained in:
고동영
2024-02-06 18:33:50 +09:00
parent 364cf7ce23
commit a7967fa242
6 changed files with 377 additions and 220 deletions

View File

@@ -1,10 +1,4 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import React, { useCallback, useRef, useState } from "react";
import classNames from "classnames";
import compose from "ramda/src/compose";
@@ -25,17 +19,15 @@ const TabItemBase = ({
target,
deActivateTab,
onClick,
lgCatCd,
isSubItem,
onFocus,
path,
isArrow = false,
showSubTab = false,
temp,
setTemp,
...rest
}) => {
const [focused, setFocused] = useState(false);
const [pressed, setPressed] = useState(false);
const itemRef = useRef();
const [fixed, setFixed] = useState(false);
const clearPressedJob = useRef(
new Job((func) => {
setTimeout(func, 100);
@@ -43,7 +35,6 @@ const TabItemBase = ({
);
const _onClick = useCallback(
(ev) => {
setPressed(true);
clearPressedJob.current.start(() => {
if (onClick) {
onClick({ index, target });
@@ -53,26 +44,17 @@ const TabItemBase = ({
[target, index, onClick]
);
useEffect(() => {}, [pressed]);
const _onFocus = useCallback(() => {
setFocused(true);
if (onFocus) {
onFocus(index);
}
}, [index, isArrow]);
}, [index, showSubTab, onFocus]);
const _onBlur = useCallback(() => {
setFocused(false);
setPressed(false);
}, []);
const isDivider = useMemo(() => {
if (!title || !path) {
return false;
}
return true;
}, []);
}, [showSubTab]);
const onKeyDown = useCallback(
(event) => {
@@ -83,30 +65,6 @@ const TabItemBase = ({
[deActivateTab]
);
const ImageComponent = useCallback(() => {
return (
<>
<span className={classNames(css.outline)} />
<img src={path} alt="" />
</>
);
}, [path]);
const TextComponent = useCallback(() => {
return (
<>
{expanded && (
<Marquee
marqueeOn={"focus"}
className={classNames(css.text, isSubItem && css.subItem)}
>
{title}
</Marquee>
)}
</>
);
}, [title]);
const renderIcon = useCallback(() => {
if (icons) {
const Component = icons;
@@ -126,36 +84,35 @@ const TabItemBase = ({
} else {
return null;
}
}, [focused, expanded, selected]);
}, [focused, expanded, selected, fixed]);
delete rest.hasChildren;
delete rest.getChildren;
return (
<SpottableComponent
ref={itemRef}
className={classNames(
css.tabItem,
!path && focused && css.focused,
!isSubItem && focused && isArrow && css.arrow,
path && css.path,
isSubItem && css.subDepth,
!path && !isDivider && selected && css.selected,
focused && path && css.ImgFocus,
selected && css.ImgSelect
focused && css.focused,
showSubTab && fixed && css.fixed,
!isSubItem && focused && showSubTab && css.arrow,
selected && css.selected
)}
onKeyDown={onKeyDown}
onFocus={_onFocus}
onBlur={_onBlur}
onClick={_onClick}
>
<div className={css.layout}>
<div className={classNames(css.itemWrap, focused && css.focused)}>
{icons && <div className={css.icon}>{renderIcon()}</div>}
<div className={classNames(isSubItem && css.subWrap)}>
<span className={css[`category-icon-${lgCatCd}`]} />
{path ? <ImageComponent /> : <TextComponent />}
</div>
{expanded && title && (
<Marquee
className={classNames(css.text, isSubItem && css.subItem)}
marqueeOn={"focus"}
>
{title}
</Marquee>
)}
{/* <TabItemSub /> */}
</div>
</SpottableComponent>
);

View File

@@ -3,11 +3,6 @@
@ICON_SIZE: 48px;
.spottable-next-left {
display:none;
}
.tabItem{
font-size: 36px;
display: flex;
@@ -18,9 +13,6 @@
padding-left: 42px;
padding-right: 24px;
// .spottable-next-left {
// background-color: red;
// }
&.focused {
color: #eee;
@@ -38,72 +30,41 @@
.position(@position: absolute, @top: 24px, @right: 18px);
background-image: url('../../../assets/icons/ic-lnb-right-arrow.png');
background-size: 36px 36px;
} }
> div{
margin-left:-30px;
}
}
}
}
&.selected {
color: #eee;
}
&.subDepth{
width: 386px;
height: 78px;
padding-left: 42px;
&.focused {
background: rgba(255, 255, 255, .1);
border-radius: 0px;
border-right: 6px solid #c70850;
margin-left: 0px;
> div {
padding-left: 30px;
}
}
&.path {
padding-left: 0px;
margin-bottom: 70px;
}
.outline {
.position(@position: absolute, @top: 0, @right: auto, @bottom: auto, @left: 0);
.size(@w: 138px, @h:138px);
&.fixed {
color: #eee;
background: linear-gradient(to right, #cb1253, #e15ba1);
border-radius: 42px;
width: 402px;
z-index: 1;
margin-left: 30px;
position:relative;
&.arrow {
&::after {
content: "";
.size(@w:36px, @h:36px);
.position(@position: absolute, @top: 24px, @right: 18px);
background-image: url('../../../assets/icons/ic-lnb-right-arrow.png');
background-size: 36px 36px;
}
}
background-position: center;
background-size: cover;
}
img {
.size(@w: 120px, @h: 120px);
}
&.ImgFocus {
.outline {
border-radius: 60px;
z-index: 99;
// box-shadow: -3px 0px 30px 0 #c70850;
// border: solid 1px #dadada;
background-image: url("../../../assets/icons/ic-tab-partners-focus@3x.png");
.itemWrap {
display: flex;
&.focused {
margin-left : -30px;
}
img {
.size(@w: 138px, @h: 138px);
}
}
&.ImgSelect {
img {
.size(@w: 138px, @h: 138px);
}
.outline {
background-image: url("../../../assets/icons/ic-tab-partners-lnb-selected@3x.png");
}
}
}
}
.icon {
position: relative;
@@ -135,86 +96,13 @@
width: 245px;
}
}
.layout {
display: flex;
}
.marqueeWrap {
width: 100%;
}
}
.subWrap{
.flex();
span {
.size(@w: 40px, @h:40px);
background-size: cover;
&.category-icon-1017 {
// LG Electronics
background-image: url("../../../assets/category/ic-category-lgelectronics-nor@3x.png");
}
// Garden and Outdoors
&.category-icon-1008 {
background-image: url("../../../assets/icons/ic-category-garden-nor.png");
}
// Fashion
&.category-icon-1000 {
background-image: url("../../../assets/icons/ic-category-fashion-nor.png");
}
// Beauty
&.category-icon-1003 {
background-image: url("../../../assets/icons/ic-category-beauty-nor.png");
}
// Jewelry
&.category-icon-1004 {
background-image: url("../../../assets/icons/ic-category-jewelry-nor.png");
}
// Home
&.category-icon-1006 {
background-image: url("../../../assets/icons/ic-category-home-nor.png");
}
// Kitchen & Food
&.category-icon-1007 {
background-image: url("../../../assets/icons/ic-category-kitchen-nor.png");
}
// Accessories
&.category-icon-1014 {
background-image: url("../../../assets/icons/ic-category-accessories-nor.png");
}
// Heaclth & Fitness
&.category-icon-1009 {
background-image: url("../../../assets/icons/ic-category-health-nor.png");
}
// Entertainment
&.category-icon-1012 {
background-image: url("../../../assets/icons/ic-category-enter-nor.png");
}
// Crafts & Sewing
&.category-icon-1011 {
background-image: url("../../../assets/icons/ic-category-cw-nor.png");
}
// Electronics
&.category-icon-1010 {
background-image: url("../../../assets/icons/ic-category-electronics-nor.png");
}
// Clearance
&.category-icon-1013 {
background-image: url("../../../assets/icons/ic-category-clearance-nor.png");
}
}
}

View File

@@ -0,0 +1,126 @@
import React, { useCallback, useRef, useState } from "react";
import classNames from "classnames";
import compose from "ramda/src/compose";
import { Job } from "@enact/core/util";
import { Marquee, MarqueeController } from "@enact/sandstone/Marquee";
import Spottable from "@enact/spotlight/Spottable";
import css from "./TabItemSub.module.less";
const SpottableComponent = Spottable("div");
const TabItemBase = ({
title,
expanded = false,
selected = false,
index = 0,
target,
deActivateTab,
onClick,
lgCatCd,
isSubItem,
onFocus,
onBlur,
path,
subTitle,
...rest
}) => {
const [focused, setFocused] = useState(false);
const itemRef = useRef();
const clearPressedJob = useRef(
new Job((func) => {
setTimeout(func, 100);
}, 100)
);
const _onClick = useCallback(
(ev) => {
clearPressedJob.current.start(() => {
if (onClick) {
onClick({ index, target });
}
});
},
[target, index, onClick]
);
const _onFocus = useCallback(() => {
setFocused(true);
if (onFocus) {
onFocus(index);
}
}, [index]);
const _onBlur = useCallback(() => {
setFocused(false);
if (onBlur) {
onBlur(index);
}
}, [index]);
const onKeyDown = useCallback(
(event) => {
if (event.key === "ArrowRight") {
_onClick();
}
},
[deActivateTab]
);
const ImageComponent = useCallback(() => {
return (
<div className={css.imageLayout}>
<span className={classNames(css.outline)} />
<img src={path} alt="" />
</div>
);
}, [path]);
const TextComponent = useCallback(() => {
return (
<>
{expanded && (
<Marquee
marqueeOn={"focus"}
className={classNames(css.text, isSubItem && css.subItem)}
>
{title}
</Marquee>
)}
</>
);
}, [title]);
delete rest.hasChildren;
delete rest.getChildren;
return (
<SpottableComponent
ref={itemRef}
className={classNames(
css.tabItem,
!path && focused && css.focused,
path && css.path
// focused && path && css.imageFocus,
// selected && css.imageSelect
)}
onKeyDown={onKeyDown}
onFocus={_onFocus}
onBlur={_onBlur}
onClick={_onClick}
>
<div className={css.layout}>
<div className={classNames(isSubItem && css.subWrap)}>
{!path && <span className={css[`category-icon-${lgCatCd}`]} />}
{path ? <ImageComponent /> : <TextComponent />}
</div>
</div>
</SpottableComponent>
);
};
const ItemDecorator = compose(MarqueeController({ marqueeOnFocus: true }));
const TabItemSub = ItemDecorator(TabItemBase);
export default TabItemSub;

View File

@@ -0,0 +1,166 @@
@import "../../style/utils.module.less";
@import "../../style/CommonStyle.module.less";
@ICON_SIZE: 48px;
.tabItem{
font-size: 36px;
display: flex;
color: #606060;
align-items: center;
height: 84px;
position: relative;
padding-left: 42px;
padding-right: 24px;
&.focused {
background: rgba(255, 255, 255, .1);
border-radius: 0px;
border-right: 6px solid #c70850;
margin-left: 0px;
color: #eee;
}
&.path {
padding-left: 0px;
margin-bottom: 70px;
}
&.selected {
color: #eee;
}
.imageLayout {
&.outline {
.position(@position: absolute, @top: 0, @right: auto, @bottom: auto, @left: 0);
.size(@w: 138px, @h:138px);
background-position: center;
background-size: cover;
> img {
.size(@w: 120px, @h: 120px);
}
}
&.imageFocus {
.outline {
.focusDropShadow();
border-radius: 60px;
z-index: 99;
background-image: url("../../../assets/icons/ic-tab-partners-focus@3x.png");
// box-shadow: -3px 0px 30px 0 #c70850;
// border: solid 1px #dadada;
> img {
.size(@w: 138px, @h: 138px);
}
}
}
// &.ImgSelect {
// img {
// .size(@w: 138px, @h: 138px);
// }
// .outline {
// background-image: url("../../../assets/icons/ic-tab-partners-lnb-selected@3x.png");
// }
// }
}
.text {
line-height: 1.2;
padding-left: 11px;
.font(@fontFamily:@baseFontBold, @fontSize:36px);
&.subItem {
.font (@fontFamily:@baseFontBold, @fontSize:30px);
width: 245px;
}
}
.subWrap{
.flex();
span {
.size(@w: 40px, @h:40px);
background-size: cover;
&.category-icon-1017 {
// LG Electronics
background-image: url("../../../assets/category/ic-category-lgelectronics-nor@3x.png");
}
// Garden and Outdoors
&.category-icon-1008 {
background-image: url("../../../assets/icons/ic-category-garden-nor.png");
}
// Fashion
&.category-icon-1000 {
background-image: url("../../../assets/icons/ic-category-fashion-nor.png");
}
// Beauty
&.category-icon-1003 {
background-image: url("../../../assets/icons/ic-category-beauty-nor.png");
}
// Jewelry
&.category-icon-1004 {
background-image: url("../../../assets/icons/ic-category-jewelry-nor.png");
}
// Home
&.category-icon-1006 {
background-image: url("../../../assets/icons/ic-category-home-nor.png");
}
// Kitchen & Food
&.category-icon-1007 {
background-image: url("../../../assets/icons/ic-category-kitchen-nor.png");
}
// Accessories
&.category-icon-1014 {
background-image: url("../../../assets/icons/ic-category-accessories-nor.png");
}
// Heaclth & Fitness
&.category-icon-1009 {
background-image: url("../../../assets/icons/ic-category-health-nor.png");
}
// Entertainment
&.category-icon-1012 {
background-image: url("../../../assets/icons/ic-category-enter-nor.png");
}
// Crafts & Sewing
&.category-icon-1011 {
background-image: url("../../../assets/icons/ic-category-cw-nor.png");
}
// Electronics
&.category-icon-1010 {
background-image: url("../../../assets/icons/ic-category-electronics-nor.png");
}
// Clearance
&.category-icon-1013 {
background-image: url("../../../assets/icons/ic-category-clearance-nor.png");
}
}
}
.layout {
display: flex;
}
.marqueeWrap {
width: 100%;
}
}

View File

@@ -32,6 +32,7 @@ import OnSaleIcon from "./iconComponents/OnSaleIcon";
import SearchIcon from "./iconComponents/SearchIcon";
import TrendingNowIcon from "./iconComponents/TrendingNowIcon";
import TabItem from "./TabItem";
import TabItemSub from "./TabItemSub";
import css from "./TabLayout.module.less";
const Container = SpotlightContainerDecorator(
@@ -113,7 +114,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
const [mainExpanded, setMainExpanded] = useState(false);
const [mainSelectedIndex, setMainSelectedIndex] = useState(-1);
const [secondDepthReduce, setSecondDepthReduce] = useState(false);
const [focused, setFocused] = useState(false);
const [temp, setTemp] = useState(false);
const [tabs, setTabs] = useState([]);
const [tabFocused, setTabFocused] = useState([false, false, false]); //COLLABSED_MAIN, ACTIVATED_MAIN, ACTIVATED_SUB
const panelSwitching = useRef(null);
@@ -167,6 +168,16 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
result = data?.homeCategory.map((item) => ({
id: item.lgCatCd,
title: item.lgCatNm,
target: [
{
name: panel_names.CATEGORY_PANEL,
panelInfo: {
lgCatNm: item.lgCatNm,
lgCatCd: item.lgCatCd,
COUNT: item.COUNT,
},
},
],
}));
break;
case "GNB":
@@ -179,7 +190,12 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
result = data?.shortFeaturedBrands.map((item) => ({
Id: item.patnrId,
path: item.patncLogoPath,
target: [{ name: panel_names.FEATURED_BRANDS_PANEL }],
target: [
{
name: panel_names.FEATURED_BRANDS_PANEL,
panelInfo: item.patnrId,
},
],
}));
break;
case "My Page":
@@ -309,9 +325,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
switch (type) {
case ACTIVATED_MAIN: {
if (!cursorVisible) {
// setMainExpanded(false);
}
break;
}
case ACTIVATED_SUB: {
@@ -336,16 +350,16 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
);
const onFocus = (index) => {
setFocused(true);
setMainSelectedIndex(index);
setTemp(false);
if (showSubTab) {
setSecondDepthReduce((prev) => !prev);
}
};
const onBlur = () => {
setFocused(false);
};
const onBlur = useCallback(() => {
setTemp(true);
}, []);
const handleNavigation = useCallback(
({ index, target }) => {
@@ -365,6 +379,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
({ index, target }) => {
if (target) {
dispatch(resetPanels(target));
deActivateTab();
panelSwitching.current = true;
panelSwitchingJob.start(panelSwitching);
@@ -376,7 +391,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
({ index, target }) => {
deActivateTabJob.startAfter(100, deActivateTab);
},
[dispatch, deActivateTab]
[deActivateTab]
);
const tabActivated = useMemo(() => {
@@ -433,7 +448,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
}
});
}
}, [secondDepthReduce, showSubTab, focused]);
}, [secondDepthReduce, showSubTab]);
if (!showTab) {
return null;
@@ -485,13 +500,14 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
<TabItem
{...item}
onFocus={onFocus}
onBlur={onBlur}
key={"tabitemExpanded" + index}
onClick={handleNavigation}
deActivateTab={deActivateTab}
isArrow={showSubTab}
showSubTab={showSubTab}
icons={item.icons}
expanded={mainExpanded}
temp={temp}
setTemp={setTemp}
selected={
(panels.length === 0 && index === 0) ||
(Array.isArray(item.target) &&
@@ -521,8 +537,9 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
{showSubTab &&
tabs[mainSelectedIndex]?.children.map((item, index) => {
return (
<TabItem
<TabItemSub
{...item}
onBlur={onBlur}
key={"tabitemSubmenu" + index}
onClick={onClickSubItem}
expanded={true}
@@ -532,7 +549,7 @@ export default function TabLayout({ topPanelName, onTabActivated }) {
title={item.title}
lgCatCd={item.id}
path={item.path}
isArrow={showSubTab}
showSubTab={showSubTab}
// selected={
// (panels.length === 0 && index === 0) ||
// (Array.isArray(item.target) &&

View File

@@ -39,6 +39,7 @@
justify-content: center;
z-index: 1;
flex-grow: 0;
// transition: width 0.5s ease;
> img {
@@ -47,13 +48,15 @@
margin: -40px 24px 84px 42px;
}
&.expanded {
width: 402px;
> img {
width: 234px;
height: 54px;
}
}
&.secondDepthLayout {