fix: 선택약관 4차수정 250622

This commit is contained in:
djaco
2025-06-22 22:19:57 +09:00
parent f0418b3c2b
commit 556a0e8456
23 changed files with 4437 additions and 477 deletions

View File

@@ -6,28 +6,38 @@ 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 { $L, scaleH, scaleW } from "../../../utils/helperMethods";
import {
setDefaultFocus,
setShowPopup,
fetchCurrentUserHomeTerms,
} from "../../../actions/homeActions";
import { changeAppStatus } from "../../../actions/commonActions";
import { setMyPageTermsAgree } from '../../../actions/myPageActions';
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 TButtonScroller from "../../../components/TButtonScroller/TButtonScroller";
import OptionalConfirm from "../../../components/Optional/OptionalConfirm";
import * as Config from "../../../utils/Config";
// import * as Config from "../../../utils/Config";
import PersistentVideoUnit from "./PersistentVideoUnit";
const SpottableComponent = Spottable("div");
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
"div",
);
const ContainerBasic = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
"div",
);
export default function HomeBanner({
@@ -38,11 +48,11 @@ export default function HomeBanner({
}) {
const dispatch = useDispatch();
const homeTopDisplayInfo = useSelector(
(state) => state.home.homeTopDisplayInfo
(state) => state.home.homeTopDisplayInfo,
);
const bannerDataList = useSelector(
(state) => state.home.bannerData?.bannerInfos
(state) => state.home.bannerData?.bannerInfos,
);
const popupVisible = useSelector((state) => state.common.popup.popupVisible);
@@ -57,9 +67,39 @@ export default function HomeBanner({
}
}, [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 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);
@@ -68,7 +108,8 @@ export default function HomeBanner({
//------------------------------------------------------------------------------
// 팝업표시 상태
const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = useState(false);
const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] =
useState(false);
const [isOptionalTermsVisible, setIsOptionalTermsVisible] = useState(false);
// 선택약관 팝업 표시 여부
@@ -80,35 +121,42 @@ export default function HomeBanner({
if (!terms) {
return false;
}
const optionalTerm = terms.find(term => term.trmsTpCd === "MST00405");
return optionalTerm ? optionalTerm.trmsPopFlag === 'Y' && optionalTerm.trmsAgrFlag === 'N' : 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');
console.log("handleAgree Click");
// 약관 동의할 항목들 (string array)
const termsList = ["TID0000222", "TID0000223", "TID0000232"];
const termsList = ["TID0000222", "TID0000223", "TID0000232"];
// 동의하지 않을 항목들 (빈 배열)
const notTermsList = [];
console.log('OptionalTermsConfirm -약관 동의 API 호출 파라미터:', { termsList, notTermsList });
console.log("OptionalTermsConfirm -약관 동의 API 호출 파라미터:", {
termsList,
notTermsList,
});
const callback = (response) => {
if (response.retCode === "000" || response.retCode === 0) {
console.log('약관 동의 성공:', response);
console.log("약관 동의 성공:", response);
// 약관 정보 갱신
dispatch(fetchCurrentUserHomeTerms());
} else {
console.error('약관 동의 실패:', response);
console.error("약관 동의 실패:", response);
}
};
console.log('OptionalTermsConfirm - 약관 동의 API 호출 payload:', { termsList, notTermsList });
console.log("OptionalTermsConfirm - 약관 동의 API 호출 payload:", {
termsList,
notTermsList,
});
dispatch(setMyPageTermsAgree({ termsList, notTermsList }, callback));
}, [dispatch]);
const handleOptionalTermsClick = useCallback(() => {
console.log('약관 자세히 보기 클릭');
console.log("약관 자세히 보기 클릭");
setIsOptionalConfirmVisible(false);
setIsOptionalTermsVisible(true);
// 약관 상세 팝업을 띄우는 로직 추가
@@ -120,7 +168,7 @@ export default function HomeBanner({
}, []);
const handleOptionalDeclineClick = useCallback(() => {
console.log('거절/다음에 하기 버튼 클릭');
console.log("거절/다음에 하기 버튼 클릭");
setIsOptionalConfirmVisible(false);
// 거절 처리 로직 추가
}, []);
@@ -135,11 +183,10 @@ export default function HomeBanner({
// 선택약관 팝업 Agree
const handleTermsPopupAgree = useCallback(() => {
console.log("handleTermsPopupAgree");
handleOptionalAgree();
setIsOptionalTermsVisible(false);
handleOptionalAgree();
setIsOptionalTermsVisible(false);
}, []);
//------------------------------------------------------------------------------
const _handleShelfFocus = useCallback(() => {
if (handleShelfFocus) {
@@ -164,7 +211,7 @@ export default function HomeBanner({
}
} else if (
bannerDetailInfos.find(
(el) => el.shptmBanrTpNm === "LIVE" || el.shptmBanrTpNm === "VOD"
(el) => el.shptmBanrTpNm === "LIVE" || el.shptmBanrTpNm === "VOD",
)
) {
targetIndex = i;
@@ -192,7 +239,7 @@ export default function HomeBanner({
// 테스트용 팝업 표시
// useEffect(() => {
// setTimeout(() => {
// console.log("App.js optionalTermsTest 팝업 표시");
// console.log("App.js optionalTermsTest 팝업 표시");
// setIsOptionalConfirmVisible(true);
// // setIsOptionalTermsVisible(true);
// }, 1000);
@@ -203,7 +250,7 @@ export default function HomeBanner({
if (termsLoading) {
// 약관 데이터 로딩 중에는 아무것도 하지 않음
return;
}
}
// 선택 약관 팝업을 띄워야 하는 경우
if (shouldShowOptionalTermsPopup) {
// 3초 후에 팝업을 띄우도록 설정
@@ -213,15 +260,33 @@ export default function HomeBanner({
setIsOptionalConfirmVisible(true);
// dispatch(setShowPopup({ activePopup: "optionalTermsConfirm" }));
}, 1000); // 3000 milliseconds = 3 seconds
// 컴포넌트 언마운트 시 타이머 클리어
return () => clearTimeout(timer);
}
}, [shouldShowOptionalTermsPopup, termsLoading]);
}, [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" ? (
@@ -263,7 +328,60 @@ export default function HomeBanner({
</div>
);
},
[_handleItemFocus, _handleShelfFocus, bannerDataList]
[
bannerDataList,
_handleItemFocus,
_handleShelfFocus,
handleSecondBannerFocus,
handleSecondBannerBlur,
],
);
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(() => {
@@ -272,6 +390,7 @@ export default function HomeBanner({
return (
<>
<ContainerBasic className={css.smallBox}>
{/* {renderItemPersistentVideo(0, true)} */}
{renderItem(0, true)}
{renderItem(1, true)}
</ContainerBasic>
@@ -306,7 +425,7 @@ export default function HomeBanner({
}
}
return null;
}, [selectTemplate, renderItem]);
}, [selectTemplate, renderItem, renderItemPersistentVideo]);
return (
<>
@@ -317,7 +436,7 @@ export default function HomeBanner({
>
<div className={css.homeTemplateBox}>{renderLayout()}</div>
</Container>
{/* 선택약관 동의 팝업 */}
{/* 선택약관 동의 팝업 */}
<OptionalConfirm
open={isOptionalConfirmVisible}
spotlightId="optional-confirm-popup"
@@ -327,41 +446,23 @@ export default function HomeBanner({
onOptionalDeclineClick={handleOptionalDeclineClick}
customPosition={true}
position={{
position: 'absolute',
top: '342px', // 가운데를 기준으로 한 좌표 (1080/2) - 198
left: '0px',
bottom: 'unset',
transform: 'none',
position: "absolute",
top: "342px", // 가운데를 기준으로 한 좌표 (1080/2) - 198
left: "0px",
bottom: "unset",
transform: "none",
}}
/>
{/* 선택약관 자세히 보기 팝업 */}
/>
{/* 선택약관 자세히 보기 팝업 */}
<TNewPopUp
kind="introTermsPopup"
kind="figmaTermsPopup"
open={isOptionalTermsVisible}
title={$L("Optional Terms")}
text={optionalTermsData?.trmsCntt || ""}
onClose={handleTermsPopupClosed}
onClick={handleTermsPopupClosed}
onIntroTermsAgreeClick={handleTermsPopupAgree}
hasButton
button1Text={$L("Close")}
>
{optionalTermsData && (
<div className={css.termsViewerContent}>
<div className={css.termsViewerTitle}>{$L("Optional Terms")}</div>
<TButtonScroller
boxHeight={scaleH(300)}
width={scaleW(980)}
className={css.termsDescription}
>
<div
className={css.termsDesc}
dangerouslySetInnerHTML={{
__html: optionalTermsData.trmsCntt,
}}
/>
</TButtonScroller>
</div>
)}
</TNewPopUp>
onAgreeClick={handleTermsPopupAgree}
showAgreeButton={true}
/>
</>
);
}