[251126] fix: Log Migration - DetailPanel sendLogGNB

🕐 커밋 시간: 2025. 11. 26. 12:45:16

📊 변경 통계:
  • 총 파일: 3개
  • 추가: +71줄
  • 삭제: -1줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx

🔧 주요 변경 내용:
  • 소규모 기능 개선
This commit is contained in:
2025-11-26 12:45:17 +09:00
parent d795182d4c
commit 42eda7e0bb
3 changed files with 71 additions and 1 deletions

View File

@@ -33,6 +33,11 @@ import {
setHidePopup, setHidePopup,
setShowPopup, setShowPopup,
} from '../../../actions/commonActions.js'; } from '../../../actions/commonActions.js';
import {
sendLogGNB,
} from '../../../actions/logActions';
import { updatePanel } from '../../../actions/panelActions';
import { panel_names } from '../../../utils/Config';
import { import {
getProductCouponDownload, getProductCouponDownload,
getProductCouponSearch, getProductCouponSearch,
@@ -59,7 +64,6 @@ import TVirtualGridList
import useReviews from '../../../hooks/useReviews/useReviews'; import useReviews from '../../../hooks/useReviews/useReviews';
import useScrollTo from '../../../hooks/useScrollTo'; import useScrollTo from '../../../hooks/useScrollTo';
import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig'; import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig';
import { panel_names } from '../../../utils/Config';
import * as Config from '../../../utils/Config.js'; import * as Config from '../../../utils/Config.js';
import { import {
andThen, andThen,
@@ -242,6 +246,7 @@ export default function ProductAllSection({
// Redux 상태 // Redux 상태
const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion); const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion);
const groupInfos = useSelector((state) => state.product.groupInfo); const groupInfos = useSelector((state) => state.product.groupInfo);
const nowMenu = useSelector((state) => state.common.menu.nowMenu);
// YouMayLike 데이터는 API 응답 시간이 걸리므로 직접 구독 // YouMayLike 데이터는 API 응답 시간이 걸리므로 직접 구독
const youmaylikeData = useSelector((state) => state.main.youmaylikeData); const youmaylikeData = useSelector((state) => state.main.youmaylikeData);
@@ -263,6 +268,18 @@ export default function ProductAllSection({
const [isShowQRCode, setIsShowQRCode] = useState(true); const [isShowQRCode, setIsShowQRCode] = useState(true);
const timerRef = useRef(null); const timerRef = useRef(null);
// sendLogGNB용 entryMenu
const entryMenuRef = useRef(null);
// 출처 정보 통합 (향후 확장성 대비)
// YouMayLike 상품이 아닐 경우 fromPanel을 초기화하여 오기 방지
const fromPanel = useMemo(() => ({
fromYouMayLike: panelInfo?.fromPanel?.fromYouMayLike || false,
// 향후 다른 출처 플래그들 추가 가능
// fromRecommendation: panelInfo?.fromPanel?.fromRecommendation || false,
// fromSearch: panelInfo?.fromPanel?.fromSearch || false,
}), [panelInfo?.fromPanel?.fromYouMayLike]);
//구매 하단 토스트 노출 확인을 위한 용도 //구매 하단 토스트 노출 확인을 위한 용도
const [openToast, setOpenToast] = useState(false); const [openToast, setOpenToast] = useState(false);
@@ -652,6 +669,45 @@ export default function ProductAllSection({
dispatch(resetShowAllReviews()); dispatch(resetShowAllReviews());
}, []); // 빈 dependency array = 마운트 시에만 실행 }, []); // 빈 dependency array = 마운트 시에만 실행
// sendLogGNB 로깅 - Source의 DetailPanel 컴포넌트들과 동일한 패턴
useEffect(() => {
if (!entryMenuRef.current) entryMenuRef.current = nowMenu;
// BUY NOW 버튼 활성화 상태에 따른 메뉴 결정 (Source SingleProduct vs UnableProduct 패턴)
let baseMenu;
if (isTravelProductVisible) {
baseMenu = Config.LOG_MENU.DETAIL_PAGE_TRAVEL_THEME_DETAIL;
} else if (isGroupProductVisible) {
baseMenu = Config.LOG_MENU.DETAIL_PAGE_GROUP_DETAIL;
} else if (isBillingProductVisible) {
// BUY NOW 버튼 활성화 = SingleProduct
baseMenu = Config.LOG_MENU.DETAIL_PAGE_BILLING_PRODUCT_DETAIL;
} else {
// BUY NOW 버튼 비활성화 = UnableProduct
baseMenu = Config.LOG_MENU.DETAIL_PAGE_PRODUCT_DETAIL;
}
// YouMayLike에서 상품 선택 시 메뉴 변경 (Source의 isYouMayLikeOpened와 동일 패턴)
const menu = (fromPanel?.fromYouMayLike !== undefined && fromPanel?.fromYouMayLike === true)
? `${baseMenu}/${Config.LOG_MENU.DETAIL_PAGE_YOU_MAY_LIKE}`
: baseMenu;
dispatch(sendLogGNB(menu));
// sendLogGNB 전송 후 플래그 초기화 (1회 사용 후 비활성화)
if (fromPanel?.fromYouMayLike === true) {
dispatch(updatePanel({
name: panel_names.DETAIL_PANEL,
panelInfo: {
...panelInfo,
fromPanel: {
fromYouMayLike: false // 플래그 초기화
}
}
}));
}
}, [fromPanel?.fromYouMayLike, isBillingProductVisible, isUnavailableProductVisible, isGroupProductVisible, isTravelProductVisible]); // BUY NOW 상태 변경 시 재실행
// [251115] 주석 처리: MediaPanel에서 이미 포커스 이동을 처리하므로 // [251115] 주석 처리: MediaPanel에서 이미 포커스 이동을 처리하므로
// ProductAllSection의 자동 포커스는 포커스 탈취를 일으킬 수 있음 // ProductAllSection의 자동 포커스는 포커스 탈취를 일으킬 수 있음
// useEffect(() => { // useEffect(() => {

View File

@@ -169,6 +169,9 @@ export default function YouMayAlsoLike({
prdtId, prdtId,
launchedFromPlayer: launchedFromPlayer, launchedFromPlayer: launchedFromPlayer,
bgVideoInfo: bgVideoInfo, // 백그라운드 비디오 정보 유지 bgVideoInfo: bgVideoInfo, // 백그라운드 비디오 정보 유지
fromPanel: {
fromYouMayLike: true, // YouMayLike에서 선택된 상품임을 표시
}, // 출처 정보 통합 객체
}, },
}) })
); );

View File

@@ -718,6 +718,13 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
panelInfo?.modal && panelInfo?.modal &&
liveLogParamsRef.current?.showId === panelInfo?.showId liveLogParamsRef.current?.showId === panelInfo?.showId
) { ) {
dlog('[PlayerPanel] 📡 LIVE Modal Log Ready and Conditions Met:', {
isModalLiveLogReady: logStatus.isModalLiveLogReady,
isOnTop,
isModal: panelInfo?.modal,
showIdMatch: liveLogParamsRef.current?.showId === panelInfo?.showId,
logParams: liveLogParamsRef.current,
});
let watchStrtDt = formatGMTString(new Date()); let watchStrtDt = formatGMTString(new Date());
watchIntervalLive.current = setInterval(() => { watchIntervalLive.current = setInterval(() => {
@@ -736,6 +743,10 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
isModalLiveLogReady: false, isModalLiveLogReady: false,
})); }));
clearInterval(watchIntervalLive.current); clearInterval(watchIntervalLive.current);
dlog('[PlayerPanel] 🚀 Dispatching LIVE Modal Log:', {
logParams: liveLogParamsRef.current,
watchStrtDt,
});
dispatch( dispatch(
sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () => sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () =>
dispatch(changeLocalSettings({ watchRecord: {} })) dispatch(changeLocalSettings({ watchRecord: {} }))