diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx index b57ed8e3..4dd01426 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx @@ -1,22 +1,11 @@ // src/views/HomePanel/HomeBanner/HomeBanner.jsx -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { - useDispatch, - useSelector, -} from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import Spotlight from '@enact/spotlight'; -import { - SpotlightContainerDecorator, -} from '@enact/spotlight/SpotlightContainerDecorator'; +import { SpotlightContainerDecorator } from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; import { types } from '../../../actions/actionTypes'; @@ -29,15 +18,9 @@ import { updateOptionalTermsAgreement, } from '../../../actions/commonActions'; import { justForYou } from '../../../actions/forYouActions'; -import { - fetchCurrentUserHomeTerms, - setDefaultFocus, -} from '../../../actions/homeActions'; +import { fetchCurrentUserHomeTerms, setDefaultFocus } from '../../../actions/homeActions'; import { setMyPageTermsAgree } from '../../../actions/myPageActions'; -import { - popPanel, - pushPanel, -} from '../../../actions/panelActions'; +import { popPanel, pushPanel } from '../../../actions/panelActions'; import { clearAllVideoTimers, releasePlayControl, @@ -49,10 +32,9 @@ 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 { useVideoMove } from '../../../hooks/useVideoTransition/useVideoMove'; +import { useFocusHistory } from '../../../hooks/useFocusHistory/useFocusHistory'; +// [COMMENTED OUT] useVideoMove 관련 코드 주석 처리 - 향후 사용 검토 필요 +// import { useVideoMove } from '../../../hooks/useVideoTransition/useVideoMove'; import { panel_names } from '../../../utils/Config'; import { $L } from '../../../utils/helperMethods'; import css from './HomeBanner.module.less'; @@ -65,53 +47,40 @@ import Random from './RandomUnit'; import Rolling from './RollingUnit'; import SimpleVideoContainer from './SimpleVideoContainer'; -const SpottableComponent = Spottable("div"); -const Container = SpotlightContainerDecorator( - { enterTo: "last-focused" }, - "div" -); -const ContainerBasic = SpotlightContainerDecorator( - { enterTo: "last-focused" }, - "div" -); +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, -}) { +export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, handleShelfFocus }) { const dispatch = useDispatch(); - useEffect(() => { + useEffect(() => { dispatch(justForYou()); }, [dispatch]); - const homeTopDisplayInfo = useSelector( - (state) => state.home.homeTopDisplayInfo - ); + const homeTopDisplayInfo = useSelector((state) => state.home.homeTopDisplayInfo); - const bannerDataList = useSelector( - (state) => state.home.bannerData?.bannerInfos - ); + const bannerDataList = useSelector((state) => state.home.bannerData?.bannerInfos); const popupVisible = useSelector((state) => state.common.popup.popupVisible); // 🔽 useFocusHistory - 경량화된 범용 포커스 히스토리 const focusHistory = useFocusHistory({ enableLogging: true, useGlobalState: true, - logPrefix: "[HomeBanner-Focus]", + logPrefix: '[HomeBanner-Focus]', }); // 🔽 useVideoMove - 포커스 전환 기반 동영상 제어 - const { playByTransition, cleanup } = useVideoMove({ - enableLogging: true, - logPrefix: "[HomeBanner-VideoMove]", - }); + // [COMMENTED OUT] useVideoMove 미사용 - playByTransition() 호출되지 않음 + // const { playByTransition, cleanup } = useVideoMove({ + // enableLogging: true, + // logPrefix: "[HomeBanner-VideoMove]", + // }); // 🔽 컴포넌트 언마운트 시 비디오 리소스 정리 useEffect(() => { return () => { // console.log('[HomeBanner] 컴포넌트 언마운트 - 비디오 리소스 정리'); - cleanup(); + // [COMMENTED OUT] useVideoMove cleanup 미사용 + // cleanup(); // 전역 비디오 타이머 정리 (메모리 누수 방지) clearAllVideoTimers(); @@ -126,7 +95,7 @@ export default function HomeBanner({ } } }; - }, [cleanup]); + }, []); // [COMMENTED OUT] cleanup 변수 제거 - useVideoMove 미사용으로 인한 의존성 제거 const selectTemplate = useMemo(() => { return homeTopDisplayInfo.shptmTmplCd; @@ -140,19 +109,11 @@ export default function HomeBanner({ const termsData = useSelector((state) => state.home.termsData); const termsIdMap = useSelector((state) => state.home.termsIdMap); - const optionalTermsAvailable = useSelector( - (state) => state.home.optionalTermsAvailable - ); + 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" - ); + 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; }); @@ -161,17 +122,14 @@ export default function HomeBanner({ const currentTermsFlag = useSelector((state) => state.common.termsFlag); // 새로운 Redux 상태: 선택약관 팝업 플로우 관리 - const optionalTermsPopupFlow = useSelector( - (state) => state.common.optionalTermsPopupFlow - ); + const optionalTermsPopupFlow = useSelector((state) => state.common.optionalTermsPopupFlow); // 🔽 초기 비디오 재생 플래그 (1회만 실행되도록) const isInitialVideoPlayRef = useRef(false); //------------------------------------------------------------------------------ // 팝업표시 상태 - const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = - useState(false); + const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] = useState(false); const [isOptionalTermsVisible, setIsOptionalTermsVisible] = useState(false); const [optionalTermsAgreed, setOptionalTermsAgreed] = useState(false); @@ -189,8 +147,8 @@ export default function HomeBanner({ // 1. 기본 조건 확인 if (termsLoading || isGnbOpened || !optionalTermsAvailable) { - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] Early return: 기본 조건 불만족"); + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] Early return: 기본 조건 불만족'); } return false; } @@ -201,11 +159,8 @@ export default function HomeBanner({ optionalTermsPopupFlow.userDecision || optionalTermsPopupFlow.agreedInSession ) { - if (process.env.NODE_ENV === "development") { - console.log( - "[HomeBanner] Early return: 이미 처리됨", - optionalTermsPopupFlow - ); + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] Early return: 이미 처리됨', optionalTermsPopupFlow); } return false; } @@ -216,19 +171,19 @@ export default function HomeBanner({ // console.log("[HomeBanner] Step 2: termsData 확인", terms); // } if (!terms) { - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] Early return: terms가 존재하지 않음"); + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] Early return: terms가 존재하지 않음'); } return false; } - const optionalTerm = terms.find((term) => term.trmsTpCd === "MST00405"); + 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" + ? optionalTerm.trmsPopFlag === 'Y' && optionalTerm.trmsAgrFlag === 'N' : false; // if (process.env.NODE_ENV === "development") { @@ -251,62 +206,62 @@ export default function HomeBanner({ // } if (!termsIdMap || Object.keys(termsIdMap).length === 0) { - if (process.env.NODE_ENV === "development") { - console.error("[HomeBanner] termsIdMap이 없습니다:", termsIdMap); + if (process.env.NODE_ENV === 'development') { + console.error('[HomeBanner] termsIdMap이 없습니다:', termsIdMap); } return; } - const requiredTermTypes = ["MST00401", "MST00402", "MST00405"]; + 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); + if (process.env.NODE_ENV === 'development') { + console.error('[HomeBanner] 누락된 약관 타입:', missingTerms); } return; } const termsList = []; - if (termsIdMap["MST00401"]) { - termsList.push(termsIdMap["MST00401"]); // 개인정보처리방침 + if (termsIdMap['MST00401']) { + termsList.push(termsIdMap['MST00401']); // 개인정보처리방침 } - if (termsIdMap["MST00402"]) { - termsList.push(termsIdMap["MST00402"]); // 이용약관 + if (termsIdMap['MST00402']) { + termsList.push(termsIdMap['MST00402']); // 이용약관 } - if (termsIdMap["MST00405"]) { - termsList.push(termsIdMap["MST00405"]); // 선택약관 + if (termsIdMap['MST00405']) { + termsList.push(termsIdMap['MST00405']); // 선택약관 } const notTermsList = []; - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] 현재 termsIdMap:", termsIdMap); - console.log("[HomeBanner] 약관 동의 API 호출 파라미터:", { + 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); + 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.error('[HomeBanner] 약관 동의 실패:', response); } } }; - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] 약관 동의 API 호출 payload:", { + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] 약관 동의 API 호출 payload:', { termsList, notTermsList, }); @@ -316,8 +271,8 @@ export default function HomeBanner({ }, [dispatch, termsIdMap]); const handleOptionalTermsClick = useCallback(() => { - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] 약관 자세히 보기 클릭"); + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] 약관 자세히 보기 클릭'); } setIsOptionalConfirmVisible(false); setIsOptionalTermsVisible(true); @@ -331,14 +286,14 @@ export default function HomeBanner({ type: types.GET_TERMS_AGREE_YN_SUCCESS, payload: { ...currentTermsFlag, - optionalTerms: "Y", + optionalTerms: 'Y', }, }); }, [handleOptionalAgree]); const handleOptionalDeclineClick = useCallback(() => { - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] 거절/다음에 하기 버튼 클릭"); + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] 거절/다음에 하기 버튼 클릭'); } // ✅ 거절 상태 업데이트 dispatch(updateOptionalTermsAgreement(false)); @@ -349,13 +304,13 @@ export default function HomeBanner({ const handleTermsPopupClosed = useCallback(() => { setIsOptionalTermsVisible(false); setIsOptionalConfirmVisible(true); - Spotlight.focus("optional-confirm-popup"); + Spotlight.focus('optional-confirm-popup'); }, []); // 선택약관 팝업 Agree const handleTermsPopupAgree = useCallback(() => { - if (process.env.NODE_ENV === "development") { - console.log("[HomeBanner] handleTermsPopupAgree"); + if (process.env.NODE_ENV === 'development') { + console.log('[HomeBanner] handleTermsPopupAgree'); } handleOptionalAgree(); setIsOptionalTermsVisible(false); @@ -375,24 +330,22 @@ export default function HomeBanner({ const data = bannerDataList[i]; let bannerDetailInfos = data.bannerDetailInfos; - if (data.shptmDspyTpNm === "Random") { + if (data.shptmDspyTpNm === 'Random') { if ( - bannerDetailInfos[data.randomIndex].shptmBanrTpNm === "LIVE" || - bannerDetailInfos[data.randomIndex].shptmBanrTpNm === "VOD" + bannerDetailInfos[data.randomIndex].shptmBanrTpNm === 'LIVE' || + bannerDetailInfos[data.randomIndex].shptmBanrTpNm === 'VOD' ) { targetIndex = i; break; } } else if ( - bannerDetailInfos.find( - (el) => el.shptmBanrTpNm === "LIVE" || el.shptmBanrTpNm === "VOD" - ) + bannerDetailInfos.find((el) => el.shptmBanrTpNm === 'LIVE' || el.shptmBanrTpNm === 'VOD') ) { targetIndex = i; break; } } - return "banner" + targetIndex; + return 'banner' + targetIndex; } return null; @@ -452,8 +405,8 @@ export default function HomeBanner({ // 선택 약관 팝업을 띄워야 하는 경우 if (shouldShowOptionalTermsPopup && !isOptionalConfirmVisible) { - console.log("shouldShowOptionalTermsPopup", shouldShowOptionalTermsPopup); - console.log("App.js optionalTermsConfirm 팝업 표시"); + console.log('shouldShowOptionalTermsPopup', shouldShowOptionalTermsPopup); + console.log('App.js optionalTermsConfirm 팝업 표시'); const timer = setTimeout(() => { setIsOptionalConfirmVisible(true); @@ -464,12 +417,7 @@ export default function HomeBanner({ // 컴포넌트 언마운트 시 타이머 클리어 return () => clearTimeout(timer); } - }, [ - shouldShowOptionalTermsPopup, - termsLoading, - isOptionalConfirmVisible, - dispatch, - ]); + }, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]); const renderItem = useCallback( (index, isHorizontal) => { @@ -478,37 +426,36 @@ export default function HomeBanner({ // videoPlayable을 동적으로 계산 // Random이나 Rolling 배너에서 LIVE 또는 VOD 타입의 비디오가 있는지 확인 const videoPlayerable = - (data.shptmDspyTpNm === "Random" || data.shptmDspyTpNm === "Rolling") && - data.bannerDetailInfos?.some(item => - item.shptmBanrTpNm === "LIVE" || - item.shptmBanrTpNm === "VOD" + (data.shptmDspyTpNm === 'Random' || data.shptmDspyTpNm === 'Rolling') && + data.bannerDetailInfos?.some( + (item) => item.shptmBanrTpNm === 'LIVE' || item.shptmBanrTpNm === 'VOD' ); return (
- {data.shptmDspyTpNm === "Rolling" ? ( + {data.shptmDspyTpNm === 'Rolling' ? ( - ) : data.shptmDspyTpNm === "Random" ? ( + ) : data.shptmDspyTpNm === 'Random' ? ( ) : ( - + @@ -536,7 +481,7 @@ export default function HomeBanner({ return (
@@ -551,7 +496,7 @@ export default function HomeBanner({ return (
@@ -563,7 +508,7 @@ export default function HomeBanner({ const renderLayout = useCallback(() => { switch (selectTemplate) { - case "DSP00201": { + case 'DSP00201': { return ( <> @@ -575,7 +520,7 @@ export default function HomeBanner({ ); } - case "DSP00202": { + case 'DSP00202': { return ( <> {renderItem(0, false)} @@ -587,7 +532,7 @@ export default function HomeBanner({ ); } - case "DSP00203": { + case 'DSP00203': { return ( <> {renderItem(0, false)} @@ -605,11 +550,7 @@ export default function HomeBanner({ return ( <> - +
{renderLayout()}
{/* 선택약관 동의 팝업 */} @@ -622,19 +563,19 @@ 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', }} /> {/* 선택약관 자세히 보기 팝업 */} { }); // 🔽 useVideoMove - 포커스 전환 기반 동영상 제어 - const { playByTransition, cleanup } = useVideoMove({ - enableLogging: true, - logPrefix: '[HomePanel-VideoMove]', - }); + // [COMMENTED OUT] useVideoMove 미사용 - cleanup() 호출되지 않음 + // const { playByTransition, cleanup } = useVideoMove({ + // enableLogging: true, + // logPrefix: '[HomePanel-VideoMove]', + // }); const isGnbOpened = useSelector((state) => state.common.isGnbOpened); const homeLayoutInfo = useSelector((state) => state.home.layoutData); const panelInfo = useSelector((state) => state.home.homeInfo?.panelInfo ?? {});