[251123] fix: OptionalTerms->HomePanel로 이동
🕐 커밋 시간: 2025. 11. 23. 19:18:58 📊 변경 통계: • 총 파일: 3개 • 추가: +281줄 • 삭제: -483줄 📝 수정된 파일: ~ com.twin.app.shoptime/package-lock.json ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx (javascript): 🔄 Modified: SpotlightContainerDecorator() ❌ Deleted: callback() 📄 com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx (javascript): ✅ Added: callback() Performance: 코드 최적화로 성능 개선 기대
This commit is contained in:
290
com.twin.app.shoptime/package-lock.json
generated
290
com.twin.app.shoptime/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,19 +8,8 @@ import Spotlight from '@enact/spotlight';
|
|||||||
import { SpotlightContainerDecorator } from '@enact/spotlight/SpotlightContainerDecorator';
|
import { SpotlightContainerDecorator } from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
|
|
||||||
import { types } from '../../../actions/actionTypes';
|
import { changeAppStatus } from '../../../actions/commonActions';
|
||||||
import {
|
|
||||||
changeAppStatus,
|
|
||||||
handleOptionalTermsAgree as handleOptionalTermsAgreeAction,
|
|
||||||
handleOptionalTermsDecline,
|
|
||||||
setOptionalTermsPopupShown,
|
|
||||||
setOptionalTermsUserDecision,
|
|
||||||
updateOptionalTermsAgreement,
|
|
||||||
} from '../../../actions/commonActions';
|
|
||||||
import { justForYou } from '../../../actions/forYouActions';
|
import { justForYou } from '../../../actions/forYouActions';
|
||||||
import { fetchCurrentUserHomeTerms, setDefaultFocus } from '../../../actions/homeActions';
|
|
||||||
import { setMyPageTermsAgree } from '../../../actions/myPageActions';
|
|
||||||
import { popPanel, pushPanel } from '../../../actions/panelActions';
|
|
||||||
import {
|
import {
|
||||||
clearAllVideoTimers,
|
clearAllVideoTimers,
|
||||||
releasePlayControl,
|
releasePlayControl,
|
||||||
@@ -29,9 +18,6 @@ import {
|
|||||||
startVideoPlayerNew,
|
startVideoPlayerNew,
|
||||||
} from '../../../actions/playActions';
|
} from '../../../actions/playActions';
|
||||||
import CustomImage from '../../../components/CustomImage/CustomImage';
|
import CustomImage from '../../../components/CustomImage/CustomImage';
|
||||||
// import TButtonScroller from "../../../components/TButtonScroller/TButtonScroller";
|
|
||||||
import OptionalConfirm from '../../../components/Optional/OptionalConfirm';
|
|
||||||
import TNewPopUp from '../../../components/TPopUp/TNewPopUp';
|
|
||||||
import { useFocusHistory } from '../../../hooks/useFocusHistory/useFocusHistory';
|
import { useFocusHistory } from '../../../hooks/useFocusHistory/useFocusHistory';
|
||||||
// [COMMENTED OUT] useVideoMove 관련 코드 주석 처리 - 향후 사용 검토 필요
|
// [COMMENTED OUT] useVideoMove 관련 코드 주석 처리 - 향후 사용 검토 필요
|
||||||
// import { useVideoMove } from '../../../hooks/useVideoTransition/useVideoMove';
|
// import { useVideoMove } from '../../../hooks/useVideoTransition/useVideoMove';
|
||||||
@@ -113,215 +99,9 @@ export default function HomeBanner({
|
|||||||
}
|
}
|
||||||
}, [handleItemFocus]);
|
}, [handleItemFocus]);
|
||||||
|
|
||||||
const termsData = useSelector((state) => state.home.termsData);
|
|
||||||
const termsIdMap = useSelector((state) => state.home.termsIdMap);
|
|
||||||
const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable);
|
|
||||||
const optionalTermsData = useSelector((state) => {
|
|
||||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
|
||||||
if (state.home.termsData && state.home.termsData.data && state.home.termsData.data.terms) {
|
|
||||||
return state.home.termsData.data.terms.find((term) => term.trmsTpCd === 'MST00405');
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
const termsLoading = useSelector((state) => state.common.termsLoading);
|
|
||||||
const isGnbOpened = useSelector((state) => state.common.isGnbOpened);
|
|
||||||
const currentTermsFlag = useSelector((state) => state.common.termsFlag);
|
|
||||||
|
|
||||||
// 새로운 Redux 상태: 선택약관 팝업 플로우 관리
|
|
||||||
const optionalTermsPopupFlow = useSelector((state) => state.common.optionalTermsPopupFlow);
|
|
||||||
|
|
||||||
// 🔽 초기 비디오 재생 플래그 (1회만 실행되도록)
|
// 🔽 초기 비디오 재생 플래그 (1회만 실행되도록)
|
||||||
const isInitialVideoPlayRef = useRef(false);
|
const isInitialVideoPlayRef = useRef(false);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// 팝업표시 상태
|
|
||||||
const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = useState(false);
|
|
||||||
const [isOptionalTermsVisible, setIsOptionalTermsVisible] = useState(false);
|
|
||||||
|
|
||||||
const [optionalTermsAgreed, setOptionalTermsAgreed] = useState(false);
|
|
||||||
|
|
||||||
// 선택약관 팝업 표시 여부 ===================================================
|
|
||||||
const shouldShowOptionalTermsPopup = useMemo(() => {
|
|
||||||
// if (process.env.NODE_ENV === "development") {
|
|
||||||
// console.log("[HomeBanner] Step 1: 상태 확인", {
|
|
||||||
// termsLoading,
|
|
||||||
// isGnbOpened,
|
|
||||||
// optionalTermsAvailable,
|
|
||||||
// optionalTermsPopupFlow,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 1. 기본 조건 확인
|
|
||||||
if (termsLoading || isGnbOpened || !optionalTermsAvailable) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] Early return: 기본 조건 불만족');
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 새로운 Redux 상태 확인 (TV 환경 최적화)
|
|
||||||
if (
|
|
||||||
optionalTermsPopupFlow.popupShown ||
|
|
||||||
optionalTermsPopupFlow.userDecision ||
|
|
||||||
optionalTermsPopupFlow.agreedInSession
|
|
||||||
) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] Early return: 이미 처리됨', optionalTermsPopupFlow);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 서버 데이터 확인
|
|
||||||
const terms = termsData && termsData.data && termsData.data.terms;
|
|
||||||
// if (process.env.NODE_ENV === "development") {
|
|
||||||
// console.log("[HomeBanner] Step 2: termsData 확인", terms);
|
|
||||||
// }
|
|
||||||
if (!terms) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] Early return: terms가 존재하지 않음');
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionalTerm = terms.find((term) => term.trmsTpCd === 'MST00405');
|
|
||||||
// if (process.env.NODE_ENV === "development") {
|
|
||||||
// console.log("[HomeBanner] Step 3: optionalTerm 검색 결과", optionalTerm);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const result = optionalTerm
|
|
||||||
? optionalTerm.trmsPopFlag === 'Y' && optionalTerm.trmsAgrFlag === 'N'
|
|
||||||
: false;
|
|
||||||
|
|
||||||
// if (process.env.NODE_ENV === "development") {
|
|
||||||
// console.log("[HomeBanner] Step 4: 최종 결과", result);
|
|
||||||
// }
|
|
||||||
return result;
|
|
||||||
}, [
|
|
||||||
termsData.data?.terms,
|
|
||||||
termsLoading,
|
|
||||||
isGnbOpened,
|
|
||||||
optionalTermsAvailable,
|
|
||||||
optionalTermsPopupFlow,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 선택약관 팝업 표시 여부 ===================================================
|
|
||||||
|
|
||||||
const handleOptionalAgree = useCallback(() => {
|
|
||||||
// if (process.env.NODE_ENV === "development") {
|
|
||||||
// console.log("[HomeBanner] handleAgree Click");
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!termsIdMap || Object.keys(termsIdMap).length === 0) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.error('[HomeBanner] termsIdMap이 없습니다:', termsIdMap);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const requiredTermTypes = ['MST00401', 'MST00402', 'MST00405'];
|
|
||||||
const missingTerms = requiredTermTypes.filter((type) => !termsIdMap[type]);
|
|
||||||
|
|
||||||
if (missingTerms.length > 0) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.error('[HomeBanner] 누락된 약관 타입:', missingTerms);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const termsList = [];
|
|
||||||
|
|
||||||
if (termsIdMap['MST00401']) {
|
|
||||||
termsList.push(termsIdMap['MST00401']); // 개인정보처리방침
|
|
||||||
}
|
|
||||||
if (termsIdMap['MST00402']) {
|
|
||||||
termsList.push(termsIdMap['MST00402']); // 이용약관
|
|
||||||
}
|
|
||||||
if (termsIdMap['MST00405']) {
|
|
||||||
termsList.push(termsIdMap['MST00405']); // 선택약관
|
|
||||||
}
|
|
||||||
|
|
||||||
const notTermsList = [];
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] 현재 termsIdMap:', termsIdMap);
|
|
||||||
console.log('[HomeBanner] 약관 동의 API 호출 파라미터:', {
|
|
||||||
termsList,
|
|
||||||
notTermsList,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const callback = (response) => {
|
|
||||||
if (response.retCode === '000' || response.retCode === 0) {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] 약관 동의 성공:', response);
|
|
||||||
}
|
|
||||||
// ✅ IntroPanel과 동일한 방식으로 Redux 상태 직접 업데이트 (API 호출 없이)
|
|
||||||
dispatch(updateOptionalTermsAgreement(true));
|
|
||||||
// 로컬 상태도 업데이트 (기존 로직 유지)
|
|
||||||
setOptionalTermsAgreed(true);
|
|
||||||
} else {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.error('[HomeBanner] 약관 동의 실패:', response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] 약관 동의 API 호출 payload:', {
|
|
||||||
termsList,
|
|
||||||
notTermsList,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(setMyPageTermsAgree({ termsList, notTermsList }, callback));
|
|
||||||
}, [dispatch, termsIdMap]);
|
|
||||||
|
|
||||||
const handleOptionalTermsClick = useCallback(() => {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] 약관 자세히 보기 클릭');
|
|
||||||
}
|
|
||||||
setIsOptionalConfirmVisible(false);
|
|
||||||
setIsOptionalTermsVisible(true);
|
|
||||||
// 약관 상세 팝업을 띄우는 로직 추가
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleOptionalAgreeClick = useCallback(() => {
|
|
||||||
handleOptionalAgree();
|
|
||||||
setIsOptionalConfirmVisible(false);
|
|
||||||
dispatch({
|
|
||||||
type: types.GET_TERMS_AGREE_YN_SUCCESS,
|
|
||||||
payload: {
|
|
||||||
...currentTermsFlag,
|
|
||||||
optionalTerms: 'Y',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, [handleOptionalAgree]);
|
|
||||||
|
|
||||||
const handleOptionalDeclineClick = useCallback(() => {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] 거절/다음에 하기 버튼 클릭');
|
|
||||||
}
|
|
||||||
// ✅ 거절 상태 업데이트
|
|
||||||
dispatch(updateOptionalTermsAgreement(false));
|
|
||||||
setIsOptionalConfirmVisible(false);
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
// 선택약관 팝업 Close
|
|
||||||
const handleTermsPopupClosed = useCallback(() => {
|
|
||||||
setIsOptionalTermsVisible(false);
|
|
||||||
setIsOptionalConfirmVisible(true);
|
|
||||||
Spotlight.focus('optional-confirm-popup');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// 선택약관 팝업 Agree
|
|
||||||
const handleTermsPopupAgree = useCallback(() => {
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
console.log('[HomeBanner] handleTermsPopupAgree');
|
|
||||||
}
|
|
||||||
handleOptionalAgree();
|
|
||||||
setIsOptionalTermsVisible(false);
|
|
||||||
}, [handleOptionalAgree]);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
const _handleShelfFocus = useCallback(() => {
|
const _handleShelfFocus = useCallback(() => {
|
||||||
if (handleShelfFocus) {
|
if (handleShelfFocus) {
|
||||||
@@ -402,29 +182,6 @@ export default function HomeBanner({
|
|||||||
}
|
}
|
||||||
}, [bannerDataList, defaultFocus, dispatch]);
|
}, [bannerDataList, defaultFocus, dispatch]);
|
||||||
|
|
||||||
// 약관 동의 및 선택 약관 팝업 처리 (TV 환경 최적화)
|
|
||||||
useEffect(() => {
|
|
||||||
if (termsLoading) {
|
|
||||||
// 약관 데이터 로딩 중에는 아무것도 하지 않음
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 선택 약관 팝업을 띄워야 하는 경우
|
|
||||||
if (shouldShowOptionalTermsPopup && !isOptionalConfirmVisible) {
|
|
||||||
console.log('shouldShowOptionalTermsPopup', shouldShowOptionalTermsPopup);
|
|
||||||
console.log('App.js optionalTermsConfirm 팝업 표시');
|
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
setIsOptionalConfirmVisible(true);
|
|
||||||
// 팝업이 실제로 표시된 후에 Redux 상태 업데이트
|
|
||||||
dispatch(setOptionalTermsPopupShown(true));
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// 컴포넌트 언마운트 시 타이머 클리어
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
}
|
|
||||||
}, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]);
|
|
||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
(index, isHorizontal) => {
|
(index, isHorizontal) => {
|
||||||
const data = bannerDataList?.[index] ?? {};
|
const data = bannerDataList?.[index] ?? {};
|
||||||
@@ -560,33 +317,6 @@ export default function HomeBanner({
|
|||||||
<Container className={css.container} spotlightId={spotlightId} data-wheel-point={true}>
|
<Container className={css.container} spotlightId={spotlightId} data-wheel-point={true}>
|
||||||
<div className={css.homeTemplateBox}>{renderLayout()}</div>
|
<div className={css.homeTemplateBox}>{renderLayout()}</div>
|
||||||
</Container>
|
</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}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { types } from '../../actions/actionTypes';
|
||||||
import { applyMiddleware } from 'redux';
|
import { applyMiddleware } from 'redux';
|
||||||
|
|
||||||
import Spotlight from '@enact/spotlight';
|
import Spotlight from '@enact/spotlight';
|
||||||
@@ -16,6 +17,8 @@ import {
|
|||||||
setExitApp,
|
setExitApp,
|
||||||
setHidePopup,
|
setHidePopup,
|
||||||
setShowPopup,
|
setShowPopup,
|
||||||
|
setOptionalTermsPopupShown,
|
||||||
|
updateOptionalTermsAgreement,
|
||||||
} from '../../actions/commonActions';
|
} from '../../actions/commonActions';
|
||||||
import { getWelcomeEventInfo } from '../../actions/eventActions';
|
import { getWelcomeEventInfo } from '../../actions/eventActions';
|
||||||
import {
|
import {
|
||||||
@@ -23,8 +26,9 @@ import {
|
|||||||
getHomeLayout,
|
getHomeLayout,
|
||||||
getHomeMainContents,
|
getHomeMainContents,
|
||||||
updateHomeInfo,
|
updateHomeInfo,
|
||||||
// <<<<<<< HEAD
|
// <<<<<<< HEAD
|
||||||
} from '../../actions/homeActions';
|
} from '../../actions/homeActions';
|
||||||
|
import { setMyPageTermsAgree } from '../../actions/myPageActions';
|
||||||
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions';
|
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions';
|
||||||
import { getSubCategory, getTop20Show } from '../../actions/mainActions';
|
import { getSubCategory, getTop20Show } from '../../actions/mainActions';
|
||||||
import { getHomeOnSaleInfo } from '../../actions/onSaleActions';
|
import { getHomeOnSaleInfo } from '../../actions/onSaleActions';
|
||||||
@@ -38,6 +42,8 @@ import {
|
|||||||
import { getBestSeller } from '../../actions/productActions';
|
import { getBestSeller } from '../../actions/productActions';
|
||||||
import TBody from '../../components/TBody/TBody';
|
import TBody from '../../components/TBody/TBody';
|
||||||
import TButton, { TYPES } from '../../components/TButton/TButton';
|
import TButton, { TYPES } from '../../components/TButton/TButton';
|
||||||
|
import OptionalConfirm from '../../components/Optional/OptionalConfirm';
|
||||||
|
import TNewPopUp from '../../components/TPopUp/TNewPopUp';
|
||||||
import TPanel from '../../components/TPanel/TPanel';
|
import TPanel from '../../components/TPanel/TPanel';
|
||||||
import TPopUp from '../../components/TPopUp/TPopUp';
|
import TPopUp from '../../components/TPopUp/TPopUp';
|
||||||
import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator';
|
import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator';
|
||||||
@@ -185,6 +191,20 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
const topInfos = useSelector((state) => state.main.top20ShowData.topInfos);
|
const topInfos = useSelector((state) => state.main.top20ShowData.topInfos);
|
||||||
const isDeepLink = useSelector((state) => state.common.deepLinkInfo.isDeepLink);
|
const isDeepLink = useSelector((state) => state.common.deepLinkInfo.isDeepLink);
|
||||||
|
|
||||||
|
// 선택약관 관련 Redux 상태
|
||||||
|
const termsData = useSelector((state) => state.home.termsData);
|
||||||
|
const termsIdMap = useSelector((state) => state.home.termsIdMap);
|
||||||
|
const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable);
|
||||||
|
const optionalTermsData = useSelector((state) => {
|
||||||
|
if (state.home.termsData && state.home.termsData.data && state.home.termsData.data.terms) {
|
||||||
|
return state.home.termsData.data.terms.find((term) => term.trmsTpCd === 'MST00405');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
const termsLoading = useSelector((state) => state.common.termsLoading);
|
||||||
|
const currentTermsFlag = useSelector((state) => state.common.termsFlag);
|
||||||
|
const optionalTermsPopupFlow = useSelector((state) => state.common.optionalTermsPopupFlow);
|
||||||
|
|
||||||
const [btnDisabled, setBtnDisabled] = useState(true);
|
const [btnDisabled, setBtnDisabled] = useState(true);
|
||||||
const [arrowBottom, setArrowBottom] = useState(true);
|
const [arrowBottom, setArrowBottom] = useState(true);
|
||||||
const [firstSpot, setFirstSpot] = useState(false);
|
const [firstSpot, setFirstSpot] = useState(false);
|
||||||
@@ -193,6 +213,10 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
const [firstLgCatCd, setFirstLgCatCd] = useState(panelInfo.currentCatCd ?? null);
|
const [firstLgCatCd, setFirstLgCatCd] = useState(panelInfo.currentCatCd ?? null);
|
||||||
const [cateCd, setCateCd] = useState(panelInfo.currentCatCd ?? null);
|
const [cateCd, setCateCd] = useState(panelInfo.currentCatCd ?? null);
|
||||||
const [cateNm, setCateNm] = useState(panelInfo.currentCateName ?? null);
|
const [cateNm, setCateNm] = useState(panelInfo.currentCateName ?? null);
|
||||||
|
// 선택약관 팝업 상태
|
||||||
|
const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = useState(false);
|
||||||
|
const [isOptionalTermsVisible, setIsOptionalTermsVisible] = useState(false);
|
||||||
|
const [optionalTermsAgreed, setOptionalTermsAgreed] = useState(false);
|
||||||
const { entryMenu, nowMenu } = useSelector((state) => state.common.menu);
|
const { entryMenu, nowMenu } = useSelector((state) => state.common.menu);
|
||||||
const [focusedContainerId, setFocusedContainerId] = useState(panelInfo.focusedContainerId);
|
const [focusedContainerId, setFocusedContainerId] = useState(panelInfo.focusedContainerId);
|
||||||
// DetailPanel 진입 시 포커스 대상 저장
|
// DetailPanel 진입 시 포커스 대상 저장
|
||||||
@@ -271,6 +295,162 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
const loadingComplete = useSelector((state) => state.common?.loadingComplete);
|
const loadingComplete = useSelector((state) => state.common?.loadingComplete);
|
||||||
const isVideoTransitionLocked = useSelector((state) => state.home.videoTransitionLocked);
|
const isVideoTransitionLocked = useSelector((state) => state.home.videoTransitionLocked);
|
||||||
|
|
||||||
|
// 선택약관 동의 핸들러
|
||||||
|
const handleOptionalAgree = useCallback(() => {
|
||||||
|
if (!termsIdMap || Object.keys(termsIdMap).length === 0) {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.error('[HomePanel] termsIdMap이 없습니다:', termsIdMap);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requiredTermTypes = ['MST00401', 'MST00402', 'MST00405'];
|
||||||
|
const missingTerms = requiredTermTypes.filter((type) => !termsIdMap[type]);
|
||||||
|
|
||||||
|
if (missingTerms.length > 0) {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.error('[HomePanel] 누락된 약관 타입:', missingTerms);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const termsList = [];
|
||||||
|
|
||||||
|
if (termsIdMap['MST00401']) {
|
||||||
|
termsList.push(termsIdMap['MST00401']); // 개인정보처리방침
|
||||||
|
}
|
||||||
|
if (termsIdMap['MST00402']) {
|
||||||
|
termsList.push(termsIdMap['MST00402']); // 이용약관
|
||||||
|
}
|
||||||
|
if (termsIdMap['MST00405']) {
|
||||||
|
termsList.push(termsIdMap['MST00405']); // 선택약관
|
||||||
|
}
|
||||||
|
|
||||||
|
const notTermsList = [];
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('[HomePanel] 현재 termsIdMap:', termsIdMap);
|
||||||
|
console.log('[HomePanel] 약관 동의 API 호출 파라미터:', {
|
||||||
|
termsList,
|
||||||
|
notTermsList,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const callback = (response) => {
|
||||||
|
if (response.retCode === '000' || response.retCode === 0) {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('[HomePanel] 약관 동의 성공:', response);
|
||||||
|
}
|
||||||
|
dispatch(updateOptionalTermsAgreement(true));
|
||||||
|
setOptionalTermsAgreed(true);
|
||||||
|
} else {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.error('[HomePanel] 약관 동의 실패:', response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(setMyPageTermsAgree({ termsList, notTermsList }, callback));
|
||||||
|
}, [dispatch, termsIdMap]);
|
||||||
|
|
||||||
|
const handleOptionalTermsClick = useCallback(() => {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('[HomePanel] 약관 자세히 보기 클릭');
|
||||||
|
}
|
||||||
|
setIsOptionalConfirmVisible(false);
|
||||||
|
setIsOptionalTermsVisible(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleOptionalAgreeClick = useCallback(() => {
|
||||||
|
handleOptionalAgree();
|
||||||
|
setIsOptionalConfirmVisible(false);
|
||||||
|
dispatch({
|
||||||
|
type: types.GET_TERMS_AGREE_YN_SUCCESS,
|
||||||
|
payload: {
|
||||||
|
...currentTermsFlag,
|
||||||
|
optionalTerms: 'Y',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, [handleOptionalAgree, dispatch, currentTermsFlag]);
|
||||||
|
|
||||||
|
const handleOptionalDeclineClick = useCallback(() => {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('[HomePanel] 거절/다음에 하기 버튼 클릭');
|
||||||
|
}
|
||||||
|
dispatch(updateOptionalTermsAgreement(false));
|
||||||
|
setIsOptionalConfirmVisible(false);
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const handleTermsPopupClosed = useCallback(() => {
|
||||||
|
setIsOptionalTermsVisible(false);
|
||||||
|
setIsOptionalConfirmVisible(true);
|
||||||
|
Spotlight.focus('optional-confirm-popup');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleTermsPopupAgree = useCallback(() => {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('[HomePanel] handleTermsPopupAgree');
|
||||||
|
}
|
||||||
|
handleOptionalAgree();
|
||||||
|
setIsOptionalTermsVisible(false);
|
||||||
|
}, [handleOptionalAgree]);
|
||||||
|
|
||||||
|
// shouldShowOptionalTermsPopup 계산
|
||||||
|
const shouldShowOptionalTermsPopup = useMemo(() => {
|
||||||
|
// 1. 기본 조건 확인
|
||||||
|
if (termsLoading || isGnbOpened || !optionalTermsAvailable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 새로운 Redux 상태 확인 (TV 환경 최적화)
|
||||||
|
if (
|
||||||
|
optionalTermsPopupFlow.popupShown ||
|
||||||
|
optionalTermsPopupFlow.userDecision ||
|
||||||
|
optionalTermsPopupFlow.agreedInSession
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 서버 데이터 확인
|
||||||
|
const terms = termsData && termsData.data && termsData.data.terms;
|
||||||
|
if (!terms) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionalTerm = terms.find((term) => term.trmsTpCd === 'MST00405');
|
||||||
|
|
||||||
|
const result = optionalTerm
|
||||||
|
? optionalTerm.trmsPopFlag === 'Y' && optionalTerm.trmsAgrFlag === 'N'
|
||||||
|
: false;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, [
|
||||||
|
termsData.data?.terms,
|
||||||
|
termsLoading,
|
||||||
|
isGnbOpened,
|
||||||
|
optionalTermsAvailable,
|
||||||
|
optionalTermsPopupFlow,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 선택약관 팝업 표시 처리
|
||||||
|
useEffect(() => {
|
||||||
|
if (termsLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldShowOptionalTermsPopup && !isOptionalConfirmVisible) {
|
||||||
|
console.log('shouldShowOptionalTermsPopup', shouldShowOptionalTermsPopup);
|
||||||
|
console.log('HomePanel optionalTermsConfirm 팝업 표시');
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsOptionalConfirmVisible(true);
|
||||||
|
dispatch(setOptionalTermsPopupShown(true));
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}
|
||||||
|
}, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]);
|
||||||
|
|
||||||
const onCancel = useCallback(() => {
|
const onCancel = useCallback(() => {
|
||||||
const currentSpot = Spotlight.getCurrent();
|
const currentSpot = Spotlight.getCurrent();
|
||||||
|
|
||||||
@@ -773,7 +953,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
// 비디오가 재생이 아니면 videoPlayIntentRef의 bannerId로 비디오 재생
|
// 비디오가 재생이 아니면 videoPlayIntentRef의 bannerId로 비디오 재생
|
||||||
// [251116] isHomeOnTop인 경우에는 비디오가 항상 재생되어야 함
|
// [251116] isHomeOnTop인 경우에는 비디오가 항상 재생되어야 함
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// <<<<<<< HEAD
|
// <<<<<<< HEAD
|
||||||
// console.log('[HomeActive] useEffect 실행 - isOnTop:', isOnTop);
|
// console.log('[HomeActive] useEffect 실행 - isOnTop:', isOnTop);
|
||||||
// console.log('[HomeActive] videoPlayIntentRef.current:', videoPlayIntentRef.current);
|
// console.log('[HomeActive] videoPlayIntentRef.current:', videoPlayIntentRef.current);
|
||||||
// console.log(
|
// console.log(
|
||||||
@@ -990,23 +1170,23 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [detailPanelClosed, isOnTop, bannerDataList, dispatch]);
|
}, [detailPanelClosed, isOnTop, bannerDataList, dispatch]);
|
||||||
// =======
|
// =======
|
||||||
// const justCameBack = !prevIsOnTopRef.current && isOnTop;
|
// const justCameBack = !prevIsOnTopRef.current && isOnTop;
|
||||||
|
|
||||||
// if (
|
// if (
|
||||||
// justCameBack &&
|
// justCameBack &&
|
||||||
// panelInfo?.lastFocusedTargetId &&
|
// panelInfo?.lastFocusedTargetId &&
|
||||||
// panelInfo.lastFocusedTargetId !== lastRestoredIdRef.current
|
// panelInfo.lastFocusedTargetId !== lastRestoredIdRef.current
|
||||||
// ) {
|
// ) {
|
||||||
// lastRestoredIdRef.current = panelInfo.lastFocusedTargetId;
|
// lastRestoredIdRef.current = panelInfo.lastFocusedTargetId;
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// Spotlight.focus(panelInfo.lastFocusedTargetId);
|
// Spotlight.focus(panelInfo.lastFocusedTargetId);
|
||||||
// }, 150);
|
// }, 150);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// prevIsOnTopRef.current = isOnTop;
|
// prevIsOnTopRef.current = isOnTop;
|
||||||
// }, [isOnTop, panelInfo?.lastFocusedTargetId]);
|
// }, [isOnTop, panelInfo?.lastFocusedTargetId]);
|
||||||
// >>>>>>> gitlab/develop
|
// >>>>>>> gitlab/develop
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@@ -1031,12 +1211,12 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
currentSpot: currentSpot,
|
currentSpot: currentSpot,
|
||||||
currentCatCd: targetSpotlightCatcd,
|
currentCatCd: targetSpotlightCatcd,
|
||||||
currentCateName: targetSpotlightCateNm,
|
currentCateName: targetSpotlightCateNm,
|
||||||
// <<<<<<< HEAD
|
// <<<<<<< HEAD
|
||||||
focusedContainerId: focusedContainerIdRef.current,
|
focusedContainerId: focusedContainerIdRef.current,
|
||||||
lastFocusedTargetId: lastFocusedTargetRef.current || panelInfo.lastFocusedTargetId,
|
lastFocusedTargetId: lastFocusedTargetRef.current || panelInfo.lastFocusedTargetId,
|
||||||
// =======
|
// =======
|
||||||
// focusedContainerId: focusedContainerId,
|
// focusedContainerId: focusedContainerId,
|
||||||
// >>>>>>> gitlab/develop
|
// >>>>>>> gitlab/develop
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -1159,6 +1339,33 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
|||||||
{(activePopup === ACTIVE_POPUP.eventPopup || activePopup === ACTIVE_POPUP.smsPopup) && (
|
{(activePopup === ACTIVE_POPUP.eventPopup || activePopup === ACTIVE_POPUP.smsPopup) && (
|
||||||
<EventPopUpBanner />
|
<EventPopUpBanner />
|
||||||
)}
|
)}
|
||||||
|
{/* 선택약관 동의 팝업 */}
|
||||||
|
<OptionalConfirm
|
||||||
|
open={isOptionalConfirmVisible}
|
||||||
|
spotlightId="optional-confirm-popup"
|
||||||
|
onClose={handleOptionalDeclineClick}
|
||||||
|
onOptionalTermsClick={handleOptionalTermsClick}
|
||||||
|
onOptionalAgreeClick={handleOptionalAgreeClick}
|
||||||
|
onOptionalDeclineClick={handleOptionalDeclineClick}
|
||||||
|
customPosition={true}
|
||||||
|
position={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '385px',
|
||||||
|
left: '0px',
|
||||||
|
bottom: 'unset',
|
||||||
|
transform: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 선택약관 자세히 보기 팝업 */}
|
||||||
|
<TNewPopUp
|
||||||
|
kind="figmaTermsPopup"
|
||||||
|
open={isOptionalTermsVisible}
|
||||||
|
title={$L('Optional Terms')}
|
||||||
|
text={optionalTermsData?.trmsCntt || ''}
|
||||||
|
onClose={handleTermsPopupClosed}
|
||||||
|
onAgreeClick={handleTermsPopupAgree}
|
||||||
|
showAgreeButton={true}
|
||||||
|
/>
|
||||||
</TPanel>
|
</TPanel>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user