242 lines
6.8 KiB
JavaScript
242 lines
6.8 KiB
JavaScript
import React, {
|
|
memo,
|
|
useCallback,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState,
|
|
} from "react";
|
|
|
|
import classNames from "classnames";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
|
|
import { Job } from "@enact/core/util";
|
|
import Spotlight from "@enact/spotlight";
|
|
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
|
import Spottable from "@enact/spotlight/Spottable";
|
|
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
|
|
|
|
import { clearThemeDetail } from "../../../actions/homeActions";
|
|
import { getMainYouMayLike } from "../../../actions/mainActions";
|
|
import { popPanel, pushPanel } from "../../../actions/panelActions";
|
|
import { finishVideoPreview } from "../../../actions/playActions";
|
|
import TItemCard from "../../../components/TItemCard/TItemCard";
|
|
import TVirtualGridList from "../../../components/TVirtualGridList/TVirtualGridList";
|
|
import useScrollTo from "../../../hooks/useScrollTo";
|
|
import { panel_names } from "../../../utils/Config";
|
|
import { $L } from "../../../utils/helperMethods";
|
|
import { SpotlightIds } from "../../../utils/SpotlightIds";
|
|
import css from "./YouMayLike.module.less";
|
|
import { sendLogTotalRecommend } from "../../../actions/logActions";
|
|
import * as Config from "../../../utils/Config";
|
|
|
|
const Container = SpotlightContainerDecorator(
|
|
{ enterTo: "default-element" },
|
|
"div"
|
|
);
|
|
|
|
const SpottableComponent = Spottable("div");
|
|
export default memo(function YouMayLike({
|
|
isUnable,
|
|
panelInfo,
|
|
productInfo,
|
|
setSelectedIndex,
|
|
setIsYouMayLikeOpened,
|
|
}) {
|
|
const [focused, setFocused] = useState(false);
|
|
const [expanded, setExpanded] = useState(false);
|
|
const dispatch = useDispatch();
|
|
const youmaylikeData = useSelector((state) => state.main.youmaylikeData);
|
|
const { getScrollTo, scrollLeft } = useScrollTo();
|
|
const panels = useSelector((state) => state.panels.panels);
|
|
const cursorVisible = useSelector(
|
|
(state) => state.common.appStatus.cursorVisible
|
|
);
|
|
const themeProductInfos = useSelector(
|
|
(state) => state.home.themeCurationDetailInfoData
|
|
);
|
|
|
|
const cursorOpen = useRef(new Job((func) => func(), 1000));
|
|
|
|
const launchedFromPlayer = useMemo(() => {
|
|
const detailPanelIndex = panels.findIndex(
|
|
({ name }) => name === "detailpanel"
|
|
);
|
|
const playerPanelIndex = panels.findIndex(
|
|
({ name }) => name === "playerpanel"
|
|
);
|
|
|
|
return detailPanelIndex - 1 === playerPanelIndex;
|
|
}, [panels]);
|
|
|
|
useEffect(() => {
|
|
if (expanded) {
|
|
setIsYouMayLikeOpened(true);
|
|
|
|
return () => setIsYouMayLikeOpened(false);
|
|
}
|
|
}, [expanded, setIsYouMayLikeOpened]);
|
|
|
|
useEffect(() => {
|
|
scrollLeft();
|
|
}, [panelInfo]);
|
|
|
|
const cursorVisibleOnFocus = useCallback(() => {
|
|
if (cursorVisible) {
|
|
cursorOpen.current.start(() => {
|
|
setExpanded(true);
|
|
});
|
|
} else if (productInfo) {
|
|
setExpanded(true);
|
|
}
|
|
}, [productInfo, cursorVisible]);
|
|
|
|
const cursorVisibleOnBlur = useCallback(() => {
|
|
if (cursorVisible) {
|
|
cursorOpen.current.stop();
|
|
}
|
|
}, [cursorVisible]);
|
|
|
|
const onFocus = useCallback(() => {
|
|
if (productInfo) {
|
|
setFocused(true);
|
|
}
|
|
}, [productInfo]);
|
|
|
|
const onBlur = useCallback(() => {
|
|
setFocused(false);
|
|
}, []);
|
|
|
|
const onClickExtraArea = useCallback(() => {
|
|
setExpanded(false);
|
|
setFocused(false);
|
|
}, []);
|
|
|
|
const onKeyDown = useCallback((event) => {
|
|
if (event.key === "ArrowUp") {
|
|
setExpanded(false);
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
Spotlight.focus("spotlight-IndicatorContainer");
|
|
}
|
|
}, []);
|
|
|
|
const onButtonClick = useCallback(() => {
|
|
setExpanded((prev) => !prev);
|
|
}, []);
|
|
|
|
const renderItem = useCallback(
|
|
({ index, ...rest }) => {
|
|
const {
|
|
imgUrl,
|
|
patnrId,
|
|
prdtId,
|
|
prdtNm,
|
|
priceInfo,
|
|
offerInfo,
|
|
patncNm,
|
|
brndNm,
|
|
lgCatCd,
|
|
lgCatNm,
|
|
} = youmaylikeData[index];
|
|
|
|
const handleItemClick = () => {
|
|
setExpanded(false);
|
|
setSelectedIndex(0);
|
|
dispatch(finishVideoPreview());
|
|
dispatch(popPanel(panel_names.DETAIL_PANEL));
|
|
|
|
setContainerLastFocusedElement(null, ["indicator-GridListContainer"]);
|
|
if (themeProductInfos && themeProductInfos.length > 0) {
|
|
dispatch(clearThemeDetail());
|
|
}
|
|
dispatch(
|
|
pushPanel({
|
|
name: panel_names.DETAIL_PANEL,
|
|
panelInfo: {
|
|
patnrId,
|
|
prdtId,
|
|
launchedFromPlayer: launchedFromPlayer,
|
|
},
|
|
})
|
|
);
|
|
cursorOpen.current.stop();
|
|
};
|
|
|
|
return (
|
|
<TItemCard
|
|
{...rest}
|
|
key={prdtId}
|
|
contextName={Config.LOG_CONTEXT_NAME.YOUMAYLIKE}
|
|
messageId={Config.LOG_MESSAGE_ID.CONTENTCLICK}
|
|
productId={prdtId}
|
|
productTitle={prdtNm}
|
|
nowProductId={productInfo?.prdtId}
|
|
nowProductTitle={productInfo?.prdtNm}
|
|
nowCategory={productInfo?.catNm}
|
|
catNm={lgCatNm}
|
|
patnerName={patncNm}
|
|
brandName={brndNm}
|
|
imageAlt={prdtId}
|
|
imageSource={imgUrl}
|
|
priceInfo={priceInfo}
|
|
offerInfo={offerInfo}
|
|
productName={prdtNm}
|
|
onClick={handleItemClick}
|
|
label={index * 1 + 1 + " of " + youmaylikeData.length}
|
|
lastLabel=" go to detail, button"
|
|
/>
|
|
);
|
|
},
|
|
[youmaylikeData, launchedFromPlayer]
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Container
|
|
className={classNames(
|
|
css.container,
|
|
isUnable && css.unable,
|
|
expanded && css.expanded,
|
|
focused && css.focused
|
|
)}
|
|
spotlightRestrict="self-only"
|
|
onFocus={cursorVisibleOnFocus}
|
|
onBlur={cursorVisibleOnBlur}
|
|
>
|
|
<SpottableComponent
|
|
className={classNames(css.button, focused && css.focused)}
|
|
onKeyDown={onKeyDown}
|
|
onFocus={onFocus}
|
|
onBlur={onBlur}
|
|
onClick={onButtonClick}
|
|
aria-label={
|
|
(expanded === false ? "Open " : "Close ") + "YOU MAY LIKE, button"
|
|
}
|
|
>
|
|
{$L("You may also like")}
|
|
<span className={classNames(css.arrow, expanded && css.expanded)} />
|
|
</SpottableComponent>
|
|
<Container className={css.itemWrap}>
|
|
{youmaylikeData && youmaylikeData.length > 0 && (
|
|
<TVirtualGridList
|
|
cbScrollTo={getScrollTo}
|
|
dataSize={youmaylikeData.length}
|
|
direction="horizontal"
|
|
autoScroll
|
|
renderItem={renderItem}
|
|
itemWidth={324}
|
|
itemHeight={438}
|
|
spacing={15}
|
|
className={css.itemList}
|
|
/>
|
|
)}
|
|
</Container>
|
|
{expanded && (
|
|
<Container className={css.extraArea} onClick={onClickExtraArea} />
|
|
)}
|
|
</Container>
|
|
</>
|
|
);
|
|
});
|