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

View File

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

View File

@@ -2,66 +2,15 @@
@import "../../../style/utils.module.less"; @import "../../../style/utils.module.less";
.container { .container {
.flex(@justifyCenter:flex start);
.size(@w: 100%, @h: 180px); .size(@w: 100%, @h: 180px);
padding: 30px 60px; padding: 18px 60px;
background-color: #e7e7e7; background-color: #e7e7e7;
ul { .virtualGridList {
.flex(@justifyCenter: flex-start); overflow: unset;
gap: 18px;
/* normal */ > div {
li { overflow: unset !important;
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");
}
}
} }
} }
} }

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"
]
}