[FeaturedBrandsPanel] section CATEGORY, scroll & focus 정책 적용
This commit is contained in:
@@ -25,11 +25,13 @@ import {
|
||||
getBrandTSVInfo,
|
||||
} from "../../actions/brandActions";
|
||||
import { changeAppStatus, setHidePopup } from "../../actions/commonActions";
|
||||
import { updatePanel } from "../../actions/panelActions";
|
||||
import TBody from "../../components/TBody/TBody";
|
||||
import TButton, { TYPES } from "../../components/TButton/TButton";
|
||||
import TPanel from "../../components/TPanel/TPanel";
|
||||
import TPopUp from "../../components/TPopUp/TPopUp";
|
||||
import useScrollTo from "../../hooks/useScrollTo";
|
||||
import { panel_names } from "../../utils/Config";
|
||||
import { $L } from "../../utils/helperMethods";
|
||||
import Banner from "./Banner/Banner";
|
||||
import FeaturedBestSeller from "./FeaturedBestSeller/FeaturedBestSeller";
|
||||
@@ -200,6 +202,7 @@ export default function FeaturedBrandsPanel() {
|
||||
const [selectedCatCdLv1, setSelectedCatCdLv1] = useState();
|
||||
const [selectedCatCdLv2, setSelectedCatCdLv2] = useState();
|
||||
const [targetId, setTargetId] = useState();
|
||||
const [_, setForceUpdate] = useState({});
|
||||
|
||||
const firstFocusableTargetId = useRef();
|
||||
const getFirstFocusableTargetIdJob = useRef(
|
||||
@@ -253,11 +256,23 @@ export default function FeaturedBrandsPanel() {
|
||||
|
||||
useEffect(() => {
|
||||
if (panelInfo) {
|
||||
scrollTopBody({ animate: false });
|
||||
setSelectedPatnrId(panelInfo);
|
||||
console.log("pyh panelInfo", panelInfo);
|
||||
console.log("pyh panelInfo.length", Object.keys(panelInfo).length);
|
||||
|
||||
if (Object.keys(panelInfo).length > 1) {
|
||||
setSelectedBrandInfo(
|
||||
findItemByValue(panelInfo.brandInfo, panelInfo.patnrId)
|
||||
);
|
||||
setTargetId(panelInfo.targetId);
|
||||
// pyh Todo, edit, scroll timing
|
||||
queueMicrotask(() => scrollTopBody({ y: panelInfo.y, animate: false }));
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedPatnrId(panelInfo?.patnrId);
|
||||
setTargetId("spotlightId-" + panelInfo);
|
||||
}
|
||||
}, [panelInfo]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!brandInfo) {
|
||||
@@ -276,38 +291,33 @@ export default function FeaturedBrandsPanel() {
|
||||
}, [brandInfo, targetId]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
getFirstFocusableTargetIdJob.current.stop();
|
||||
focusJob.current.stop();
|
||||
};
|
||||
}, []);
|
||||
if (brandInfo) {
|
||||
if (selectedPatnrId) {
|
||||
setSelectedBrandInfo(findItemByValue(brandInfo, selectedPatnrId));
|
||||
setSelectedCatCd();
|
||||
setSelectedHstNm();
|
||||
setSelectedSeriesId();
|
||||
setSelectedCatCdLv1();
|
||||
setSelectedCatCdLv2();
|
||||
|
||||
useEffect(() => {
|
||||
if (brandInfo && selectedPatnrId) {
|
||||
setSelectedBrandInfo(findItemByValue(brandInfo, selectedPatnrId));
|
||||
setSelectedCatCd();
|
||||
setSelectedHstNm();
|
||||
setSelectedSeriesId();
|
||||
setSelectedCatCdLv1();
|
||||
setSelectedCatCdLv2();
|
||||
|
||||
dispatch(getBrandLayoutInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandLiveChannelInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandTSVInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandBestSeller({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandRecommendedShowInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandCreatorsInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandSeriesInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(
|
||||
getBrandCategoryInfo({
|
||||
patnrId: selectedPatnrId,
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
getBrandShowroom({
|
||||
patnrId: selectedPatnrId,
|
||||
})
|
||||
);
|
||||
dispatch(getBrandLayoutInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandLiveChannelInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandTSVInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandBestSeller({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandRecommendedShowInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandCreatorsInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(getBrandSeriesInfo({ patnrId: selectedPatnrId }));
|
||||
dispatch(
|
||||
getBrandCategoryInfo({
|
||||
patnrId: selectedPatnrId,
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
getBrandShowroom({
|
||||
patnrId: selectedPatnrId,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [brandInfo, dispatch, selectedPatnrId]);
|
||||
|
||||
@@ -344,17 +354,39 @@ export default function FeaturedBrandsPanel() {
|
||||
}
|
||||
}, [selectedSeriesId, dispatch]);
|
||||
|
||||
// pyh Todo, scroll issue
|
||||
useEffect(() => {
|
||||
if (selectedCatCdLv1 === "") {
|
||||
dispatch(
|
||||
getBrandLayoutInfo({
|
||||
patnrId: selectedPatnrId,
|
||||
catCdLv1: selectedCatCdLv1,
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [dispatch, selectedCatCdLv1]);
|
||||
setForceUpdate({});
|
||||
}, [selectedCatCdLv1, selectedCatCdLv2]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (brandInfo) {
|
||||
console.log("pyh -------------------- unmounted --------------------");
|
||||
const marker = document.querySelector(`[data-marker="scroll-marker"]`);
|
||||
const lastFocusedTarget = Spotlight.getCurrent();
|
||||
|
||||
if (marker && lastFocusedTarget) {
|
||||
const targetId = lastFocusedTarget.getAttribute("data-spotlight-id");
|
||||
|
||||
const markerRect = marker.getBoundingClientRect();
|
||||
const lastFocusedTargetRect =
|
||||
lastFocusedTarget.getBoundingClientRect();
|
||||
|
||||
const y = lastFocusedTargetRect.top - markerRect.top;
|
||||
|
||||
dispatch(
|
||||
updatePanel({
|
||||
name: panel_names.FEATURED_BRANDS_PANEL,
|
||||
panelInfo: { ...panelInfo, brandInfo, targetId, y },
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getFirstFocusableTargetIdJob.current.stop();
|
||||
focusJob.current.stop();
|
||||
}
|
||||
};
|
||||
}, [brandInfo]);
|
||||
|
||||
const handleTopButtonClick = useCallback(() => {
|
||||
if (!firstFocusableTargetId.current) {
|
||||
@@ -381,7 +413,6 @@ export default function FeaturedBrandsPanel() {
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
/* scenario page 98 */
|
||||
<TPanel className={css.tPanel}>
|
||||
<TBody className={css.tBody} cbScrollTo={getScrollToBody}>
|
||||
<div data-marker="scroll-marker" />
|
||||
|
||||
@@ -101,6 +101,7 @@ export default memo(function FeaturedCategory({
|
||||
brandCategoryProductDetailInfoItem={
|
||||
brandCategoryProductDetailInfoItem
|
||||
}
|
||||
index={index}
|
||||
isCarousel={array.length > 1}
|
||||
key={"brand-category-product-info-" + index}
|
||||
scrollTopBody={scrollTopBody}
|
||||
|
||||
@@ -13,6 +13,7 @@ const Container = SpotlightContainerDecorator(
|
||||
|
||||
export default function FeaturedCategoryContents({
|
||||
brandCategoryProductDetailInfoItem,
|
||||
index,
|
||||
isCarousel,
|
||||
scrollTopBody,
|
||||
selectedPatnrId,
|
||||
@@ -22,11 +23,12 @@ export default function FeaturedCategoryContents({
|
||||
|
||||
return (
|
||||
<Container className={css.container}>
|
||||
<h3 data-subtitle={catNm}>{catNm}</h3>
|
||||
<h3 data-category-subtitle-index={index}>{catNm}</h3>
|
||||
{isCarousel ? (
|
||||
<FeaturedCategoryProductList
|
||||
brandCategoryProductDetailInfo={brandCategoryProductDetailInfo}
|
||||
catNm={catNm}
|
||||
index={index}
|
||||
patnrId={patnrId}
|
||||
scrollTopBody={scrollTopBody}
|
||||
selectedPatnrId={selectedPatnrId}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
.container {
|
||||
> h3 {
|
||||
margin: 36px 0 12px;
|
||||
margin-top: 14px;
|
||||
padding-left: 60px;
|
||||
font-weight: bold;
|
||||
font-size: 36px;
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
@import "../../../../../style/utils.module.less";
|
||||
|
||||
.container {
|
||||
padding-left: 60px;
|
||||
|
||||
ul {
|
||||
.flex(@justifyCenter: flex-start);
|
||||
flex-wrap: wrap;
|
||||
padding: 22px 0 0 60px;
|
||||
|
||||
li {
|
||||
margin: 0 18px 15px 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
|
||||
import { pushPanel } from "../../../../../actions/panelActions";
|
||||
import TItemCard from "../../../../../components/TItemCard/TItemCard";
|
||||
import TVirtualGridList from "../../../../../components/TVirtualGridList/TVirtualGridList";
|
||||
import TScroller from "../../../../../components/TScroller/TScroller";
|
||||
import useScrollTo from "../../../../../hooks/useScrollTo";
|
||||
import { panel_names } from "../../../../../utils/Config";
|
||||
import css from "./FeaturedCategoryProductList.module.less";
|
||||
@@ -17,6 +17,7 @@ import css from "./FeaturedCategoryProductList.module.less";
|
||||
export default memo(function FeaturedCategoryProductList({
|
||||
brandCategoryProductDetailInfo,
|
||||
catNm,
|
||||
index,
|
||||
patnrId,
|
||||
scrollTopBody,
|
||||
selectedPatnrId,
|
||||
@@ -43,81 +44,79 @@ export default memo(function FeaturedCategoryProductList({
|
||||
|
||||
const setScrollTopBody = useCallback(() => {
|
||||
const marker = document.querySelector(`[data-marker="scroll-marker"]`);
|
||||
const sectionTitle = document.querySelector(`[data-subtitle="${catNm}"]`);
|
||||
const subTitle = document.querySelector(
|
||||
`[data-category-subtitle-index="${index}"]`
|
||||
);
|
||||
|
||||
if (marker && sectionTitle) {
|
||||
if (marker && subTitle) {
|
||||
const markerRect = marker.getBoundingClientRect();
|
||||
const sectionTitleRect = sectionTitle.getBoundingClientRect();
|
||||
const subTitleRect = subTitle.getBoundingClientRect();
|
||||
const subSectionGap = 36;
|
||||
|
||||
const y = sectionTitleRect.top - markerRect.top;
|
||||
const y = subTitleRect.top - markerRect.top - subSectionGap;
|
||||
|
||||
timeoutRef.current = setTimeout(() => scrollTopBody({ y }));
|
||||
} else {
|
||||
console.error("subTitle not found");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ index, ...rest }) => {
|
||||
const { imgUrl, offerInfo, prdtId, prdtNm, priceInfo } =
|
||||
brandCategoryProductDetailInfo[index];
|
||||
const handleBlur = useCallback(() => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleBlur = () => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
dispatch(
|
||||
pushPanel({
|
||||
name: panel_names.DETAIL_PANEL,
|
||||
panelInfo: { patnrId, prdtId },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleFocus = () => {
|
||||
if (cursorVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
setScrollTopBody();
|
||||
};
|
||||
|
||||
return (
|
||||
<TItemCard
|
||||
imageAlt={prdtNm}
|
||||
imageSource={imgUrl}
|
||||
onBlur={handleBlur}
|
||||
onClick={handleClick}
|
||||
onFocus={handleFocus}
|
||||
offerInfo={offerInfo}
|
||||
priceInfo={priceInfo}
|
||||
productId={prdtId}
|
||||
productName={prdtNm}
|
||||
{...rest}
|
||||
/>
|
||||
const handleClick = useCallback(
|
||||
(prdtId) => {
|
||||
dispatch(
|
||||
pushPanel({
|
||||
name: panel_names.DETAIL_PANEL,
|
||||
panelInfo: { patnrId, prdtId },
|
||||
})
|
||||
);
|
||||
},
|
||||
[brandCategoryProductDetailInfo, cursorVisible, dispatch, patnrId]
|
||||
[dispatch, patnrId]
|
||||
);
|
||||
|
||||
const handleFocus = useCallback(() => {
|
||||
if (cursorVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
setScrollTopBody();
|
||||
}, [cursorVisible]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={css.container}
|
||||
id={"featured-category-product-list-id-" + catNm}
|
||||
>
|
||||
{brandCategoryProductDetailInfo && (
|
||||
<TVirtualGridList
|
||||
cbScrollTo={getScrollTo}
|
||||
className={css.tVirtualGridList}
|
||||
dataSize={brandCategoryProductDetailInfo.length}
|
||||
direction="horizontal"
|
||||
itemHeight={438}
|
||||
itemWidth={324}
|
||||
spacing={18}
|
||||
renderItem={renderItem}
|
||||
/>
|
||||
)}
|
||||
<TScroller
|
||||
cbScrollTo={getScrollTo}
|
||||
direction="horizontal"
|
||||
noScrollByWheel
|
||||
>
|
||||
<ul>
|
||||
{brandCategoryProductDetailInfo.map(
|
||||
({ imgUrl, offerInfo, prdtId, prdtNm, priceInfo }, itemIndex) => (
|
||||
<li key={"brand-category-product-detail-info-" + prdtId}>
|
||||
<TItemCard
|
||||
imageAlt={prdtNm}
|
||||
imageSource={imgUrl}
|
||||
onBlur={handleBlur}
|
||||
onClick={() => handleClick(prdtId)}
|
||||
onFocus={handleFocus}
|
||||
offerInfo={offerInfo}
|
||||
priceInfo={priceInfo}
|
||||
productId={prdtId}
|
||||
productName={prdtNm}
|
||||
/>
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</TScroller>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,14 +3,25 @@
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
.size(@w: 100%, @h: 438px);
|
||||
.size(@w: 100%, @h: 482px);
|
||||
|
||||
// tVirtualGridListContainer
|
||||
// tScroller
|
||||
> div:nth-child(1) {
|
||||
.size(@w: inherit, @h: inherit);
|
||||
.size(@w: 100%, @h: 482px);
|
||||
|
||||
&.tVirtualGridList {
|
||||
padding-left: 60px;
|
||||
ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 22px 0 22px 60px;
|
||||
|
||||
> li {
|
||||
flex: none;
|
||||
|
||||
// tItemCard
|
||||
> div {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,8 +62,9 @@ export default function FeaturedCategoryNav({
|
||||
if (marker && sectionTitle) {
|
||||
const markerRect = marker.getBoundingClientRect();
|
||||
const sectionTitleRect = sectionTitle.getBoundingClientRect();
|
||||
const sectionGap = 58;
|
||||
|
||||
const y = sectionTitleRect.top - markerRect.top;
|
||||
const y = sectionTitleRect.top - markerRect.top - sectionGap;
|
||||
|
||||
timeoutRef.current = setTimeout(() => scrollTopBody({ y }));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
.nav {
|
||||
position: relative;
|
||||
.size(@w: 100%, @h: 132px);
|
||||
margin-top: -48px;
|
||||
margin: -48px 0 36px 0;
|
||||
background-color: #e9e9e9;
|
||||
|
||||
// tScroller
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import React, { memo, useCallback } from "react";
|
||||
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||
|
||||
import { updatePanel } from "../../../actions/panelActions";
|
||||
import TScroller from "../../../components/TScroller/TScroller";
|
||||
import useScrollReset from "../../../hooks/useScrollReset";
|
||||
import useScrollTo from "../../../hooks/useScrollTo";
|
||||
import { panel_names } from "../../../utils/Config";
|
||||
import QuickMenuItem from "../QuickMenu/QuickMenuItem/QuickMenuItem";
|
||||
import css from "./QuickMenu.module.less";
|
||||
|
||||
@@ -24,6 +28,8 @@ export default memo(function QuickMenu({
|
||||
true
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleBlur = useCallback((index) => {
|
||||
if (index !== 0) {
|
||||
return;
|
||||
@@ -38,9 +44,16 @@ export default memo(function QuickMenu({
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
updatePanel({
|
||||
name: panel_names.FEATURED_BRANDS_PANEL,
|
||||
panelInfo: selectedPatnrId,
|
||||
})
|
||||
);
|
||||
|
||||
setSelectedPatnrId(patnrId);
|
||||
},
|
||||
[selectedPatnrId]
|
||||
[dispatch, selectedPatnrId]
|
||||
);
|
||||
|
||||
const handleFocus = useCallback((index) => {
|
||||
|
||||
Reference in New Issue
Block a user