1022 lines
34 KiB
JavaScript
1022 lines
34 KiB
JavaScript
import React, {
|
||
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 { types } from "../../actions/actionTypes";
|
||
import {
|
||
getBrandBestSeller,
|
||
getBrandCategoryInfo,
|
||
getBrandCategoryProductInfo,
|
||
getBrandCreatorsInfo,
|
||
getBrandLayoutInfo,
|
||
getBrandList,
|
||
getBrandLiveChannelInfo,
|
||
getBrandRecommendedShowInfo,
|
||
getBrandSeriesInfo,
|
||
getBrandShowroom,
|
||
getBrandTSVInfo,
|
||
} from "../../actions/brandActions";
|
||
import { changeAppStatus, setHidePopup } from "../../actions/commonActions";
|
||
import {
|
||
sendLogGNB,
|
||
sendLogPartners,
|
||
sendLogTotalRecommend,
|
||
} from "../../actions/logActions";
|
||
import { setMainLiveUpcomingAlarm } from "../../actions/mainActions";
|
||
import {
|
||
deleteMyUpcomingAlertShow,
|
||
getMyUpcomingAlertShow,
|
||
setMyUpcomingUseAlert,
|
||
} from "../../actions/myPageActions";
|
||
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 TVerticalPagenator from "../../components/TVerticalPagenator/TVerticalPagenator";
|
||
import usePrevious from "../../hooks/usePrevious";
|
||
import {
|
||
ACTIVE_POPUP,
|
||
LOG_CONTEXT_NAME,
|
||
LOG_MENU,
|
||
LOG_MESSAGE_ID,
|
||
panel_names,
|
||
} from "../../utils/Config";
|
||
import { $L } from "../../utils/helperMethods";
|
||
import { SpotlightIds } from "../../utils/SpotlightIds";
|
||
import Banner from "./Banner/Banner";
|
||
import FeaturedBestSeller from "./FeaturedBestSeller/FeaturedBestSeller";
|
||
import css from "./FeaturedBrandsPanel.module.less";
|
||
import FeaturedCategory from "./FeaturedCategory/FeaturedCategory";
|
||
import FeaturedCreators from "./FeaturedCreators/FeaturedCreators";
|
||
import LiveChannels from "./LiveChannels/LiveChannels";
|
||
import QuickMenu from "./QuickMenu/QuickMenu";
|
||
import RecommendedShows from "./RecommendedShows/RecommendedShows";
|
||
import Series from "./Series/Series";
|
||
import Showroom from "./Showroom/Showroom";
|
||
import TodaysDeals from "./TodaysDeals/TodaysDeals";
|
||
import UpComing from "./UpComing/UpComing";
|
||
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
|
||
|
||
const STRING_CONF = {
|
||
CANCEL: "CANCEL",
|
||
OK: "OK",
|
||
YES: "YES",
|
||
NO_SHOW_MESSAGE: "This show doesn’t exist anymore",
|
||
REMINDER_ON_OFF_MESSAGE:
|
||
"Reminder Notification is turned off. Select Yes to turn on reminders.",
|
||
UPCOMING_TIME_CONFLICT_MESSAGE:
|
||
"A Reminder is already set on the selected schedule. Press OK to overwrite the existing Reminder.",
|
||
};
|
||
|
||
const TEMPLATE_CODE_CONF = {
|
||
LIVE_CHANNELS: "BRD00101",
|
||
UP_COMING: "BRD00102",
|
||
TODAYS_DEALS: "BRD00103",
|
||
BEST_SELLER: "BRD00104",
|
||
RECOMMENDED_SHOWS: "BRD00105",
|
||
FEATURED_CREATORS: "BRD00106",
|
||
SERIES: "BRD00107",
|
||
CATEGORY: "BRD00108",
|
||
SHOWROOM: "BRD00109",
|
||
};
|
||
|
||
const DISPATCH_MAP = Object.freeze({
|
||
[TEMPLATE_CODE_CONF.LIVE_CHANNELS]: getBrandLiveChannelInfo,
|
||
[TEMPLATE_CODE_CONF.TODAYS_DEALS]: getBrandTSVInfo,
|
||
[TEMPLATE_CODE_CONF.BEST_SELLER]: getBrandBestSeller,
|
||
[TEMPLATE_CODE_CONF.RECOMMENDED_SHOWS]: getBrandRecommendedShowInfo,
|
||
[TEMPLATE_CODE_CONF.FEATURED_CREATORS]: getBrandCreatorsInfo,
|
||
[TEMPLATE_CODE_CONF.SERIES]: getBrandSeriesInfo,
|
||
[TEMPLATE_CODE_CONF.CATEGORY]: getBrandCategoryInfo,
|
||
[TEMPLATE_CODE_CONF.SHOWROOM]: getBrandShowroom,
|
||
});
|
||
|
||
const TOP_MARGIN = 36;
|
||
|
||
const hasTemplateCodeWithValue = (array, value) =>
|
||
array?.some((obj) => obj?.shptmBrndOptTpCd === value) ?? false;
|
||
|
||
const shouldRenderComponent = (data) => {
|
||
return (
|
||
(Array.isArray(data) && data.length > 0) ||
|
||
(typeof data === "object" && Object.keys(data).length > 0)
|
||
);
|
||
};
|
||
|
||
const findSelector = (selector, maxAttempts = 5, currentAttempts = 0) => {
|
||
try {
|
||
if (currentAttempts >= maxAttempts) {
|
||
throw new Error("selector not found");
|
||
}
|
||
|
||
const initialSelector = document.querySelector(selector);
|
||
|
||
if (initialSelector) {
|
||
return initialSelector;
|
||
} else {
|
||
return findSelector(selector, maxAttempts, currentAttempts + 1);
|
||
}
|
||
} catch (error) {
|
||
console.warn(error.message);
|
||
}
|
||
};
|
||
|
||
const findAndFocusFirstContainer = (timerRef) => {
|
||
if (typeof window === "object") {
|
||
const containers = document.querySelectorAll("[data-wheel-point]");
|
||
const firstContainer = Array.from(containers) //
|
||
.find((container) => container?.getAttribute("data-shelf-order") === "1");
|
||
|
||
if (firstContainer) {
|
||
Spotlight.focus(firstContainer);
|
||
clearTimeout(timerRef.current?.timer);
|
||
timerRef.current.timer = null;
|
||
timerRef.current.attemptCount = 0;
|
||
return;
|
||
}
|
||
|
||
if (timerRef.current.attemptCount < 5) {
|
||
timerRef.current.attemptCount += 1;
|
||
timerRef.current.timer = setTimeout(
|
||
() => findAndFocusFirstContainer(timerRef),
|
||
200
|
||
);
|
||
}
|
||
}
|
||
};
|
||
|
||
const getMessageByPopupType = (type) => {
|
||
switch (type) {
|
||
case ACTIVE_POPUP.reminderPopup:
|
||
return $L(STRING_CONF.REMINDER_ON_OFF_MESSAGE);
|
||
case ACTIVE_POPUP.timeConflictPopup:
|
||
return $L(STRING_CONF.UPCOMING_TIME_CONFLICT_MESSAGE);
|
||
case ACTIVE_POPUP.noShowPopup:
|
||
return $L(STRING_CONF.NO_SHOW_MESSAGE);
|
||
default:
|
||
return;
|
||
}
|
||
};
|
||
|
||
const getMenuByContainerId = (containerId) => {
|
||
if (!containerId) return;
|
||
|
||
const splittedId = containerId.split("-")[0];
|
||
switch (splittedId) {
|
||
case SpotlightIds.BRAND_QUICK_MENU:
|
||
return LOG_MENU.FEATURED_BRANDS_QUICK_MENU;
|
||
case TEMPLATE_CODE_CONF.LIVE_CHANNELS:
|
||
return LOG_MENU.FEATURED_BRANDS_LIVE_CHANNELS;
|
||
case TEMPLATE_CODE_CONF.UP_COMING:
|
||
return LOG_MENU.FEATURED_BRANDS_UPCOMING;
|
||
case TEMPLATE_CODE_CONF.TODAYS_DEALS:
|
||
return LOG_MENU.FEATURED_BRANDS_TODAYS_DEALS;
|
||
case TEMPLATE_CODE_CONF.BEST_SELLER:
|
||
return LOG_MENU.FEATURED_BRANDS_BEST_SELLER;
|
||
case TEMPLATE_CODE_CONF.RECOMMENDED_SHOWS:
|
||
return LOG_MENU.FEATURED_BRANDS_RECOMMENDED_SHOWS;
|
||
case TEMPLATE_CODE_CONF.FEATURED_CREATORS:
|
||
return LOG_MENU.FEATURED_BRANDS_FEATURED_CREATORS;
|
||
case TEMPLATE_CODE_CONF.SERIES:
|
||
return LOG_MENU.FEATURED_BRANDS_SERIES;
|
||
case TEMPLATE_CODE_CONF.CATEGORY:
|
||
return LOG_MENU.FEATURED_BRANDS_CATEGORY;
|
||
case TEMPLATE_CODE_CONF.SHOWROOM:
|
||
return LOG_MENU.FEATURED_BRANDS_SHOWROOM;
|
||
default:
|
||
return;
|
||
}
|
||
};
|
||
|
||
const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
|
||
const dispatch = useDispatch();
|
||
|
||
const cursorVisible = useSelector(
|
||
(state) => state.common.appStatus.cursorVisible
|
||
);
|
||
const activePopup = useSelector((state) => state.common.popup.activePopup);
|
||
const popupVisible = useSelector((state) => state.common.popup.popupVisible);
|
||
const brandInfo = useSelector(
|
||
(state) => state.brand.brandInfoData.data.brandInfo
|
||
);
|
||
const brandTopImgInfo = useSelector(
|
||
(state) => state.brand.brandLayoutInfoData.data.brandTopImgInfo
|
||
);
|
||
const brandLayoutInfo = useSelector(
|
||
(state) => state.brand.brandLayoutInfoData.data.brandLayoutInfo
|
||
);
|
||
const brandChanInfo = useSelector(
|
||
(state) => state.brand.brandLiveChannelInfoData.data.brandChanInfo
|
||
);
|
||
const brandChannelCnt = useSelector(
|
||
(state) => state.brand.brandLiveChannelInfoData.data.brandChannelCnt
|
||
);
|
||
const brandLiveChannelUpcoming = useSelector(
|
||
(state) =>
|
||
state.brand.brandLiveChannelInfoData.data.brandLiveChannelUpcoming
|
||
);
|
||
const brandTsvInfo = useSelector(
|
||
(state) => state.brand.brandTsvInfoData.data.brandTsvInfo
|
||
);
|
||
const brandBestSellerInfo = useSelector(
|
||
(state) => state.brand.brandBestSellerData.data.brandBestSellerInfo
|
||
);
|
||
const brandRecommendedShowCategoryInfo = useSelector(
|
||
(state) =>
|
||
state.brand.brandRecommendedShowInfoData.data
|
||
.brandRecommendedShowCategoryInfo
|
||
);
|
||
const brandRecommendedShowInfo = useSelector(
|
||
(state) =>
|
||
state.brand.brandRecommendedShowInfoData.data.brandRecommendedShowInfo
|
||
);
|
||
const brandCreatorsInfo = useSelector(
|
||
(state) => state.brand.brandCreatorsInfoData.data.brandCreatorsInfo
|
||
);
|
||
const barndCreatorsShowInfo = useSelector(
|
||
(state) => state.brand.brandCreatorsInfoData.data.barndCreatorsShowInfo
|
||
);
|
||
const brandSeriesGroupInfo = useSelector(
|
||
(state) => state.brand.brandSeriesInfoData.data.brandSeriesGroupInfo
|
||
);
|
||
const brandSeriesInfo = useSelector(
|
||
(state) => state.brand.brandSeriesInfoData.data.brandSeriesInfo
|
||
);
|
||
const brandCategoryInfo = useSelector(
|
||
(state) => state.brand.brandCategoryInfoData.data.brandCategoryInfo
|
||
);
|
||
const brandCategoryProductInfo = useSelector(
|
||
(state) => state.brand.brandCategoryInfoData.data.brandCategoryProductInfo
|
||
);
|
||
const brandShowroomInfo = useSelector(
|
||
(state) => state.brand.brandShowroomData.data.brandShowroomInfo
|
||
);
|
||
|
||
const [displayTopButton, setDisplayTopButton] = useState(false);
|
||
const [focusedContainerId, setFocusedContainerId] = useState(null);
|
||
const [isInitialFocusOccurred, setIsInitialFocusOccurred] = useState(null);
|
||
const [isLogGNBSent, setIsLogGNBSent] = useState(false);
|
||
const [selectedPatncNm, setSelectedPatncNm] = useState(null);
|
||
const [selectedPatnrId, setSelectedPatnrId] = useState(null);
|
||
const [selectedCatCd, setSelectedCatCd] = useState(null);
|
||
const [selectedHstNm, setSelectedHstNm] = useState(null);
|
||
const [selectedSeriesId, setSelectedSeriesId] = useState(null);
|
||
const [selectedCatCdLv1, setSelectedCatCdLv1] = useState(null);
|
||
const [selectedCatCdLv2, setSelectedCatCdLv2] = useState(null);
|
||
|
||
const brandInfoRef = usePrevious(brandInfo);
|
||
const displayTopButtonRef = usePrevious(displayTopButton);
|
||
const focusedContainerIdRef = usePrevious(focusedContainerId);
|
||
|
||
const initialFocusTimeoutJob = useRef(new Job((func) => func(), 0));
|
||
|
||
const alarmTimer = useRef(null);
|
||
const cbChangePageRef = useRef(null);
|
||
const lastMenuRef = useRef(null);
|
||
const orderableFlexContainerRef = useRef(null);
|
||
const prevSelectedPatncNmRef = useRef(null);
|
||
const noneTargetTimer = useRef({
|
||
timer: null,
|
||
attemptCount: 0,
|
||
});
|
||
const renderedShelfCountRef = useRef(0);
|
||
|
||
const fromDetail = panelInfo?.from && panelInfo.from === "detail";
|
||
const fromGNB = panelInfo?.from && panelInfo.from === "gnb";
|
||
const fromUpcoming = panelInfo?.from && panelInfo.from === "upcoming";
|
||
const fromQuickMenu = panelInfo?.from && panelInfo.from === "menu";
|
||
|
||
const hasQuickMenu = useMemo(
|
||
() => brandInfo && brandInfo.length > 1,
|
||
[brandInfo]
|
||
);
|
||
|
||
const sortedBrandLayoutInfo = useMemo(
|
||
() => brandLayoutInfo?.sort((a, b) => a.expsOrd - b.expsOrd) ?? [],
|
||
[brandLayoutInfo]
|
||
);
|
||
|
||
const doSendLogGNB = useCallback(
|
||
(containerId, shelfOrder) => {
|
||
if (
|
||
!selectedPatncNm ||
|
||
!getMenuByContainerId(containerId) ||
|
||
(getMenuByContainerId(containerId) === lastMenuRef.current &&
|
||
selectedPatncNm === prevSelectedPatncNmRef.current)
|
||
) {
|
||
return;
|
||
}
|
||
|
||
const selectedBrand = `${LOG_MENU.FEATURED_BRANDS}/${selectedPatncNm}`;
|
||
const currentShelf = `${getMenuByContainerId(containerId)}`;
|
||
const menu =
|
||
selectedBrand && currentShelf && `${selectedBrand} ${currentShelf}`;
|
||
|
||
dispatch(sendLogGNB(menu));
|
||
|
||
dispatch(
|
||
sendLogTotalRecommend({
|
||
contextName: LOG_CONTEXT_NAME.FEATURED_BRANDS,
|
||
messageId: LOG_MESSAGE_ID.SHELF,
|
||
partner: selectedPatncNm,
|
||
shelfLocation: shelfOrder,
|
||
shelfId: containerId,
|
||
shelfTitle: currentShelf,
|
||
})
|
||
);
|
||
|
||
setIsLogGNBSent(true);
|
||
prevSelectedPatncNmRef.current = selectedPatncNm;
|
||
lastMenuRef.current = getMenuByContainerId(containerId);
|
||
},
|
||
[selectedPatncNm, sortedBrandLayoutInfo, selectedPatncNm]
|
||
);
|
||
|
||
const focusOnMount = useCallback((targetId) => {
|
||
initialFocusTimeoutJob.current.start(() => {
|
||
const focusTarget = findSelector(`[data-spotlight-id="${targetId}"]`);
|
||
|
||
if (focusTarget) Spotlight.focus(focusTarget);
|
||
else findAndFocusFirstContainer(noneTargetTimer);
|
||
});
|
||
}, []);
|
||
|
||
const handleItemFocus = useCallback(
|
||
(containerId, shelfOrder) => doSendLogGNB(containerId, shelfOrder),
|
||
[doSendLogGNB]
|
||
);
|
||
|
||
const handlePopupClick = useCallback(() => {
|
||
if (activePopup?.type === ACTIVE_POPUP.reminderPopup) {
|
||
dispatch(setMyUpcomingUseAlert({ upcomingAlamUseFlag: "Y" }));
|
||
}
|
||
|
||
if (activePopup?.type === ACTIVE_POPUP.timeConflictPopup) {
|
||
const { upcomingAlarmInfo, deletedAlertShows } = activePopup;
|
||
|
||
dispatch(setMainLiveUpcomingAlarm(upcomingAlarmInfo));
|
||
dispatch(deleteMyUpcomingAlertShow({ showList: deletedAlertShows }));
|
||
|
||
alarmTimer.current = setTimeout(
|
||
() => dispatch(getMyUpcomingAlertShow()),
|
||
200
|
||
);
|
||
}
|
||
|
||
dispatch(setHidePopup());
|
||
setTimeout(() => Spotlight.focus());
|
||
}, [dispatch, activePopup]);
|
||
|
||
const handlePopupClose = useCallback(() => {
|
||
dispatch(setHidePopup());
|
||
setTimeout(() => Spotlight.focus());
|
||
}, [dispatch]);
|
||
|
||
const handleTopButtonClick = useCallback(() => {
|
||
if (cbChangePageRef.current) cbChangePageRef.current(0, true);
|
||
|
||
let target;
|
||
|
||
if (hasQuickMenu) {
|
||
target = document.querySelector(`[data-menu-index="${0}"]`);
|
||
} else {
|
||
const paginatorItem = document.querySelector(`[data-wheel-point]`);
|
||
const spotlightItem = paginatorItem?.querySelector(`[data-spotlight-id]`);
|
||
target = spotlightItem?.querySelector(`[tabindex="${-1}"]`);
|
||
}
|
||
|
||
if (target) Spotlight.focus(target);
|
||
}, [hasQuickMenu]);
|
||
|
||
const onFocusedContainerId = useCallback(
|
||
(containerId) => setFocusedContainerId(containerId),
|
||
[]
|
||
);
|
||
|
||
const renderPageItem = useCallback(() => {
|
||
return (
|
||
<>
|
||
{sortedBrandLayoutInfo.map((el, idx) => {
|
||
switch (el.shptmBrndOptTpCd) {
|
||
case TEMPLATE_CODE_CONF.LIVE_CHANNELS: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.LIVE_CHANNELS
|
||
) &&
|
||
shouldRenderComponent(brandChanInfo) && (
|
||
<LiveChannels
|
||
brandChanInfo={brandChanInfo}
|
||
brandChannelCnt={brandChannelCnt}
|
||
handleItemFocus={handleItemFocus}
|
||
isOnTop={isOnTop}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.LIVE_CHANNELS}
|
||
selectedPatnrId={selectedPatnrId}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.UP_COMING: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.UP_COMING
|
||
) &&
|
||
shouldRenderComponent(brandLiveChannelUpcoming) && (
|
||
<UpComing
|
||
brandLiveChannelUpcoming={brandLiveChannelUpcoming}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
selectedPatnrId={selectedPatnrId}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.UP_COMING}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.TODAYS_DEALS: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.TODAYS_DEALS
|
||
) &&
|
||
shouldRenderComponent(brandTsvInfo) && (
|
||
<TodaysDeals
|
||
brandTsvInfo={brandTsvInfo}
|
||
handleItemFocus={handleItemFocus}
|
||
hasQuickMenu={hasQuickMenu}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.TODAYS_DEALS}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.BEST_SELLER: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.BEST_SELLER
|
||
) &&
|
||
shouldRenderComponent(brandBestSellerInfo) && (
|
||
<FeaturedBestSeller
|
||
brandBestSellerInfo={brandBestSellerInfo}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.BEST_SELLER}
|
||
selectedPatnrId={selectedPatnrId}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.RECOMMENDED_SHOWS: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.RECOMMENDED_SHOWS
|
||
) &&
|
||
shouldRenderComponent(brandRecommendedShowCategoryInfo) &&
|
||
shouldRenderComponent(brandRecommendedShowInfo) && (
|
||
<RecommendedShows
|
||
brandRecommendedShowCategoryInfo={
|
||
brandRecommendedShowCategoryInfo
|
||
}
|
||
brandRecommendedShowInfo={brandRecommendedShowInfo}
|
||
fromGNB={fromGNB}
|
||
fromQuickMenu={fromQuickMenu}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.RECOMMENDED_SHOWS}
|
||
selectedCatCd={selectedCatCd}
|
||
selectedPatncNm={selectedPatncNm}
|
||
selectedPatnrId={selectedPatnrId}
|
||
setSelectedCatCd={setSelectedCatCd}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.FEATURED_CREATORS: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.FEATURED_CREATORS
|
||
) &&
|
||
shouldRenderComponent(brandCreatorsInfo) &&
|
||
shouldRenderComponent(barndCreatorsShowInfo) && (
|
||
<FeaturedCreators
|
||
brandCreatorsInfo={brandCreatorsInfo}
|
||
barndCreatorsShowInfo={barndCreatorsShowInfo}
|
||
fromGNB={fromGNB}
|
||
fromQuickMenu={fromQuickMenu}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
selectedHstNm={selectedHstNm}
|
||
selectedPatncNm={selectedPatncNm}
|
||
selectedPatnrId={selectedPatnrId}
|
||
setSelectedHstNm={setSelectedHstNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.FEATURED_CREATORS}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.SERIES: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.SERIES
|
||
) &&
|
||
shouldRenderComponent(brandSeriesGroupInfo) &&
|
||
shouldRenderComponent(brandSeriesInfo) && (
|
||
<Series
|
||
brandSeriesGroupInfo={brandSeriesGroupInfo}
|
||
brandSeriesInfo={brandSeriesInfo}
|
||
fromGNB={fromGNB}
|
||
fromQuickMenu={fromQuickMenu}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.SERIES}
|
||
selectedPatncNm={selectedPatncNm}
|
||
selectedPatnrId={selectedPatnrId}
|
||
selectedSeriesId={selectedSeriesId}
|
||
setSelectedSeriesId={setSelectedSeriesId}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.CATEGORY: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.CATEGORY
|
||
) &&
|
||
shouldRenderComponent(brandCategoryInfo) &&
|
||
shouldRenderComponent(brandCategoryProductInfo) && (
|
||
<FeaturedCategory
|
||
brandCategoryInfo={brandCategoryInfo}
|
||
brandCategoryProductInfo={brandCategoryProductInfo}
|
||
fromGNB={fromGNB}
|
||
fromQuickMenu={fromQuickMenu}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.CATEGORY}
|
||
selectedCatCdLv1={selectedCatCdLv1}
|
||
selectedCatCdLv2={selectedCatCdLv2}
|
||
selectedPatncNm={selectedPatncNm}
|
||
selectedPatnrId={selectedPatnrId}
|
||
setSelectedCatCdLv1={setSelectedCatCdLv1}
|
||
setSelectedCatCdLv2={setSelectedCatCdLv2}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
|
||
case TEMPLATE_CODE_CONF.SHOWROOM: {
|
||
return (
|
||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||
{hasTemplateCodeWithValue(
|
||
sortedBrandLayoutInfo,
|
||
TEMPLATE_CODE_CONF.SHOWROOM
|
||
) &&
|
||
shouldRenderComponent(brandShowroomInfo) && (
|
||
<Showroom
|
||
brandShowroomInfo={brandShowroomInfo}
|
||
fromGNB={fromGNB}
|
||
fromQuickMenu={fromQuickMenu}
|
||
handleItemFocus={handleItemFocus}
|
||
order={idx + 1}
|
||
shelfOrder={el.expsOrd}
|
||
shelfTitle={el.shptmBrndOptTpNm}
|
||
selectedPatnrId={selectedPatnrId}
|
||
selectedPatncNm={selectedPatncNm}
|
||
spotlightId={TEMPLATE_CODE_CONF.SHOWROOM}
|
||
/>
|
||
)}
|
||
</React.Fragment>
|
||
);
|
||
}
|
||
}
|
||
})}
|
||
</>
|
||
);
|
||
}, [
|
||
brandBestSellerInfo,
|
||
brandCategoryInfo,
|
||
brandCategoryProductInfo,
|
||
brandChanInfo,
|
||
brandChannelCnt,
|
||
brandCreatorsInfo,
|
||
barndCreatorsShowInfo,
|
||
brandLiveChannelUpcoming,
|
||
brandRecommendedShowCategoryInfo,
|
||
brandRecommendedShowInfo,
|
||
brandSeriesGroupInfo,
|
||
brandSeriesInfo,
|
||
brandShowroomInfo,
|
||
brandTsvInfo,
|
||
fromGNB,
|
||
fromQuickMenu,
|
||
handleItemFocus,
|
||
hasQuickMenu,
|
||
isOnTop,
|
||
selectedCatCd,
|
||
selectedCatCdLv1,
|
||
selectedCatCdLv2,
|
||
selectedHstNm,
|
||
selectedPatncNm,
|
||
selectedPatnrId,
|
||
selectedSeriesId,
|
||
sortedBrandLayoutInfo,
|
||
]);
|
||
|
||
const resetStates = useCallback(() => {
|
||
setSelectedCatCd(null);
|
||
setSelectedHstNm(null);
|
||
setSelectedSeriesId(null);
|
||
setSelectedCatCdLv1(null);
|
||
setSelectedCatCdLv2(null);
|
||
setContainerLastFocusedElement(null, ["upcoming-list-id"]);
|
||
setContainerLastFocusedElement(null, ["featured-category-nav-id"]);
|
||
}, []);
|
||
|
||
// effect: reset the brand store and set the focusedContainerId and fetch brand list on initial render
|
||
useEffect(() => {
|
||
if (!fromDetail) {
|
||
const containerId =
|
||
fromUpcoming || panelInfo?.linkTpCd === "8002"
|
||
? TEMPLATE_CODE_CONF.LIVE_CHANNELS
|
||
: SpotlightIds.BRAND_QUICK_MENU;
|
||
|
||
setFocusedContainerId(containerId);
|
||
dispatch(getBrandList());
|
||
dispatch({ type: types.RESET_BRAND_STATE_EXCEPT_BRAND_INFO });
|
||
} else setFocusedContainerId(panelInfo?.focusedContainerId);
|
||
}, []);
|
||
|
||
// effect: layout information fetching due to partner id change
|
||
useEffect(() => {
|
||
if (!fromDetail) {
|
||
dispatch({ type: types.RESET_BRAND_LAYOUT_INFO });
|
||
dispatch(getBrandLayoutInfo({ patnrId: panelInfo?.patnrId }));
|
||
setIsInitialFocusOccurred(false);
|
||
setDisplayTopButton(false);
|
||
}
|
||
}, [panelInfo?.patnrId]);
|
||
|
||
// effect: set selectedPatnrId and selectedPatncNm
|
||
useEffect(() => {
|
||
if (brandInfo) {
|
||
const patnrId = panelInfo?.patnrId;
|
||
const patncNm = brandInfo.find((b) => b?.patnrId === patnrId).patncNm;
|
||
|
||
setSelectedPatncNm(patncNm);
|
||
|
||
if (!fromDetail) setSelectedPatnrId(patnrId);
|
||
}
|
||
}, [brandInfo, panelInfo?.patnrId]);
|
||
|
||
// effect: data fetching based on brandLayoutInfo and selectedPatnrId
|
||
useEffect(() => {
|
||
if (sortedBrandLayoutInfo && selectedPatnrId) {
|
||
Object.entries(DISPATCH_MAP) //
|
||
.forEach(([templateCode, action]) => {
|
||
if (hasTemplateCodeWithValue(sortedBrandLayoutInfo, templateCode)) {
|
||
dispatch(action({ patnrId: selectedPatnrId }));
|
||
}
|
||
});
|
||
|
||
resetStates();
|
||
}
|
||
}, [sortedBrandLayoutInfo, selectedPatnrId]);
|
||
|
||
useEffect(() => {
|
||
if (selectedCatCd) {
|
||
dispatch(
|
||
getBrandRecommendedShowInfo({
|
||
patnrId: panelInfo?.patnrId,
|
||
catCd: selectedCatCd,
|
||
})
|
||
);
|
||
}
|
||
}, [selectedCatCd]);
|
||
|
||
useEffect(() => {
|
||
if (selectedHstNm) {
|
||
dispatch(
|
||
getBrandCreatorsInfo({
|
||
patnrId: panelInfo?.patnrId,
|
||
hstNm: selectedHstNm,
|
||
})
|
||
);
|
||
}
|
||
}, [selectedHstNm]);
|
||
|
||
useEffect(() => {
|
||
if (selectedCatCdLv1 === "") {
|
||
dispatch(
|
||
getBrandCategoryInfo({
|
||
patnrId: panelInfo?.patnrId,
|
||
})
|
||
);
|
||
return;
|
||
}
|
||
|
||
if (selectedCatCdLv1) {
|
||
dispatch(
|
||
getBrandCategoryProductInfo({
|
||
patnrId: panelInfo?.patnrId,
|
||
catCdLv1: selectedCatCdLv1,
|
||
})
|
||
);
|
||
}
|
||
}, [selectedCatCdLv1]);
|
||
|
||
// effect: initial or top panel focus logic
|
||
useEffect(() => {
|
||
if (isOnTop && !isInitialFocusOccurred && selectedPatncNm) {
|
||
// case: gnb or quick menu
|
||
let targetId = "spotlightId-" + panelInfo?.patnrId;
|
||
|
||
// case: upcoming or system alarm
|
||
if (fromUpcoming || panelInfo?.linkTpCd === "8002") {
|
||
targetId = TEMPLATE_CODE_CONF.LIVE_CHANNELS;
|
||
|
||
if (typeof window === "object" && window.MutationObserver) {
|
||
const observer = new window.MutationObserver((mutations) => {
|
||
for (let idx = mutations.length; idx--; ) {
|
||
if (mutations[idx].addedNodes.length) {
|
||
for (let i = mutations[idx].addedNodes.length; i--; ) {
|
||
const node = mutations[idx].addedNodes[i];
|
||
|
||
if (node.getAttribute("data-spotlight-id") === targetId) {
|
||
if (cbChangePageRef.current) {
|
||
cbChangePageRef.current(targetId, false);
|
||
}
|
||
|
||
Spotlight.focus(node);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
if (orderableFlexContainerRef.current) {
|
||
observer.observe(orderableFlexContainerRef.current, {
|
||
childList: true,
|
||
});
|
||
}
|
||
|
||
return () => observer.disconnect();
|
||
}
|
||
}
|
||
|
||
// case: detail
|
||
if (fromDetail) {
|
||
if (panelInfo?.catCdLv1) setSelectedCatCdLv1(panelInfo.catCdLv1);
|
||
if (panelInfo?.catCdLv2) setSelectedCatCdLv2(panelInfo.catCdLv2);
|
||
if (panelInfo?.seriesId) setSelectedSeriesId(panelInfo.seriesId);
|
||
}
|
||
|
||
focusOnMount(panelInfo?.lastFocusedTargetId ?? targetId);
|
||
setIsInitialFocusOccurred(true);
|
||
}
|
||
}, [isOnTop, isInitialFocusOccurred, selectedPatncNm]);
|
||
|
||
// effect: top button display setting logic
|
||
useEffect(() => {
|
||
if (panelInfo?.displayTopButton) {
|
||
setDisplayTopButton(true);
|
||
return;
|
||
}
|
||
|
||
if (typeof window === "object" && window.MutationObserver) {
|
||
const observer = new window.MutationObserver((mutations) => {
|
||
let shouldDisplayTopButton = false;
|
||
|
||
for (let idx = mutations.length; idx--; ) {
|
||
if (mutations[idx].type === "childList") {
|
||
renderedShelfCountRef.current =
|
||
orderableFlexContainerRef.current?.children.length || 0;
|
||
}
|
||
|
||
if (renderedShelfCountRef.current > 1) {
|
||
shouldDisplayTopButton = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (shouldDisplayTopButton !== displayTopButtonRef.current) {
|
||
setDisplayTopButton(shouldDisplayTopButton);
|
||
}
|
||
});
|
||
|
||
if (orderableFlexContainerRef.current) {
|
||
observer.observe(orderableFlexContainerRef.current, {
|
||
childList: true,
|
||
});
|
||
}
|
||
|
||
return () => observer.disconnect();
|
||
}
|
||
}, [panelInfo?.displayTopButton, panelInfo?.patnrId]);
|
||
|
||
// effect: gnb log
|
||
useEffect(() => {
|
||
if (!isOnTop) {
|
||
prevSelectedPatncNmRef.current = null;
|
||
setIsInitialFocusOccurred(false);
|
||
}
|
||
|
||
if (focusedContainerId && isOnTop && selectedPatncNm) {
|
||
doSendLogGNB(focusedContainerId);
|
||
}
|
||
}, [doSendLogGNB, focusedContainerId, isOnTop, selectedPatncNm]);
|
||
|
||
// effect: partners log
|
||
useEffect(() => {
|
||
if (
|
||
isLogGNBSent &&
|
||
isInitialFocusOccurred &&
|
||
selectedPatnrId &&
|
||
selectedPatncNm
|
||
) {
|
||
dispatch(
|
||
sendLogPartners({
|
||
patncNm: selectedPatncNm,
|
||
patnrId: selectedPatnrId,
|
||
})
|
||
);
|
||
}
|
||
}, [isLogGNBSent, isInitialFocusOccurred, selectedPatnrId, selectedPatncNm]);
|
||
|
||
// effect: unmount
|
||
useEffect(() => {
|
||
return () => {
|
||
dispatch(
|
||
updatePanel({
|
||
name: panel_names.FEATURED_BRANDS_PANEL,
|
||
panelInfo: {
|
||
brandInfo: brandInfoRef.current,
|
||
displayTopButton: displayTopButtonRef.current,
|
||
focusedContainerId: focusedContainerIdRef.current,
|
||
from: "detail",
|
||
lastMenu: lastMenuRef.current,
|
||
},
|
||
})
|
||
);
|
||
|
||
clearTimeout(alarmTimer.current);
|
||
clearTimeout(noneTargetTimer.current);
|
||
initialFocusTimeoutJob.current.stop();
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<TPanel
|
||
className={css.tPanel}
|
||
spotlightId={cursorVisible ? spotlightId : null}
|
||
>
|
||
<TBody
|
||
className={css.tBody}
|
||
scrollable={false}
|
||
spotlightDisabled={!isOnTop}
|
||
>
|
||
<TVerticalPagenator
|
||
cbChangePageRef={cbChangePageRef}
|
||
className={css.tVerticalPagenator}
|
||
defaultContainerId={panelInfo?.focusedContainerId}
|
||
deleteFocus
|
||
onFocusedContainerId={onFocusedContainerId}
|
||
spotlightId={SpotlightIds.BRAND_VERTICAL_PAGENATOR}
|
||
topMargin={TOP_MARGIN}
|
||
>
|
||
{brandInfo && brandInfo.length > 1 && (
|
||
<QuickMenu
|
||
brandInfo={brandInfo}
|
||
fromGNB={fromGNB}
|
||
fromQuickMenu={fromQuickMenu}
|
||
handleItemFocus={handleItemFocus}
|
||
panelPatnrId={panelInfo?.patnrId}
|
||
selectedPatnrId={selectedPatnrId}
|
||
spotlightId={SpotlightIds.BRAND_QUICK_MENU}
|
||
resetStates={resetStates}
|
||
/>
|
||
)}
|
||
|
||
{brandInfo && brandTopImgInfo && (
|
||
<Banner
|
||
brandInfo={brandInfo}
|
||
brandTopImgInfo={brandTopImgInfo}
|
||
panelPatnrId={panelInfo?.patnrId}
|
||
/>
|
||
)}
|
||
|
||
{sortedBrandLayoutInfo && (
|
||
<div
|
||
className={css.orderableFlexContainer}
|
||
ref={orderableFlexContainerRef}
|
||
>
|
||
{renderPageItem()}
|
||
</div>
|
||
)}
|
||
|
||
{displayTopButton && (
|
||
<TButton
|
||
className={classNames(css.tButton)}
|
||
data-wheel-point
|
||
onClick={handleTopButtonClick}
|
||
size={null}
|
||
spotlightId={SpotlightIds.BRAND_TOP_BUTTON}
|
||
type={TYPES.topButton}
|
||
/>
|
||
)}
|
||
</TVerticalPagenator>
|
||
</TBody>
|
||
|
||
{(activePopup?.type === ACTIVE_POPUP.reminderPopup ||
|
||
activePopup?.type === ACTIVE_POPUP.timeConflictPopup) && (
|
||
<TPopUp
|
||
button1Text={$L(STRING_CONF.OK)}
|
||
button2Text={$L(STRING_CONF.CANCEL)}
|
||
hasButton
|
||
hasText
|
||
kind="textPopup"
|
||
onClick={handlePopupClick}
|
||
onClose={handlePopupClose}
|
||
open={popupVisible}
|
||
text={getMessageByPopupType(activePopup?.type)}
|
||
/>
|
||
)}
|
||
</TPanel>
|
||
);
|
||
};
|
||
|
||
const propsAreEqual = (prev, next) => {
|
||
const keys = Object.keys(prev);
|
||
const nextKeys = Object.keys(next);
|
||
// if (!next.isOnTop) {
|
||
// //ignore event on background
|
||
// return true;
|
||
// }
|
||
if (keys.length !== nextKeys.length) {
|
||
return false;
|
||
}
|
||
for (let i = 0; i < keys.length; i++) {
|
||
if (prev[keys[i]] !== next[keys[i]]) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
|
||
export default React.memo(FeaturedBrandsPanel, propsAreEqual);
|