import React, { useCallback, useEffect, useRef, } from 'react'; import classNames from 'classnames'; import { useDispatch } from 'react-redux'; import Spotlight from '@enact/spotlight'; import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; import { setContainerLastFocusedElement } from '@enact/spotlight/src/container'; import { sendLogGNB, sendLogTotalRecommend, } from '../../actions/logActions'; import { getTop20Show } from '../../actions/mainActions'; import { pushPanel, updatePanel, } from '../../actions/panelActions'; import { finishVideoPreview } from '../../actions/playActions'; import { getBestSeller } from '../../actions/productActions'; import SectionTitle from '../../components/SectionTitle/SectionTitle'; import TBody from '../../components/TBody/TBody'; import TButton, { TYPES } from '../../components/TButton/TButton'; import { removeDotAndColon } from '../../components/TItemCard/TItemCard'; import TItemCardNew from '../../components/TItemCard/TItemCard.new'; import TPanel from '../../components/TPanel/TPanel'; import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator'; import useWhyDidYouUpdate from '../../hooks/useWhyDidYouUpdate'; import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, panel_names, } from '../../utils/Config'; import { $L } from '../../utils/helperMethods'; import { SpotlightIds } from '../../utils/SpotlightIds'; import PopularShowIndicator from './PopularShow/PopularShowIndicator'; import css from './TrendingNowPanel.module.less'; const Container = SpotlightContainerDecorator( { enterTo: "last-focused" }, "div" ); const BestSellerContainer = SpotlightContainerDecorator( { enterTo: "last-focused" }, "div" ); const STRING_CONF = { POPULAR_SHOW: "POPULAR SHOW", BEST_SELLER: "BEST SELLER", }; const TrendingNowPanel = ({ panelInfo, spotlightId, isOnTop, ...rest }) => { const dispatch = useDispatch(); const { USE_SELECTOR, USE_STATE } = useWhyDidYouUpdate(spotlightId, { panelInfo, isOnTop, ...rest, }); const topInfos = USE_SELECTOR( "topInfos", (state) => state.main.top20ShowData?.topInfos ); const bestSeller = USE_SELECTOR( "bestSeller", (state) => state.product?.bestSellerData?.bestSeller ); const [showButton, setShowButton] = USE_STATE("showButton", true); const [selectedIndex, setSelectedIndex] = USE_STATE("selectedIndex", 0); const cbChangePageRef = useRef(null); const isInitialRef = useRef(true); const currentSentMenuRef = useRef(null); const focusedContainerIdRef = useRef(panelInfo?.focusedContainerId); // effect: data fetching when no data exists in the store useEffect(() => { if (!topInfos) dispatch(getTop20Show()); if (!bestSeller) dispatch(getBestSeller()); }, []); // effect: focus handling on initial render useEffect(() => { if (isInitialRef.current && !panelInfo?.currentSpot) { if (topInfos && bestSeller) { let target; switch (panelInfo?.pageName) { case "PS": target = SpotlightIds.TRENDING_NOW_POPULAR_SHOW; break; case "BS": target = SpotlightIds.TRENDING_NOW_BEST_SELLER; break; } Spotlight.focus(target ?? spotlightId); isInitialRef.current = false; } } }, [topInfos, bestSeller]); // effect: set the index when returning to the details or entering through a deep-link useEffect(() => { if (panelInfo?.selectedIndex) setSelectedIndex(panelInfo.selectedIndex); }, []); // effect: focus recovery when returning to the details useEffect(() => { if (isOnTop && panelInfo?.currentSpot) { Spotlight.focus(panelInfo.currentSpot); } }, [isOnTop]); // effect: for the GNB log useEffect(() => { if (isOnTop) { let menu; // case: entering through a deep link or the Home, and returning from the player or details if (panelInfo?.focusedContainerId) { menu = panelInfo.focusedContainerId !== SpotlightIds.TRENDING_NOW_POPULAR_SHOW ? LOG_MENU.TRENDING_NOW_BEST_SELLER : LOG_MENU.TRENDING_NOW_POPULAR_SHOWS; } // case: entering through the GNB else { menu = LOG_MENU.TRENDING_NOW_POPULAR_SHOWS; } if (menu) dispatch(sendLogGNB(menu)); } }, [isOnTop]); const onFocusedContainerId = useCallback((containerId) => { focusedContainerIdRef.current = containerId; }, []); const handleScroll = useCallback((e) => { setShowButton(e.scrollTop === 0); if (e.scrollTop !== 0) dispatch(finishVideoPreview()); }, []); const handleSpotlight = useCallback( (spotlightId) => (e) => { e.stopPropagation(); if (spotlightId) Spotlight.focus(spotlightId); }, [] ); const handleIndicatorClick = useCallback( (direction) => () => { if (!topInfos) return; const isPrev = direction === "prev"; const isNext = direction === "next"; const isEdgeIndex = (isPrev && selectedIndex === 1) || (isNext && selectedIndex === topInfos.length - 2); if (isEdgeIndex) Spotlight.focus(SpotlightIds.TRENDING_NOW_POPULAR_VIDEO); setSelectedIndex((prev) => prev + (isPrev ? -1 : isNext ? 1 : 0)); setContainerLastFocusedElement(null, [ SpotlightIds.TRENDING_NOW_POPULAR_GRID_LIST, ]); }, [selectedIndex, topInfos] ); const handleBestSellerClick = useCallback( ({ patnrId, prdtId }) => () => { const currentSpot = Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null; dispatch( updatePanel({ name: panel_names.TRENDING_NOW_PANEL, panelInfo: { currentSpot, focusedContainerId: focusedContainerIdRef.current, selectedIndex, }, }) ); dispatch( pushPanel({ name: panel_names.DETAIL_PANEL, panelInfo: { patnrId, prdtId }, }) ); }, [selectedIndex] ); const handleBestSellerFocus = useCallback(() => { handleItemFocus(LOG_MENU.TRENDING_NOW_BEST_SELLER, STRING_CONF.BEST_SELLER); }, [handleItemFocus]); const handleItemClick = useCallback(() => { const currentSpot = Spotlight.getCurrent()?.getAttribute("data-spotlight-id") || null; dispatch( updatePanel({ name: panel_names.TRENDING_NOW_PANEL, panelInfo: { currentSpot, focusedContainerId: focusedContainerIdRef.current, selectedIndex, }, }) ); }, [selectedIndex]); const handleItemFocus = useCallback( (nowMenu, currentShelf) => { setTimeout(() => dispatch(sendLogGNB(nowMenu))); if (nowMenu !== currentSentMenuRef.current) { let order; let spotlightId; switch (currentShelf) { case STRING_CONF.POPULAR_SHOW: order = 1; spotlightId = SpotlightIds.TRENDING_NOW_POPULAR_SHOW; break; case STRING_CONF.BEST_SELLER: order = 2; spotlightId = SpotlightIds.TRENDING_NOW_BEST_SELLER; break; } if (order && spotlightId) { const params = { contextName: LOG_CONTEXT_NAME.TRENDING_NOW, messageId: LOG_MESSAGE_ID.SHELF, shelfLocation: order, shelfId: spotlightId, shelfTitle: currentShelf, }; dispatch(sendLogTotalRecommend(params)); currentSentMenuRef.current = nowMenu; } } }, [currentSentMenuRef] ); const handleTopButtonClick = useCallback(() => { if (cbChangePageRef.current) { cbChangePageRef.current(0, true); } let target = SpotlightIds.TRENDING_NOW_POPULAR_VIDEO; if (topInfos.length === 0 && bestSeller && bestSeller.length > 0) { target = `spotlightId-bestSeller-${bestSeller[0]?.prdtId}`; } Spotlight.focus(target); setContainerLastFocusedElement(null, [ SpotlightIds.TRENDING_NOW_BEST_SELLER, ]); }, [bestSeller, topInfos]); const getFirstLabel = useCallback((rankOrder) => { switch (rankOrder) { case 1: return `${rankOrder}st,`; case 2: return `${rankOrder}nd,`; case 3: return `${rankOrder}rd,`; default: return `${rankOrder}th,`; } }, []); return (