[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:
@@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { types } from '../../actions/actionTypes';
|
||||
import { applyMiddleware } from 'redux';
|
||||
|
||||
import Spotlight from '@enact/spotlight';
|
||||
@@ -16,6 +17,8 @@ import {
|
||||
setExitApp,
|
||||
setHidePopup,
|
||||
setShowPopup,
|
||||
setOptionalTermsPopupShown,
|
||||
updateOptionalTermsAgreement,
|
||||
} from '../../actions/commonActions';
|
||||
import { getWelcomeEventInfo } from '../../actions/eventActions';
|
||||
import {
|
||||
@@ -23,8 +26,9 @@ import {
|
||||
getHomeLayout,
|
||||
getHomeMainContents,
|
||||
updateHomeInfo,
|
||||
// <<<<<<< HEAD
|
||||
// <<<<<<< HEAD
|
||||
} from '../../actions/homeActions';
|
||||
import { setMyPageTermsAgree } from '../../actions/myPageActions';
|
||||
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions';
|
||||
import { getSubCategory, getTop20Show } from '../../actions/mainActions';
|
||||
import { getHomeOnSaleInfo } from '../../actions/onSaleActions';
|
||||
@@ -38,6 +42,8 @@ import {
|
||||
import { getBestSeller } from '../../actions/productActions';
|
||||
import TBody from '../../components/TBody/TBody';
|
||||
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 TPopUp from '../../components/TPopUp/TPopUp';
|
||||
import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator';
|
||||
@@ -185,6 +191,20 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
const topInfos = useSelector((state) => state.main.top20ShowData.topInfos);
|
||||
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 [arrowBottom, setArrowBottom] = useState(true);
|
||||
const [firstSpot, setFirstSpot] = useState(false);
|
||||
@@ -193,6 +213,10 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
const [firstLgCatCd, setFirstLgCatCd] = useState(panelInfo.currentCatCd ?? null);
|
||||
const [cateCd, setCateCd] = useState(panelInfo.currentCatCd ?? 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 [focusedContainerId, setFocusedContainerId] = useState(panelInfo.focusedContainerId);
|
||||
// DetailPanel 진입 시 포커스 대상 저장
|
||||
@@ -271,6 +295,162 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
const loadingComplete = useSelector((state) => state.common?.loadingComplete);
|
||||
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 currentSpot = Spotlight.getCurrent();
|
||||
|
||||
@@ -773,7 +953,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
// 비디오가 재생이 아니면 videoPlayIntentRef의 bannerId로 비디오 재생
|
||||
// [251116] isHomeOnTop인 경우에는 비디오가 항상 재생되어야 함
|
||||
useEffect(() => {
|
||||
// <<<<<<< HEAD
|
||||
// <<<<<<< HEAD
|
||||
// console.log('[HomeActive] useEffect 실행 - isOnTop:', isOnTop);
|
||||
// console.log('[HomeActive] videoPlayIntentRef.current:', videoPlayIntentRef.current);
|
||||
// console.log(
|
||||
@@ -990,23 +1170,23 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
}
|
||||
}
|
||||
}, [detailPanelClosed, isOnTop, bannerDataList, dispatch]);
|
||||
// =======
|
||||
// const justCameBack = !prevIsOnTopRef.current && isOnTop;
|
||||
// =======
|
||||
// const justCameBack = !prevIsOnTopRef.current && isOnTop;
|
||||
|
||||
// if (
|
||||
// justCameBack &&
|
||||
// panelInfo?.lastFocusedTargetId &&
|
||||
// panelInfo.lastFocusedTargetId !== lastRestoredIdRef.current
|
||||
// ) {
|
||||
// lastRestoredIdRef.current = panelInfo.lastFocusedTargetId;
|
||||
// setTimeout(() => {
|
||||
// Spotlight.focus(panelInfo.lastFocusedTargetId);
|
||||
// }, 150);
|
||||
// }
|
||||
// if (
|
||||
// justCameBack &&
|
||||
// panelInfo?.lastFocusedTargetId &&
|
||||
// panelInfo.lastFocusedTargetId !== lastRestoredIdRef.current
|
||||
// ) {
|
||||
// lastRestoredIdRef.current = panelInfo.lastFocusedTargetId;
|
||||
// setTimeout(() => {
|
||||
// Spotlight.focus(panelInfo.lastFocusedTargetId);
|
||||
// }, 150);
|
||||
// }
|
||||
|
||||
// prevIsOnTopRef.current = isOnTop;
|
||||
// }, [isOnTop, panelInfo?.lastFocusedTargetId]);
|
||||
// >>>>>>> gitlab/develop
|
||||
// prevIsOnTopRef.current = isOnTop;
|
||||
// }, [isOnTop, panelInfo?.lastFocusedTargetId]);
|
||||
// >>>>>>> gitlab/develop
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@@ -1031,12 +1211,12 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
currentSpot: currentSpot,
|
||||
currentCatCd: targetSpotlightCatcd,
|
||||
currentCateName: targetSpotlightCateNm,
|
||||
// <<<<<<< HEAD
|
||||
// <<<<<<< HEAD
|
||||
focusedContainerId: focusedContainerIdRef.current,
|
||||
lastFocusedTargetId: lastFocusedTargetRef.current || panelInfo.lastFocusedTargetId,
|
||||
// =======
|
||||
// focusedContainerId: focusedContainerId,
|
||||
// >>>>>>> gitlab/develop
|
||||
// =======
|
||||
// focusedContainerId: focusedContainerId,
|
||||
// >>>>>>> gitlab/develop
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -1159,6 +1339,33 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||
{(activePopup === ACTIVE_POPUP.eventPopup || activePopup === ACTIVE_POPUP.smsPopup) && (
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user