[FeaturedBrandsPanel] QuickMenu, component 변경

Detail Notes :

1. QuickMenu, Scroller → VirtualGridList 변경
2. QuickMenuItem 생성 및 css 수정
This commit is contained in:
younghoon100.park
2024-02-06 14:43:40 +09:00
parent 5110ad9049
commit 2f1b2606df
6 changed files with 214 additions and 126 deletions

View File

@@ -1,11 +1,14 @@
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import Spotlight from "@enact/spotlight";
import {
getBrandLayoutInfo,
getBrandLiveChannelInfo,
} from "../../actions/brandActions";
import TBody from "../../components/TBody/TBody";
import TPanel from "../../components/TPanel/TPanel";
import Banner from "./Banner/Banner";
import css from "./FeaturedBrandsPanel.module.less";
@@ -37,9 +40,16 @@ export default function FeaturedBrandsPanel() {
// @@pyh Todo, provided by GNB as props or global state
const [selectedPatnrId, setSelectedPatnrId] = useState("1");
const handleQuickMenu = (patnrId) => {
setSelectedPatnrId(patnrId);
};
const handleQuickMenuClick = useCallback(
(patnrId) => {
if (selectedPatnrId === patnrId) {
return;
}
setSelectedPatnrId(patnrId);
},
[selectedPatnrId]
);
useEffect(() => {
if (brandInfo) {
@@ -50,32 +60,40 @@ export default function FeaturedBrandsPanel() {
dispatch(getBrandLiveChannelInfo({ patnrId: selectedPatnrId }));
}, [selectedPatnrId]);
useEffect(() => {
if (selectedPatnrId) {
Spotlight.focus("spotlight" + selectedPatnrId);
}
}, [selectedPatnrId]);
return (
/* scenario page 98 */
<TPanel className={css.container}>
{brandInfo && brandInfo.length > 1 && (
<QuickMenu
brandInfo={brandInfo}
onQuickMenuClick={handleQuickMenu}
selectedPatnrId={selectedPatnrId}
/>
)}
{selectedBrandInfo && (
<Banner
selectedBrandInfo={selectedBrandInfo}
brandTopImgInfo={brandTopImgInfo}
/>
)}
<div className={css.sectionContainer}>
{brandChanInfo && (
<LiveChannels
brandChanInfo={brandChanInfo[0]}
brandChannelCnt={brandChannelCnt}
<TBody>
{brandInfo && brandInfo.length > 1 && (
<QuickMenu
brandInfo={brandInfo}
onQuickMenuClick={handleQuickMenuClick}
selectedPatnrId={selectedPatnrId}
/>
)}
</div>
{selectedBrandInfo && brandTopImgInfo && (
<Banner
selectedBrandInfo={selectedBrandInfo}
brandTopImgInfo={brandTopImgInfo}
/>
)}
<div className={css.sectionContainer}>
{brandChanInfo && (
<LiveChannels
brandChanInfo={brandChanInfo[0]}
brandChannelCnt={brandChannelCnt}
/>
)}
</div>
</TBody>
</TPanel>
);
}

View File

@@ -1,64 +1,61 @@
import React, { useEffect } from 'react';
import React, { useCallback, useEffect } from "react";
import Spotlight from '@enact/spotlight';
import SpotlightContainerDecorator
from '@enact/spotlight/SpotlightContainerDecorator';
import Spottable from '@enact/spotlight/Spottable';
import { VirtualGridList } from "@enact/sandstone/VirtualList";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import ri from "@enact/ui/resolution";
import { $L } from '../../../utils/helperMethods';
import css from './QuickMenu.module.less';
import QuickMenuItem from "../QuickMenuItem/QuickMenuItem";
import css from "./QuickMenu.module.less";
const LIST_ITEM_CONF = {
ITEM_WIDTH: 138 * 2,
ITEM_HEIGHT: 138 * 2,
};
const Container = SpotlightContainerDecorator(
{ leaveFor: { right: "" }, enterTo: "last-focused" },
"nav"
);
const SpottableComponent = Spottable("li");
export default function QuickMenu({
brandInfo,
selectedPatnrId,
onQuickMenuClick,
...rest
}) {
const handleClick = (patnrId) => {
if (selectedPatnrId === patnrId) {
return;
}
onQuickMenuClick(patnrId);
};
useEffect(() => {
console.log("@@ brandInfo", brandInfo);
// @@pyh Todo, change to logic
// const element = document.getElementById(selectedPatnrId);
Spotlight.focus("spotlight" + selectedPatnrId);
}, []);
const renderItem = useCallback(
({ index, ...rest }) => {
return (
<QuickMenuItem
brandInfo={brandInfo}
index={index}
selectedPatnrId={selectedPatnrId}
onQuickMenuClick={onQuickMenuClick}
{...rest}
/>
);
},
[brandInfo, selectedPatnrId, onQuickMenuClick]
);
return (
<Container {...rest} className={css.container}>
<ul>
{brandInfo &&
brandInfo.map(({ logoImgAlt, logoImgPath, newFlag, patnrId }) => {
return (
<SpottableComponent
className={patnrId === selectedPatnrId && css.selected}
id={patnrId}
key={patnrId}
onClick={() => handleClick(patnrId)}
spotlightId={"spotlight" + patnrId}
>
{newFlag === "Y" && (
<span className={css.newBagde}>{$L("NEW")}</span>
)}
<span className={css.outline} />
<img src={logoImgPath} alt={logoImgAlt} />
</SpottableComponent>
);
})}
</ul>
<Container className={css.container} {...rest}>
{brandInfo && (
<VirtualGridList
className={css.virtualGridList}
dataSize={brandInfo.length}
direction="horizontal"
horizontalScrollbar="hidden"
itemRenderer={renderItem}
itemSize={{
minWidth: ri.scale(LIST_ITEM_CONF.ITEM_WIDTH),
minHeight: ri.scale(LIST_ITEM_CONF.ITEM_HEIGHT),
}}
noScrollByWheel
scrollMode="translate"
// spacing={ri.scale(LIST_ITEM_CONF.SAPCING)}
/>
)}
</Container>
);
}

View File

@@ -2,66 +2,15 @@
@import "../../../style/utils.module.less";
.container {
.flex(@justifyCenter:flex start);
.size(@w: 100%, @h: 180px);
padding: 30px 60px;
padding: 18px 60px;
background-color: #e7e7e7;
ul {
.flex(@justifyCenter: flex-start);
gap: 18px;
.virtualGridList {
overflow: unset;
/* normal */
li {
position: relative;
.newBagde {
.position(@position: absolute, @top: 0, @right: 0, @bottom: auto, @left: auto);
z-index: 10;
.size(@w: 60px, @h: 30px);
background-color: #f00;
color: #fff;
border-radius: 6px;
font-family: Arial;
font-weight: 600;
font-size: 18px;
text-align: center;
}
.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);
}
/* focused */
&:focus {
border-radius: 60px;
.focusDropShadow();
.outline {
background-image: url("../../../../assets/images/partners/ic-tab-partners-focus@3x.png");
}
img {
.size(@w: 138px, @h: 138px);
}
}
/* selected */
&.selected {
img {
.size(@w: 138px, @h: 138px);
}
.outline {
background-image: url("../../../../assets/images/partners/ic-tab-partners-selected@3x.png");
}
}
> div {
overflow: unset !important;
}
}
}

View File

@@ -0,0 +1,45 @@
import React, { memo, useCallback } from "react";
import classNames from "classnames";
import Spottable from "@enact/spotlight/Spottable";
import { $L } from "../../../utils/helperMethods";
import css from "./QuickMenuItem.module.less";
const SpottableComponent = Spottable("div");
export default memo(function QuickMenuItem({
brandInfo,
index,
onQuickMenuClick,
selectedPatnrId,
...rest
}) {
const { logoImgAlt, logoImgPath, newFlag, patnrId } = brandInfo[index];
const handleClick = useCallback(
(patnrId) => {
onQuickMenuClick && onQuickMenuClick(patnrId);
},
[selectedPatnrId]
);
return (
<SpottableComponent
className={classNames(
css.item,
patnrId === selectedPatnrId && css.selected
)}
id={patnrId}
key={patnrId}
onClick={() => handleClick(patnrId)}
{...rest}
spotlightId={"spotlight" + patnrId}
>
<img src={logoImgPath} alt={logoImgAlt} />
{newFlag === "Y" && <div>{$L("NEW")}</div>}
<span />
</SpottableComponent>
);
});

View File

@@ -0,0 +1,73 @@
@import "../../../style/CommonStyle.module.less";
@import "../../../style/utils.module.less";
.item {
/* normal */
position: relative;
.size(@w: 138px, @h: 138px);
.flex();
// partner logo
img {
.size(@w: 120px, @h: 120px);
}
// newBadge
> div {
.position(@position: absolute, @top: 0, @right: 18px);
z-index: 10;
.size(@w: 60px, @h: 30px);
border-radius: 6px;
background-color: #f00;
.font(@fontFamily: @arialFontBold, @fontSize: 18px);
color: @COLOR_WHITE;
text-align: center;
}
// outline
> span {
.position(@position: absolute, @top: 0, @right: 0, @bottom: 0, @left: 0);
.size(@w: 138px, @h:138px);
background-position: center;
background-size: cover;
}
/* focused */
&:focus-within {
border-radius: 100%;
.focusDropShadow();
// partner logo
img {
.size(@w: 138px, @h: 138px);
}
// newBadge
> div {
right: 0;
}
// outline
> span {
background-image: url("../../../../assets/images/partners/ic-tab-partners-focus@3x.png");
}
}
/* selected */
&.selected {
// partner logo
img {
.size(@w: 138px, @h: 138px);
}
// newBadge
> div {
right: 0;
}
// outline
> span {
background-image: url("../../../../assets/images/partners/ic-tab-partners-selected@3x.png");
}
}
}

View File

@@ -0,0 +1,6 @@
{
"main": "QuickMenuItem.jsx",
"styles": [
"QuickMenuItem.module.less"
]
}