516 lines
17 KiB
JavaScript
516 lines
17 KiB
JavaScript
// src/views/HomePanel/HomeBanner/HomeBanner.jsx
|
|
|
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import Spotlight from "@enact/spotlight";
|
|
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
|
|
import Spottable from "@enact/spotlight/Spottable";
|
|
import { $L, scaleH, scaleW } from "../../../utils/helperMethods";
|
|
import {
|
|
setDefaultFocus,
|
|
setShowPopup,
|
|
fetchCurrentUserHomeTerms,
|
|
} from "../../../actions/homeActions";
|
|
import { changeAppStatus } from "../../../actions/commonActions";
|
|
import { setMyPageTermsAgree } from "../../../actions/myPageActions";
|
|
import { pushPanel } from "../../../actions/panelActions";
|
|
import {
|
|
requestPlayControl,
|
|
releasePlayControl,
|
|
} from "../../../actions/playActions";
|
|
import CustomImage from "../../../components/CustomImage/CustomImage";
|
|
import css from "./HomeBanner.module.less";
|
|
import Random from "./RandomUnit";
|
|
import Rolling from "./RollingUnit";
|
|
import RandomUnitNew from "./RandomUnit.new";
|
|
import TNewPopUp from "../../../components/TPopUp/TNewPopUp";
|
|
// import TButtonScroller from "../../../components/TButtonScroller/TButtonScroller";
|
|
import OptionalConfirm from "../../../components/Optional/OptionalConfirm";
|
|
// import * as Config from "../../../utils/Config";
|
|
import PersistentVideoUnit from "./PersistentVideoUnit";
|
|
|
|
const SpottableComponent = Spottable("div");
|
|
const Container = SpotlightContainerDecorator(
|
|
{ enterTo: "last-focused" },
|
|
"div",
|
|
);
|
|
const ContainerBasic = SpotlightContainerDecorator(
|
|
{ enterTo: "last-focused" },
|
|
"div",
|
|
);
|
|
|
|
export default function HomeBanner({
|
|
firstSpot,
|
|
spotlightId,
|
|
handleItemFocus,
|
|
handleShelfFocus,
|
|
}) {
|
|
const dispatch = useDispatch();
|
|
const homeTopDisplayInfo = useSelector(
|
|
(state) => state.home.homeTopDisplayInfo,
|
|
);
|
|
|
|
const bannerDataList = useSelector(
|
|
(state) => state.home.bannerData?.bannerInfos,
|
|
);
|
|
|
|
const popupVisible = useSelector((state) => state.common.popup.popupVisible);
|
|
|
|
const selectTemplate = useMemo(() => {
|
|
return homeTopDisplayInfo.shptmTmplCd;
|
|
}, [homeTopDisplayInfo]);
|
|
|
|
const _handleItemFocus = useCallback(() => {
|
|
if (handleItemFocus) {
|
|
handleItemFocus();
|
|
}
|
|
}, [handleItemFocus]);
|
|
|
|
const handleSecondBannerFocus = useCallback(() => {
|
|
const secondBannerData = bannerDataList?.[1];
|
|
if (secondBannerData) {
|
|
const randomData =
|
|
secondBannerData.bannerDetailInfos[secondBannerData.randomIndex];
|
|
const videoInfo = {
|
|
showUrl: randomData.showUrl,
|
|
patnrId: randomData.patnrId,
|
|
showId: randomData.showId,
|
|
shptmBanrTpNm: randomData.showId ? randomData.shptmBanrTpNm : "MEDIA",
|
|
lgCatCd: randomData.lgCatCd,
|
|
chanId: randomData.brdcChnlId,
|
|
modal: true,
|
|
modalContainerId: "banner1",
|
|
modalClassName: css.videoModal,
|
|
isVerticalModal: true, // Assuming second banner is horizontal, so modal is vertical
|
|
};
|
|
dispatch(requestPlayControl("banner1_preview", videoInfo));
|
|
}
|
|
if (handleItemFocus) {
|
|
handleItemFocus();
|
|
}
|
|
}, [dispatch, bannerDataList, handleItemFocus]);
|
|
|
|
const handleSecondBannerBlur = useCallback(() => {
|
|
dispatch(releasePlayControl("banner1_preview"));
|
|
}, [dispatch]);
|
|
|
|
const termsData = useSelector((state) => state.home.termsData);
|
|
const optionalTermsData = useSelector((state) =>
|
|
state.home.termsData?.data?.terms.find(
|
|
(term) => term.trmsTpCd === "MST00405",
|
|
),
|
|
);
|
|
const termsLoading = useSelector((state) => state.common.termsLoading);
|
|
const isGnbOpened = useSelector((state) => state.common.isGnbOpened);
|
|
// 선택약관 동의여부
|
|
const introTermsAgree = useSelector((state) => state.common.introTermsAgree);
|
|
|
|
//------------------------------------------------------------------------------
|
|
// 팝업표시 상태
|
|
const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] =
|
|
useState(false);
|
|
const [isOptionalTermsVisible, setIsOptionalTermsVisible] = useState(false);
|
|
|
|
// 선택약관 팝업 표시 여부
|
|
const shouldShowOptionalTermsPopup = useMemo(() => {
|
|
if (termsLoading || isGnbOpened) {
|
|
return false;
|
|
}
|
|
const terms = termsData?.data?.terms;
|
|
if (!terms) {
|
|
return false;
|
|
}
|
|
const optionalTerm = terms.find((term) => term.trmsTpCd === "MST00405");
|
|
return optionalTerm
|
|
? optionalTerm.trmsPopFlag === "Y" && optionalTerm.trmsAgrFlag === "N"
|
|
: false;
|
|
}, [termsData, termsLoading, isGnbOpened]);
|
|
|
|
const handleOptionalAgree = useCallback(() => {
|
|
console.log("handleAgree Click");
|
|
|
|
// 약관 동의할 항목들 (string array)
|
|
const termsList = ["TID0000222", "TID0000223", "TID0000232"];
|
|
// 동의하지 않을 항목들 (빈 배열)
|
|
const notTermsList = [];
|
|
console.log("OptionalTermsConfirm -약관 동의 API 호출 파라미터:", {
|
|
termsList,
|
|
notTermsList,
|
|
});
|
|
const callback = (response) => {
|
|
if (response.retCode === "000" || response.retCode === 0) {
|
|
console.log("약관 동의 성공:", response);
|
|
// 약관 정보 갱신
|
|
dispatch(fetchCurrentUserHomeTerms());
|
|
} else {
|
|
console.error("약관 동의 실패:", response);
|
|
}
|
|
};
|
|
|
|
console.log("OptionalTermsConfirm - 약관 동의 API 호출 payload:", {
|
|
termsList,
|
|
notTermsList,
|
|
});
|
|
dispatch(setMyPageTermsAgree({ termsList, notTermsList }, callback));
|
|
}, [dispatch]);
|
|
|
|
const handleOptionalTermsClick = useCallback(() => {
|
|
console.log("약관 자세히 보기 클릭");
|
|
setIsOptionalConfirmVisible(false);
|
|
setIsOptionalTermsVisible(true);
|
|
// 약관 상세 팝업을 띄우는 로직 추가
|
|
}, []);
|
|
|
|
const handleOptionalAgreeClick = useCallback(() => {
|
|
handleOptionalAgree();
|
|
setIsOptionalConfirmVisible(false);
|
|
}, []);
|
|
|
|
const handleOptionalDeclineClick = useCallback(() => {
|
|
console.log("거절/다음에 하기 버튼 클릭");
|
|
setIsOptionalConfirmVisible(false);
|
|
// 거절 처리 로직 추가
|
|
}, []);
|
|
|
|
// 선택약관 팝업 Close
|
|
const handleTermsPopupClosed = useCallback(() => {
|
|
setIsOptionalTermsVisible(false);
|
|
setIsOptionalConfirmVisible(true);
|
|
Spotlight.focus("optional-confirm-popup");
|
|
}, []);
|
|
|
|
// 선택약관 팝업 Agree
|
|
const handleTermsPopupAgree = useCallback(() => {
|
|
console.log("handleTermsPopupAgree");
|
|
handleOptionalAgree();
|
|
setIsOptionalTermsVisible(false);
|
|
}, []);
|
|
|
|
//------------------------------------------------------------------------------
|
|
const _handleShelfFocus = useCallback(() => {
|
|
if (handleShelfFocus) {
|
|
handleShelfFocus();
|
|
}
|
|
}, [handleShelfFocus]);
|
|
|
|
const defaultFocus = useMemo(() => {
|
|
if (bannerDataList) {
|
|
let targetIndex = 0;
|
|
for (let i = 0; i < bannerDataList.length; i++) {
|
|
const data = bannerDataList[i];
|
|
let bannerDetailInfos = data.bannerDetailInfos;
|
|
|
|
if (data.shptmDspyTpNm === "Random") {
|
|
if (
|
|
bannerDetailInfos[data.randomIndex].shptmBanrTpNm === "LIVE" ||
|
|
bannerDetailInfos[data.randomIndex].shptmBanrTpNm === "VOD"
|
|
) {
|
|
targetIndex = i;
|
|
break;
|
|
}
|
|
} else if (
|
|
bannerDetailInfos.find(
|
|
(el) => el.shptmBanrTpNm === "LIVE" || el.shptmBanrTpNm === "VOD",
|
|
)
|
|
) {
|
|
targetIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
return "banner" + targetIndex;
|
|
}
|
|
|
|
return null;
|
|
}, [bannerDataList]);
|
|
|
|
useEffect(() => {
|
|
if (firstSpot && defaultFocus && popupVisible === false) {
|
|
setTimeout(() => {
|
|
Spotlight.focus(defaultFocus);
|
|
}, 0);
|
|
}
|
|
|
|
if (defaultFocus) {
|
|
dispatch(setDefaultFocus(defaultFocus));
|
|
}
|
|
}, [defaultFocus, dispatch, popupVisible]);
|
|
|
|
// 테스트용 팝업 표시
|
|
// useEffect(() => {
|
|
// setTimeout(() => {
|
|
// console.log("App.js optionalTermsTest 팝업 표시");
|
|
// setIsOptionalConfirmVisible(true);
|
|
// // setIsOptionalTermsVisible(true);
|
|
// }, 1000);
|
|
// }, []);
|
|
|
|
// 약관 동의 및 선택 약관 팝업 처리
|
|
useEffect(() => {
|
|
if (termsLoading) {
|
|
// 약관 데이터 로딩 중에는 아무것도 하지 않음
|
|
return;
|
|
}
|
|
// 선택 약관 팝업을 띄워야 하는 경우
|
|
if (shouldShowOptionalTermsPopup) {
|
|
// 3초 후에 팝업을 띄우도록 설정
|
|
console.log("shouldShowOptionalTermsPopup", shouldShowOptionalTermsPopup);
|
|
console.log("App.js optionalTermsConfirm 팝업 표시");
|
|
const timer = setTimeout(() => {
|
|
setIsOptionalConfirmVisible(true);
|
|
// dispatch(setShowPopup({ activePopup: "optionalTermsConfirm" }));
|
|
}, 1000); // 3000 milliseconds = 3 seconds
|
|
|
|
// 컴포넌트 언마운트 시 타이머 클리어
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [shouldShowOptionalTermsPopup, termsLoading]);
|
|
|
|
// const renderItem = useCallback(
|
|
// (index, isHorizontal) => {
|
|
// const data = bannerDataList?.[index] ?? {};
|
|
|
|
// if (index === 1) {
|
|
// return (
|
|
// <div className={!isHorizontal ? css.imgBox : undefined}>
|
|
// <RandomUnitNew
|
|
// bannerData={data}
|
|
// isHorizontal={isHorizontal}
|
|
// key={"banner" + index}
|
|
// spotlightId={"banner" + index}
|
|
// handleShelfFocus={_handleShelfFocus}
|
|
// onFocus={handleSecondBannerFocus}
|
|
// onBlur={handleSecondBannerBlur}
|
|
// randomNumber={data.randomIndex}
|
|
// />
|
|
// </div>
|
|
// );
|
|
// }
|
|
|
|
// return (
|
|
// <div className={!isHorizontal ? css.imgBox : undefined}>
|
|
// {data.shptmDspyTpNm === "Rolling" ? (
|
|
// <Rolling
|
|
// bannerData={data}
|
|
// isHorizontal={isHorizontal}
|
|
// key={"banner" + index}
|
|
// spotlightId={"banner" + index}
|
|
// handleShelfFocus={_handleShelfFocus}
|
|
// handleItemFocus={_handleItemFocus}
|
|
// />
|
|
// ) : data.shptmDspyTpNm === "Random" ? (
|
|
// <Random
|
|
// bannerData={data}
|
|
// isHorizontal={isHorizontal}
|
|
// key={"banner" + index}
|
|
// spotlightId={"banner" + index}
|
|
// handleShelfFocus={_handleShelfFocus}
|
|
// handleItemFocus={_handleItemFocus}
|
|
// randomNumber={data.randomIndex}
|
|
// />
|
|
// ) : (
|
|
// <SpottableComponent spotlightId={"banner" + index}>
|
|
// <CustomImage
|
|
// delay={0}
|
|
// src={
|
|
// isHorizontal
|
|
// ? homeTopDisplayInfo.wdthtpImgPath1
|
|
// : homeTopDisplayInfo.vtctpImgPath1
|
|
// }
|
|
// aria-label={
|
|
// isHorizontal
|
|
// ? homeTopDisplayInfo.wdthtpImgNm1
|
|
// : homeTopDisplayInfo.vtctpImgNm1
|
|
// }
|
|
// />
|
|
// </SpottableComponent>
|
|
// )}
|
|
// </div>
|
|
// );
|
|
// },
|
|
// [
|
|
// bannerDataList,
|
|
// _handleItemFocus,
|
|
// _handleShelfFocus,
|
|
// handleSecondBannerFocus,
|
|
// handleSecondBannerBlur,
|
|
// ],
|
|
// );
|
|
|
|
const renderItem = useCallback(
|
|
(index, isHorizontal) => {
|
|
const data = bannerDataList?.[index] ?? {};
|
|
return (
|
|
<div className={!isHorizontal ? css.imgBox : undefined}>
|
|
{data.shptmDspyTpNm === "Rolling" ? (
|
|
<Rolling
|
|
bannerData={data}
|
|
isHorizontal={isHorizontal}
|
|
key={"banner" + index}
|
|
spotlightId={"banner" + index}
|
|
handleShelfFocus={_handleShelfFocus}
|
|
handleItemFocus={_handleItemFocus}
|
|
/>
|
|
) : data.shptmDspyTpNm === "Random" ? (
|
|
<Random
|
|
bannerData={data}
|
|
isHorizontal={isHorizontal}
|
|
key={"banner" + index}
|
|
spotlightId={"banner" + index}
|
|
handleShelfFocus={_handleShelfFocus}
|
|
handleItemFocus={_handleItemFocus}
|
|
randomNumber={data.randomIndex}
|
|
/>
|
|
) : (
|
|
<SpottableComponent spotlightId={"banner" + index}>
|
|
<CustomImage
|
|
delay={0}
|
|
src={
|
|
isHorizontal
|
|
? homeTopDisplayInfo.wdthtpImgPath1
|
|
: homeTopDisplayInfo.vtctpImgPath1
|
|
}
|
|
aria-label={
|
|
isHorizontal
|
|
? homeTopDisplayInfo.wdthtpImgNm1
|
|
: homeTopDisplayInfo.vtctpImgNm1
|
|
}
|
|
/>
|
|
</SpottableComponent>
|
|
)}
|
|
</div>
|
|
);
|
|
},
|
|
[_handleItemFocus, _handleShelfFocus, bannerDataList]
|
|
);
|
|
|
|
const renderItemPersistentVideo = useCallback(
|
|
(index, isHorizontal) => {
|
|
const data = bannerDataList?.[index] ?? {};
|
|
return (
|
|
<div className={!isHorizontal ? css.imgBox : undefined}>
|
|
{data.shptmDspyTpNm === "Rolling" ? (
|
|
<Rolling
|
|
bannerData={data}
|
|
isHorizontal={isHorizontal}
|
|
key={"banner" + index}
|
|
spotlightId={"banner" + index}
|
|
handleShelfFocus={_handleShelfFocus}
|
|
handleItemFocus={_handleItemFocus}
|
|
/>
|
|
) : data.shptmDspyTpNm === "Random" ? (
|
|
<PersistentVideoUnit
|
|
bannerData={data}
|
|
isHorizontal={isHorizontal}
|
|
key={"banner" + index}
|
|
spotlightId={"banner" + index}
|
|
handleShelfFocus={_handleShelfFocus}
|
|
handleItemFocus={_handleItemFocus}
|
|
randomNumber={data.randomIndex}
|
|
/>
|
|
) : (
|
|
<SpottableComponent spotlightId={"banner" + index}>
|
|
<CustomImage
|
|
delay={0}
|
|
src={
|
|
isHorizontal
|
|
? homeTopDisplayInfo.wdthtpImgPath1
|
|
: homeTopDisplayInfo.vtctpImgPath1
|
|
}
|
|
aria-label={
|
|
isHorizontal
|
|
? homeTopDisplayInfo.wdthtpImgNm1
|
|
: homeTopDisplayInfo.vtctpImgNm1
|
|
}
|
|
/>
|
|
</SpottableComponent>
|
|
)}
|
|
</div>
|
|
);
|
|
},
|
|
[_handleItemFocus, _handleShelfFocus, bannerDataList, homeTopDisplayInfo],
|
|
);
|
|
|
|
const renderLayout = useCallback(() => {
|
|
switch (selectTemplate) {
|
|
case "DSP00201": {
|
|
return (
|
|
<>
|
|
<ContainerBasic className={css.smallBox}>
|
|
{/* {renderItemPersistentVideo(0, true)} */}
|
|
{renderItem(0, true)}
|
|
{renderItem(1, true)}
|
|
</ContainerBasic>
|
|
{renderItem(2, false)}
|
|
{renderItem(3, false)}
|
|
</>
|
|
);
|
|
}
|
|
case "DSP00202": {
|
|
return (
|
|
<>
|
|
{renderItem(0, false)}
|
|
<ContainerBasic className={css.smallBox}>
|
|
{renderItem(1, true)}
|
|
{renderItem(2, true)}
|
|
</ContainerBasic>
|
|
{renderItem(3, false)}
|
|
</>
|
|
);
|
|
}
|
|
case "DSP00203": {
|
|
return (
|
|
<>
|
|
{renderItem(0, false)}
|
|
{renderItem(1, false)}
|
|
<ContainerBasic className={css.smallBox}>
|
|
{renderItem(2, true)}
|
|
{renderItem(3, true)}
|
|
</ContainerBasic>
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
return null;
|
|
}, [selectTemplate, renderItem, renderItemPersistentVideo]);
|
|
|
|
return (
|
|
<>
|
|
<Container
|
|
className={css.container}
|
|
spotlightId={spotlightId}
|
|
data-wheel-point={true}
|
|
>
|
|
<div className={css.homeTemplateBox}>{renderLayout()}</div>
|
|
</Container>
|
|
{/* 선택약관 동의 팝업 */}
|
|
<OptionalConfirm
|
|
open={isOptionalConfirmVisible}
|
|
spotlightId="optional-confirm-popup"
|
|
onClose={handleOptionalDeclineClick}
|
|
onOptionalTermsClick={handleOptionalTermsClick}
|
|
onOptionalAgreeClick={handleOptionalAgreeClick}
|
|
onOptionalDeclineClick={handleOptionalDeclineClick}
|
|
customPosition={true}
|
|
position={{
|
|
position: "absolute",
|
|
top: "342px", // 가운데를 기준으로 한 좌표 (1080/2) - 198
|
|
left: "0px",
|
|
bottom: "unset",
|
|
transform: "none",
|
|
}}
|
|
/>
|
|
{/* 선택약관 자세히 보기 팝업 */}
|
|
<TNewPopUp
|
|
kind="figmaTermsPopup"
|
|
open={isOptionalTermsVisible}
|
|
title={$L("Optional Terms")}
|
|
text={optionalTermsData?.trmsCntt || ""}
|
|
onClose={handleTermsPopupClosed}
|
|
onAgreeClick={handleTermsPopupAgree}
|
|
showAgreeButton={true}
|
|
/>
|
|
</>
|
|
);
|
|
}
|