diff --git a/com.twin.app.shoptime/src/actions/empActions.js b/com.twin.app.shoptime/src/actions/empActions.js index 6e6ba8bd..a7ebb3ea 100644 --- a/com.twin.app.shoptime/src/actions/empActions.js +++ b/com.twin.app.shoptime/src/actions/empActions.js @@ -5,7 +5,7 @@ import { types } from './actionTypes'; // IF-LGSPM-373 EMP Shoptime 선택 약관 조회 export const getShoptimeTerms = () => (dispatch, getState) => { const onSuccess = (response) => { - console.log("getShoptimeTerms onSuccess ", response.data); + // console.log("getShoptimeTerms onSuccess ", response.data); dispatch({ type: types.GET_SHOPTIME_TERMS, @@ -14,17 +14,8 @@ export const getShoptimeTerms = () => (dispatch, getState) => { }; const onFail = (error) => { - console.error("getShoptimeTerms onFail ", error); + console.error('getShoptimeTerms onFail ', error); }; - TAxios( - dispatch, - getState, - "get", - URLS.GET_SHOPTIME_TERMS, - {}, - {}, - onSuccess, - onFail - ); + TAxios(dispatch, getState, 'get', URLS.GET_SHOPTIME_TERMS, {}, {}, onSuccess, onFail); }; diff --git a/com.twin.app.shoptime/src/hooks/useFocusHistory/useFocusHistory.js b/com.twin.app.shoptime/src/hooks/useFocusHistory/useFocusHistory.js index 527fb604..d8e50622 100644 --- a/com.twin.app.shoptime/src/hooks/useFocusHistory/useFocusHistory.js +++ b/com.twin.app.shoptime/src/hooks/useFocusHistory/useFocusHistory.js @@ -3,6 +3,21 @@ import { useRef, useCallback, useState, useMemo } from 'react'; import fp from '../../utils/fp.js'; +// Toggle debug logging in this file (false by default) +const DEBUG_MODE = false; + +const dlog = (...args) => { + if (DEBUG_MODE) console.log(...args); +}; + +const dwarn = (...args) => { + if (DEBUG_MODE) console.warn(...args); +}; + +const derror = (...args) => { + console.error(...args); +}; + /** * useFocusHistory Hook - 경량화된 포커스 히스토리 관리 * - 어떤 string 식별자든 받을 수 있는 범용적 구조 @@ -112,7 +127,7 @@ const createFocusRingBuffer = () => { // 직접 포커스 (banner1, banner2) if (current === 'banner1') { if (previous === 'icons') { - console.log('[DEBUG] 🔄 icons → banner1 복원 패턴'); + dlog('[DEBUG] 🔄 icons → banner1 복원 패턴'); return { pattern: 'restore-banner1', videoTarget: 'banner1', @@ -120,7 +135,7 @@ const createFocusRingBuffer = () => { shouldShowBorder: true, }; } - console.log('[DEBUG] 🎯 banner1 직접 포커스 패턴'); + dlog('[DEBUG] 🎯 banner1 직접 포커스 패턴'); return { pattern: 'direct-banner1', videoTarget: 'banner1', @@ -130,7 +145,7 @@ const createFocusRingBuffer = () => { } if (current === 'banner2') { if (previous === 'icons') { - console.log('[DEBUG] 🔄 icons → banner2 복원 패턴'); + dlog('[DEBUG] 🔄 icons → banner2 복원 패턴'); return { pattern: 'restore-banner2', videoTarget: 'banner2', @@ -138,7 +153,7 @@ const createFocusRingBuffer = () => { shouldShowBorder: true, }; } - console.log('[DEBUG] 🎯 banner2 직접 포커스 패턴'); + dlog('[DEBUG] 🎯 banner2 직접 포커스 패턴'); return { pattern: 'direct-banner2', videoTarget: 'banner2', @@ -161,8 +176,8 @@ const createFocusRingBuffer = () => { // 🔽 [개선] 간접 포커스 (banner3, banner4) - 더 깊은 히스토리 확인 if (current === 'banner3' || current === 'banner4') { - console.log(`[DEBUG] 🔍 간접 포커스 (${current}) - 히스토리 분석 시작`); - console.log(`[DEBUG] 전체 히스토리:`, history); + dlog(`[DEBUG] 🔍 간접 포커스 (${current}) - 히스토리 분석 시작`); + dlog(`[DEBUG] 전체 히스토리:`, history); // 히스토리에서 가장 최근의 banner1 또는 banner2 찾기 let lastVideoBanner = null; @@ -172,13 +187,13 @@ const createFocusRingBuffer = () => { if (history[i] === 'banner1' || history[i] === 'banner2') { lastVideoBanner = history[i]; lastVideoBannerDistance = i; - console.log(`[DEBUG] 발견된 비디오 배너: ${lastVideoBanner} (거리: ${i})`); + dlog(`[DEBUG] 발견된 비디오 배너: ${lastVideoBanner} (거리: ${i})`); break; // 가장 최근 것만 찾으면 됨 } } if (lastVideoBanner) { - console.log(`[DEBUG] 🔄 간접 포커스 유지 패턴:`, { + dlog(`[DEBUG] 🔄 간접 포커스 유지 패턴:`, { current: current, maintainTarget: lastVideoBanner, distance: lastVideoBannerDistance, @@ -192,7 +207,7 @@ const createFocusRingBuffer = () => { reason: `${current} 포커스, ${lastVideoBannerDistance}단계 이전 ${lastVideoBanner} 유지`, }; } else { - console.log(`[DEBUG] ❓ 간접 포커스 - 히스토리 없음:`, { + dlog(`[DEBUG] ❓ 간접 포커스 - 히스토리 없음:`, { current: current, history: history.slice(0, 5), reason: '비디오 배너 히스토리 없음, 기본값 banner1 사용', @@ -294,7 +309,7 @@ const isValidBuffer = (buffer) => { typeof buffer.clear === 'function' ); } catch (error) { - console.warn('[FocusHistory] 버퍼 유효성 검증 실패:', error); + dwarn('[FocusHistory] 버퍼 유효성 검증 실패:', error); return false; } }; @@ -319,10 +334,10 @@ const getGlobalObject = () => { // if (typeof globalThis !== 'undefined') return globalThis; // 최후의 수단 - 빈 객체 - console.warn('[FocusHistory] 전역 객체 접근 불가, 빈 객체 사용'); + dwarn('[FocusHistory] 전역 객체 접근 불가, 빈 객체 사용'); return {}; } catch (error) { - console.error('[FocusHistory] 전역 객체 접근 오류:', error); + derror('[FocusHistory] 전역 객체 접근 오류:', error); return {}; } }; @@ -337,14 +352,14 @@ const attemptBufferRestore = () => { const existingBuffer = globalObj[GLOBAL_BUFFER_KEY]; if (isValidBuffer(existingBuffer)) { - console.log('[FocusHistory] ✅ 기존 전역 버퍼 복원 성공'); + dlog('[FocusHistory] ✅ 기존 전역 버퍼 복원 성공'); return existingBuffer; } else if (existingBuffer) { - console.warn('[FocusHistory] ⚠️ 손상된 전역 버퍼 발견, 제거 후 재생성'); + dwarn('[FocusHistory] ⚠️ 손상된 전역 버퍼 발견, 제거 후 재생성'); delete globalObj[GLOBAL_BUFFER_KEY]; } } catch (error) { - console.error('[FocusHistory] 버퍼 복원 시도 실패:', error); + derror('[FocusHistory] 버퍼 복원 시도 실패:', error); } return null; }; @@ -369,10 +384,10 @@ const createAndRegisterBuffer = () => { } } - console.log('[FocusHistory] 🆕 새 전역 버퍼 생성 및 등록 완료'); + dlog('[FocusHistory] 🆕 새 전역 버퍼 생성 및 등록 완료'); return newBuffer; } catch (error) { - console.error('[FocusHistory] 버퍼 생성 및 등록 실패:', error); + derror('[FocusHistory] 버퍼 생성 및 등록 실패:', error); // 최후의 수단 - 로컬 버퍼라도 반환 return createFocusRingBuffer(); } @@ -401,7 +416,7 @@ const getOrCreateGlobalBuffer = () => { globalFocusBuffer = createAndRegisterBuffer(); return globalFocusBuffer; } catch (error) { - console.error('[FocusHistory] 전역 버퍼 초기화 실패:', error); + derror('[FocusHistory] 전역 버퍼 초기화 실패:', error); // 최후의 수단: 최소한의 로컬 버퍼라도 제공 try { @@ -410,7 +425,7 @@ const getOrCreateGlobalBuffer = () => { } return globalFocusBuffer; } catch (fallbackError) { - console.error('[FocusHistory] 폴백 버퍼 생성도 실패:', fallbackError); + derror('[FocusHistory] 폴백 버퍼 생성도 실패:', fallbackError); // 더미 버퍼 반환 (앱 크래시 방지) return { enqueue: () => ({ inserted: false, policy: null }), @@ -466,7 +481,7 @@ export const useFocusHistory = (options = {}) => { try { localBufferRef.current = createFocusRingBuffer(); } catch (error) { - console.error('[FocusHistory] 로컬 버퍼 생성 실패:', error); + derror('[FocusHistory] 로컬 버퍼 생성 실패:', error); // 더미 버퍼로 폴백 localBufferRef.current = { enqueue: () => ({ inserted: false, policy: null }), @@ -497,7 +512,7 @@ export const useFocusHistory = (options = {}) => { return localBufferRef.current; } } catch (error) { - console.error('[FocusHistory] 버퍼 초기화 전체 실패:', error); + derror('[FocusHistory] 버퍼 초기화 전체 실패:', error); // 최후의 더미 버퍼 return { enqueue: () => ({ inserted: false, policy: null }), @@ -532,13 +547,13 @@ export const useFocusHistory = (options = {}) => { try { // 입력값 검증 if (!focusId || typeof focusId !== 'string') { - console.warn(`${logPrefix} Invalid focus ID:`, focusId); + dwarn(`${logPrefix} Invalid focus ID:`, focusId); return { inserted: false, policy: null }; } // 버퍼 유효성 재검증 if (!isValidBuffer(buffer)) { - console.error(`${logPrefix} 버퍼가 손상됨, enqueue 실패`); + derror(`${logPrefix} 버퍼가 손상됨, enqueue 실패`); return { inserted: false, policy: null }; } @@ -556,11 +571,11 @@ export const useFocusHistory = (options = {}) => { // 🔽 [향상된 로깅] 패턴과 정책 정보 포함 if (previous && current && previous !== current) { - console.log(`${logPrefix} 🎯 ${previous} → ${current}`); - console.log(`${logPrefix} 📋 buffer:`, buffer.getHistory()); + dlog(`${logPrefix} 🎯 ${previous} → ${current}`); + dlog(`${logPrefix} 📋 buffer:`, buffer.getHistory()); } else { - console.log(`${logPrefix} 🎯 초기 포커스: ${current}`); - console.log(`${logPrefix} 📋 buffer:`, buffer.getHistory()); + dlog(`${logPrefix} 🎯 초기 포커스: ${current}`); + dlog(`${logPrefix} 📋 buffer:`, buffer.getHistory()); } // 디버그 모드에서는 전체 히스토리 표시 @@ -573,7 +588,7 @@ export const useFocusHistory = (options = {}) => { return result; // { inserted, policy } 반환 } catch (error) { - console.error(`${logPrefix} enqueue 실행 중 오류:`, error, { focusId }); + derror(`${logPrefix} enqueue 실행 중 오류:`, error, { focusId }); // 오류 발생 시 안전한 기본값 반환 return { inserted: false, policy: null }; } @@ -585,7 +600,7 @@ export const useFocusHistory = (options = {}) => { const getQueueState = useCallback(() => { try { if (!isValidBuffer(buffer)) { - console.warn(`${logPrefix} getQueueState: 버퍼 무효`); + dwarn(`${logPrefix} getQueueState: 버퍼 무효`); return { current: null, previous: null, @@ -597,7 +612,7 @@ export const useFocusHistory = (options = {}) => { } return buffer.getState(); } catch (error) { - console.error(`${logPrefix} getQueueState 오류:`, error); + derror(`${logPrefix} getQueueState 오류:`, error); return { current: null, previous: null, @@ -613,16 +628,16 @@ export const useFocusHistory = (options = {}) => { const clearHistory = useCallback(() => { try { if (!isValidBuffer(buffer)) { - console.warn(`${logPrefix} clearHistory: 버퍼 무효`); + dwarn(`${logPrefix} clearHistory: 버퍼 무효`); return; } buffer.clear(); triggerUpdate(); // 상태 변경 시 리렌더링 트리거 if (enableLogging) { - console.log(`${logPrefix} 히스토리 초기화됨`); + dlog(`${logPrefix} 히스토리 초기화됨`); } } catch (error) { - console.error(`${logPrefix} clearHistory 오류:`, error); + derror(`${logPrefix} clearHistory 오류:`, error); } }, [buffer, enableLogging, logPrefix, triggerUpdate]); @@ -641,7 +656,7 @@ export const useFocusHistory = (options = {}) => { } return buffer.getState(); } catch (error) { - console.error(`${logPrefix} currentState 계산 오류:`, error); + derror(`${logPrefix} currentState 계산 오류:`, error); return { current: null, previous: null, @@ -658,7 +673,7 @@ export const useFocusHistory = (options = {}) => { try { return isValidBuffer(buffer) ? buffer.getHistory() : []; } catch (error) { - console.error(`${logPrefix} getHistory 오류:`, error); + derror(`${logPrefix} getHistory 오류:`, error); return []; } }, [buffer, logPrefix]); @@ -668,7 +683,7 @@ export const useFocusHistory = (options = {}) => { try { return isValidBuffer(buffer) ? buffer.getHistoryAt(distance) : null; } catch (error) { - console.error(`${logPrefix} getHistoryAt 오류:`, error); + derror(`${logPrefix} getHistoryAt 오류:`, error); return null; } }, @@ -681,7 +696,7 @@ export const useFocusHistory = (options = {}) => { ? buffer.detectPattern() : { pattern: 'error', videoTarget: null, confidence: 0 }; } catch (error) { - console.error(`${logPrefix} detectPattern 오류:`, error); + derror(`${logPrefix} detectPattern 오류:`, error); return { pattern: 'error', videoTarget: null, confidence: 0 }; } }, [buffer, logPrefix]); @@ -692,7 +707,7 @@ export const useFocusHistory = (options = {}) => { ? buffer.calculateVideoPolicy() : { videoTarget: null, shouldShowBorder: false, transition: 'error', confidence: 0 }; } catch (error) { - console.error(`${logPrefix} calculateVideoPolicy 오류:`, error); + derror(`${logPrefix} calculateVideoPolicy 오류:`, error); return { videoTarget: null, shouldShowBorder: false, transition: 'error', confidence: 0 }; } }, [buffer, logPrefix]); @@ -703,7 +718,7 @@ export const useFocusHistory = (options = {}) => { ? buffer.getDebugInfo() : { error: 'Buffer invalid or unavailable' }; } catch (error) { - console.error(`${logPrefix} getDebugInfo 오류:`, error); + derror(`${logPrefix} getDebugInfo 오류:`, error); return { error: 'getDebugInfo failed', details: error.message }; } }, [buffer, logPrefix]); @@ -716,7 +731,7 @@ export const useFocusHistory = (options = {}) => { } return buffer.getHistory(); // 이미 최신순으로 정렬됨 [current, previous, older, oldest, ...] } catch (error) { - console.error(`${logPrefix} getQueue 오류:`, error); + derror(`${logPrefix} getQueue 오류:`, error); return []; } }, [buffer, logPrefix]); @@ -733,7 +748,7 @@ export const useFocusHistory = (options = {}) => { fp.map(fp.defaultTo(null)) // 각 항목도 null로 안전하게 처리 )(queue); } catch (error) { - console.error(`${logPrefix} getQueueSafe 오류:`, error); + derror(`${logPrefix} getQueueSafe 오류:`, error); return []; // 에러 시 빈 배열 } }, [getQueue, logPrefix]); diff --git a/com.twin.app.shoptime/src/lunaSend/common.js b/com.twin.app.shoptime/src/lunaSend/common.js index bdc3ba41..708267ff 100644 --- a/com.twin.app.shoptime/src/lunaSend/common.js +++ b/com.twin.app.shoptime/src/lunaSend/common.js @@ -1,11 +1,26 @@ -import appinfo from "../../webos-meta/appinfo.json"; -import { alertToast } from "../actions/commonActions"; -import { store } from "../store/store"; -import LS2Request from "./LS2Request"; +import appinfo from '../../webos-meta/appinfo.json'; +import { alertToast } from '../actions/commonActions'; +import { store } from '../store/store'; +import LS2Request from './LS2Request'; + +// Toggle debug logging for this module (false by default) +const DEBUG_MODE = false; + +const dlog = (...args) => { + if (DEBUG_MODE) console.log(...args); +}; + +const dwarn = (...args) => { + if (DEBUG_MODE) console.warn(...args); +}; + +const derror = (...args) => { + console.error(...args); +}; export const getConnectionStatus = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND getConnectionStatus"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND getConnectionStatus'); //test // setTimeout(() => { @@ -24,11 +39,11 @@ export const getConnectionStatus = ({ onSuccess, onFailure, onComplete }) => { // }, 20000); // }, 10000); - return "Some Hard Coded Mock Data"; + return 'Some Hard Coded Mock Data'; } else { return new LS2Request().send({ - service: "luna://com.webos.service.connectionmanager", - method: "getStatus", + service: 'luna://com.webos.service.connectionmanager', + method: 'getStatus', subscribe: true, parameters: {}, onSuccess, @@ -39,59 +54,51 @@ export const getConnectionStatus = ({ onSuccess, onFailure, onComplete }) => { }; export const createToast = (message) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND createToast message", message); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND createToast message', message); return; } return new LS2Request().send({ - service: "luna://com.webos.notification", - method: "createToast", + service: 'luna://com.webos.notification', + method: 'createToast', parameters: { message: message, - iconUrl: "", + iconUrl: '', noaction: true, }, onSuccess: (res) => { - console.log("LUNA SEND createToast success", message); + dlog('LUNA SEND createToast success', message); }, onFailure: (err) => { - console.log("LUNA SEND createToast failed", err); + derror('LUNA SEND createToast failed', err); }, }); }; let httpHeaderHandler = null; -export const getHttpHeaderForServiceRequest = ({ - onSuccess, - onFailure, - onComplete, -}) => { - if ( - typeof window === "object" && - window.PalmSystem && - process.env.REACT_APP_MODE !== "DEBUG" - ) { +export const getHttpHeaderForServiceRequest = ({ onSuccess, onFailure, onComplete }) => { + if (typeof window === 'object' && window.PalmSystem && process.env.REACT_APP_MODE !== 'DEBUG') { if (httpHeaderHandler) { httpHeaderHandler.cancel(); } httpHeaderHandler = new LS2Request().send({ - service: "luna://com.webos.service.sdx", - method: "getHttpHeaderForServiceRequest", + service: 'luna://com.webos.service.sdx', + method: 'getHttpHeaderForServiceRequest', subscribe: true, parameters: {}, onSuccess: (res) => { try { - console.log("[serverHost][LS2] onSuccess HOST:", res && res.HOST); - console.log("[serverHost][LS2] onSuccess raw:", res); + dlog('[serverHost][LS2] onSuccess HOST:', res && res.HOST); + dlog('[serverHost][LS2] onSuccess raw:', res); } catch (e) {} onSuccess && onSuccess(res); }, onFailure: (err) => { - console.log("[serverHost][LS2] onFailure:", err); + derror('[serverHost][LS2] onFailure:', err); onFailure && onFailure(err); }, onComplete: (res) => { - console.log("[serverHost][LS2] onComplete:", res); + dlog('[serverHost][LS2] onComplete:', res); onComplete && onComplete(res); }, }); @@ -99,64 +106,56 @@ export const getHttpHeaderForServiceRequest = ({ } else { const serverType = store.getState().localSettings.serverType; - const userNumber = - serverType === "prd" ? "US2412306099093" : "US2210240095608"; + const userNumber = serverType === 'prd' ? 'US2412306099093' : 'US2210240095608'; const mockRes = { - HOST: "qt2-US.nextlgsdp.com", - "X-User-Number": userNumber, + HOST: 'qt2-US.nextlgsdp.com', + 'X-User-Number': userNumber, Authorization: - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuZXh0bGdzZHAuY29tIiwiYXVkIjoibmV4dGxnc2RwLmNvbSIsImlhdCI6MTcwNzc4NTUyNSwiZXhwIjoxNzA3NzkyNzI1LCJtYWNBZGRyZXNzIjoiZWVkMDQ2NjdiNjUzOWU3YmQxMDA1OTljYjBkYTI5ZjRjZTgyZGZlOGZkNzIzMDAxZGVmMjg4NWRkNWZiODRmNWNiMzZlM2QwNzYzNWZjZGJjYWNjNGVjMzI5NWIwNjZjOTMwNmNmNDI1ZGQzMmQ2MDMxMjc1NWNkOTIyNjEwMzcifQ.vqPdYGnN46diesDBLzA4UhACCJVdIycLs7wZu9M55Hc", - "X-Authentication": "MkOLvUocrJ69RH/iV1ZABJhjR2g=", - "X-Device-ID": - "OemUY5qbPITZv96QKlxrtcqT6ypeX6us2qANLng3/0QCUhv2mecK1UDTMYb/hjpjey9dC/kFycc/5R8u+oK56JIWyYC4V278z64YDPKbDXIsd+eECvyf+Rdm8BneIUPM", - "X-Device-Product": "webOSTV 6.0", - "X-Device-Platform": "W21A", - "X-Device-Model": "HE_DTV_W20P_AFADATAA", - "X-Device-Eco-Info": "1", - "X-Device-Country": "US", - "X-Device-Language": "en-US", - "X-Device-Netcast-Platform-Version": "6.4.0", - "X-Device-Publish-Flag": "N", - "X-Device-Fck": "253", - "X-Device-SDK-VERSION": "1.0.0", - "X-Device-Eula": - "additionalDataAllowed,takeOnAllowed,networkAllowed,generalTermsAllowed,chpAllowed,customAdAllowed,acrOnAllowed,voice2Allowed,voiceAllowed,acrAdAllowed", + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuZXh0bGdzZHAuY29tIiwiYXVkIjoibmV4dGxnc2RwLmNvbSIsImlhdCI6MTcwNzc4NTUyNSwiZXhwIjoxNzA3NzkyNzI1LCJtYWNBZGRyZXNzIjoiZWVkMDQ2NjdiNjUzOWU3YmQxMDA1OTljYjBkYTI5ZjRjZTgyZGZlOGZkNzIzMDAxZGVmMjg4NWRkNWZiODRmNWNiMzZlM2QwNzYzNWZjZGJjYWNjNGVjMzI5NWIwNjZjOTMwNmNmNDI1ZGQzMmQ2MDMxMjc1NWNkOTIyNjEwMzcifQ.vqPdYGnN46diesDBLzA4UhACCJVdIycLs7wZu9M55Hc', + 'X-Authentication': 'MkOLvUocrJ69RH/iV1ZABJhjR2g=', + 'X-Device-ID': + 'OemUY5qbPITZv96QKlxrtcqT6ypeX6us2qANLng3/0QCUhv2mecK1UDTMYb/hjpjey9dC/kFycc/5R8u+oK56JIWyYC4V278z64YDPKbDXIsd+eECvyf+Rdm8BneIUPM', + 'X-Device-Product': 'webOSTV 6.0', + 'X-Device-Platform': 'W21A', + 'X-Device-Model': 'HE_DTV_W20P_AFADATAA', + 'X-Device-Eco-Info': '1', + 'X-Device-Country': 'US', + 'X-Device-Language': 'en-US', + 'X-Device-Netcast-Platform-Version': '6.4.0', + 'X-Device-Publish-Flag': 'N', + 'X-Device-Fck': '253', + 'X-Device-SDK-VERSION': '1.0.0', + 'X-Device-Eula': + 'additionalDataAllowed,takeOnAllowed,networkAllowed,generalTermsAllowed,chpAllowed,customAdAllowed,acrOnAllowed,voice2Allowed,voiceAllowed,acrAdAllowed', }; try { - console.log("[serverHost][LS2][MOCK] onSuccess HOST:", mockRes.HOST); - console.log("[serverHost][LS2][MOCK] onSuccess raw:", mockRes); + dlog('[serverHost][LS2][MOCK] onSuccess HOST:', mockRes.HOST); + dlog('[serverHost][LS2][MOCK] onSuccess raw:', mockRes); } catch (e) {} onSuccess(mockRes); } }; -export const getSystemSettings = ( - parameters, - { onSuccess, onFailure, onComplete } -) => { - if ( - typeof window === "object" && - window.PalmSystem && - process.env.REACT_APP_MODE !== "DEBUG" - ) { +export const getSystemSettings = (parameters, { onSuccess, onFailure, onComplete }) => { + if (typeof window === 'object' && window.PalmSystem && process.env.REACT_APP_MODE !== 'DEBUG') { return new LS2Request().send({ - service: "luna://com.webos.settingsservice", - method: "getSystemSettings", + service: 'luna://com.webos.settingsservice', + method: 'getSystemSettings', subscribe: true, parameters: parameters, onSuccess, onFailure, onComplete, }); - } else if (typeof window === "object") { + } else if (typeof window === 'object') { const language = - typeof window.navigator === "object" + typeof window.navigator === 'object' ? window.navigator.language || window.navigator.userLanguage - : "en-US"; + : 'en-US'; const res = { settings: { - smartServiceCountryCode2: language.split("-")[1], + smartServiceCountryCode2: language.split('-')[1], captionEnable: true, }, returnValue: true, @@ -167,17 +166,17 @@ export const getSystemSettings = ( }; export function checkValidCountry(ricCode, country) { - if (ricCode === "aic") { - if (country === "US") return true; + if (ricCode === 'aic') { + if (country === 'US') return true; else return false; - } else if (ricCode === "eic") { - if (country === "GB" || country === "DE") return true; + } else if (ricCode === 'eic') { + if (country === 'GB' || country === 'DE') return true; else return false; - } else if (ricCode === "ruc") { - if (country === "RU") return true; + } else if (ricCode === 'ruc') { + if (country === 'RU') return true; else return false; } else { - if (country === "US") { + if (country === 'US') { return true; } else { return false; @@ -186,20 +185,12 @@ export function checkValidCountry(ricCode, country) { } // 3.0 ~ 4.5 -export const setSubtitleEnable = ( - mediaId, - captionEnable, - { onSuccess, onFailure, onComplete } -) => { - if ( - typeof window === "object" && - window.PalmSystem && - process.env.REACT_APP_MODE !== "DEBUG" - ) { +export const setSubtitleEnable = (mediaId, captionEnable, { onSuccess, onFailure, onComplete }) => { + if (typeof window === 'object' && window.PalmSystem && process.env.REACT_APP_MODE !== 'DEBUG') { if (captionEnable) { return new LS2Request().send({ - service: "luna://com.webos.service.tv.subtitle", - method: "enableSubtitle", + service: 'luna://com.webos.service.tv.subtitle', + method: 'enableSubtitle', parameters: { pipelineId: mediaId }, onSuccess, onFailure, @@ -207,8 +198,8 @@ export const setSubtitleEnable = ( }); } else { return new LS2Request().send({ - service: "luna://com.webos.service.tv.subtitle", - method: "disableSubtitle", + service: 'luna://com.webos.service.tv.subtitle', + method: 'disableSubtitle', parameters: { pipelineId: mediaId }, onSuccess, onFailure, @@ -224,10 +215,10 @@ export const setSubtitleEnableOver5 = ( captionEnable, { onSuccess, onFailure, onComplete } ) => { - if (typeof window === "object" && window.PalmSystem) { + if (typeof window === 'object' && window.PalmSystem) { return new LS2Request().send({ - service: "luna://com.webos.media", - method: "setSubtitleEnable", + service: 'luna://com.webos.media', + method: 'setSubtitleEnable', parameters: { enable: captionEnable, mediaId: mediaId }, onSuccess, onFailure, @@ -238,17 +229,17 @@ export const setSubtitleEnableOver5 = ( // system Alert with time validation export const addReservation = (data, { onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND addReservation data", data); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND addReservation data', data); return; } const createReservation = () => { return new LS2Request().send({ - service: "luna://com.webos.service.tvReservationAgent", - method: "add", + service: 'luna://com.webos.service.tvReservationAgent', + method: 'add', parameters: { - scheduleType: "LGShopping", + scheduleType: 'LGShopping', startTime: { year: data.startTime.year, month: data.startTime.month, @@ -258,13 +249,13 @@ export const addReservation = (data, { onSuccess, onFailure, onComplete }) => { second: data.startTime.second, }, callback: { - method: "luna://com.webos.notification/createAlert", + method: 'luna://com.webos.notification/createAlert', params: { message: data.params.message, buttons: [ { label: data.params.buttons[0].label, - onclick: "luna://com.webos.applicationManager/launch", + onclick: 'luna://com.webos.applicationManager/launch', params: { id: window.PalmSystem.identifier ?? appinfo.id, params: data.params.launch, @@ -284,16 +275,10 @@ export const addReservation = (data, { onSuccess, onFailure, onComplete }) => { }, onSuccess, onFailure: (err) => { - console.log("LUNA SEND addReservation failed", err); + derror('LUNA SEND addReservation failed', err); // Check if error is related to invalid current time - if ( - err && - err.errorText && - err.errorText.includes("Invalid current time") - ) { - console.log( - "Invalid current time error detected, will retry after time validation" - ); + if (err && err.errorText && err.errorText.includes('Invalid current time')) { + dlog('Invalid current time error detected, will retry after time validation'); // Don't call onFailure immediately, let the retry logic handle it return; } @@ -305,33 +290,33 @@ export const addReservation = (data, { onSuccess, onFailure, onComplete }) => { // First, validate system time before creating reservation const validateTimeAndCreateReservation = (retryCount = 0, maxRetries = 3) => { - console.log(`LUNA SEND validating system time, attempt ${retryCount + 1}`); + dlog(`LUNA SEND validating system time, attempt ${retryCount + 1}`); getSystemTime({ onSuccess: (timeRes) => { - console.log("LUNA SEND system time validation success", timeRes); + dlog('LUNA SEND system time validation success', timeRes); // Time is available, proceed with reservation createReservation(); }, onFailure: (timeErr) => { - console.log("LUNA SEND system time validation failed", timeErr); + derror('LUNA SEND system time validation failed', timeErr); if (retryCount < maxRetries) { // Retry with exponential backoff const delay = Math.min(1000 * Math.pow(2, retryCount), 5000); // Max 5 seconds - console.log(`LUNA SEND retrying time validation in ${delay}ms`); + dlog(`LUNA SEND retrying time validation in ${delay}ms`); setTimeout(() => { validateTimeAndCreateReservation(retryCount + 1, maxRetries); }, delay); } else { - console.log("LUNA SEND max retries exceeded for time validation"); + dlog('LUNA SEND max retries exceeded for time validation'); // Still try to create reservation as fallback createReservation(); } }, onComplete: () => { - console.log("LUNA SEND system time validation complete"); + dlog('LUNA SEND system time validation complete'); }, }); }; @@ -340,21 +325,15 @@ export const addReservation = (data, { onSuccess, onFailure, onComplete }) => { validateTimeAndCreateReservation(); }; -export const deleteReservationCallback = ( - scheduleIdList, - { onSuccess, onFailure, onComplete } -) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log( - "LUNA SEND deleteReservationCallback scheduleIdList", - scheduleIdList - ); +export const deleteReservationCallback = (scheduleIdList, { onSuccess, onFailure, onComplete }) => { + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND deleteReservationCallback scheduleIdList', scheduleIdList); return; } return new LS2Request().send({ - service: "luna://com.webos.service.tvReservationAgent", - method: "delete", + service: 'luna://com.webos.service.tvReservationAgent', + method: 'delete', parameters: { scheduleIdList: scheduleIdList, }, @@ -365,19 +344,19 @@ export const deleteReservationCallback = ( }; export const deleteReservation = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND deleteReservation"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND deleteReservation'); return; } return new LS2Request().send({ - service: "luna://com.palm.db", - method: "search", + service: 'luna://com.palm.db', + method: 'search', parameters: { query: { - from: "com.webos.service.tvReservationAgent.info:1", - orderBy: "startTime", - filter: [{ prop: "reserveType", op: "=", val: 6 }], // 6 LG Shopping 전용. + from: 'com.webos.service.tvReservationAgent.info:1', + orderBy: 'startTime', + filter: [{ prop: 'reserveType', op: '=', val: 6 }], // 6 LG Shopping 전용. }, }, onSuccess, @@ -387,8 +366,8 @@ export const deleteReservation = ({ onSuccess, onFailure, onComplete }) => { }; export const deleteOldDb8 = (kind, { onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND deleteOldDb8"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND deleteOldDb8'); onSuccess && onSuccess(); return; } @@ -396,10 +375,10 @@ export const deleteOldDb8 = (kind, { onSuccess, onFailure, onComplete }) => { const id = window.PalmSystem.identifier ?? appinfo.id; return new LS2Request().send({ - service: "luna://com.webos.service.db", - method: "delKind", + service: 'luna://com.webos.service.db', + method: 'delKind', parameters: { - id: id + ":" + kind, + id: id + ':' + kind, }, onSuccess, onFailure, @@ -408,20 +387,20 @@ export const deleteOldDb8 = (kind, { onSuccess, onFailure, onComplete }) => { }; export const checkFirstLaunch = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND checkFirstLaunch"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND checkFirstLaunch'); return; } const id = window.PalmSystem.identifier ?? appinfo.id; return new LS2Request().send({ - service: "luna://com.webos.service.db", - method: "find", + service: 'luna://com.webos.service.db', + method: 'find', parameters: { query: { from: `${id}:20`, - where: [{ prop: "type", op: "=", val: "app_init" }], + where: [{ prop: 'type', op: '=', val: 'app_init' }], }, }, onSuccess, @@ -431,8 +410,8 @@ export const checkFirstLaunch = ({ onSuccess, onFailure, onComplete }) => { }; export const saveFirstLaunchInfo = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND saveFirstLaunchInfo"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND saveFirstLaunchInfo'); onSuccess({ returnValue: true }); return; } @@ -440,13 +419,13 @@ export const saveFirstLaunchInfo = ({ onSuccess, onFailure, onComplete }) => { const id = window.PalmSystem.identifier ?? appinfo.id; return new LS2Request().send({ - service: "luna://com.webos.service.db", - method: "put", + service: 'luna://com.webos.service.db', + method: 'put', parameters: { object: [ { _kind: `${id}:20`, - type: "app_init", + type: 'app_init', initialized: true, timestamp: new Date().toISOString(), }, @@ -459,14 +438,14 @@ export const saveFirstLaunchInfo = ({ onSuccess, onFailure, onComplete }) => { }; export const disableNotification = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND disableNotification"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND disableNotification'); return; } return new LS2Request().send({ - service: "luna://com.webos.notification", - method: "disable", + service: 'luna://com.webos.notification', + method: 'disable', parameters: {}, onSuccess, onFailure, @@ -475,14 +454,14 @@ export const disableNotification = ({ onSuccess, onFailure, onComplete }) => { }; export const enableNotification = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND enableNotification"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND enableNotification'); return; } return new LS2Request().send({ - service: "luna://com.webos.notification", - method: "enable", + service: 'luna://com.webos.notification', + method: 'enable', parameters: {}, onSuccess, onFailure, @@ -491,13 +470,13 @@ export const enableNotification = ({ onSuccess, onFailure, onComplete }) => { }; export const getConnectionInfo = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND disableConnectionInfo"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND disableConnectionInfo'); return; } else { return new LS2Request().send({ - service: "luna://com.webos.service.connectionmanager", - method: "getinfo", + service: 'luna://com.webos.service.connectionmanager', + method: 'getinfo', subscribe: false, parameters: {}, onSuccess, @@ -509,35 +488,35 @@ export const getConnectionInfo = ({ onSuccess, onFailure, onComplete }) => { // Check system time availability export const getSystemTime = ({ onSuccess, onFailure, onComplete }) => { - if (typeof window === "object" && !window.PalmSystem) { - console.log("LUNA SEND getSystemTime - mock environment"); + if (typeof window === 'object' && !window.PalmSystem) { + dlog('LUNA SEND getSystemTime - mock environment'); onSuccess({ returnValue: true, utc: Date.now() / 1000 }); return; } return new LS2Request().send({ - service: "luna://com.webos.settingsservice", - method: "getSystemSettings", + service: 'luna://com.webos.settingsservice', + method: 'getSystemSettings', subscribe: false, parameters: { - category: "time", - keys: ["autoClock"], + category: 'time', + keys: ['autoClock'], }, onSuccess: (res) => { - console.log("LUNA SEND getSystemTime success", res); + dlog('LUNA SEND getSystemTime success', res); if (res && res.returnValue) { // If autoClock is available, try to get actual time new LS2Request().send({ - service: "luna://com.webos.service.systemservice", - method: "clock/getTime", + service: 'luna://com.webos.service.systemservice', + method: 'clock/getTime', subscribe: false, parameters: {}, onSuccess: (timeRes) => { - console.log("LUNA SEND clock/getTime success", timeRes); + dlog('LUNA SEND clock/getTime success', timeRes); onSuccess(timeRes); }, onFailure: (timeErr) => { - console.log("LUNA SEND clock/getTime failed", timeErr); + derror('LUNA SEND clock/getTime failed', timeErr); // Fallback to settings response if getTime fails onSuccess(res); }, diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx index 4d534bb8..15a615f4 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx @@ -1,27 +1,12 @@ -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 { Job } from '@enact/core/util'; import Spotlight from '@enact/spotlight'; -import { - getCheckoutTotalAmt, - resetCheckoutData, -} from '../../actions/checkoutActions'; -import { - setHidePopup, - setShowPopup, -} from '../../actions/commonActions'; +import { getCheckoutTotalAmt, resetCheckoutData } from '../../actions/checkoutActions'; +import { setHidePopup, setShowPopup } from '../../actions/commonActions'; import { getShoptimeTerms } from '../../actions/empActions'; import { sendLogCheckOutBtnClick, @@ -30,10 +15,7 @@ import { sendLogPaymentEntry, sendLogTotalRecommend, } from '../../actions/logActions'; -import { - popPanel, - updatePanel, -} from '../../actions/panelActions'; +import { popPanel, updatePanel } from '../../actions/panelActions'; import TBody from '../../components/TBody/TBody'; import TButton from '../../components/TButton/TButton'; import TButtonScroller from '../../components/TButtonScroller/TButtonScroller'; @@ -46,11 +28,7 @@ import TQRCode from '../../components/TQRCode/TQRCode'; import useScrollTo from '../../hooks/useScrollTo'; import { BUYNOW_CONFIG } from '../../utils/BuyNowConfig'; import * as Config from '../../utils/Config'; -import { - $L, - scaleH, - scaleW, -} from '../../utils/helperMethods'; +import { $L, scaleH, scaleW } from '../../utils/helperMethods'; import { getSafeCurrencyInfo, getSafeFirstProduct, @@ -68,7 +46,7 @@ import SummaryContainer from './container/SummaryCotainer'; export default function CheckOutPanel({ panelInfo }) { // DEBUG_LOG 설정 - 이 값이 true일 때만 console.log가 실행됨 - const DEBUG_LOG = true; // 계속 활성화하여 디버깅 + const DEBUG_LOG = false; // 계속 활성화하여 디버깅 // console.log 오버라이드를 위한 ref const originalConsoleLog = useRef(); @@ -85,32 +63,75 @@ export default function CheckOutPanel({ panelInfo }) { } }; - console.log('%c[BuyOption][CheckOutPanel] ▶️ Component mounted START', 'background: blue; color: white; font-weight: bold; padding: 5px;'); - console.log('%c🚨🚨🚨 CHECKOUT PANEL PANELINFO ANALYSIS 🚨🚨🚨', 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;'); + console.log( + '%c[BuyOption][CheckOutPanel] ▶️ Component mounted START', + 'background: blue; color: white; font-weight: bold; padding: 5px;' + ); + console.log( + '%c🚨🚨🚨 CHECKOUT PANEL PANELINFO ANALYSIS 🚨🚨🚨', + 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;' + ); console.log('%cpanelInfo:', 'background: yellow; color: black; padding: 3px;', panelInfo); - console.log('%cpanelInfo.isFromCart:', 'background: yellow; color: black; padding: 3px;', panelInfo?.isFromCart); - console.log('%cpanelInfo.fromCartPanel:', 'background: yellow; color: black; padding: 3px;', panelInfo?.fromCartPanel); - console.log('%cpanelInfo.cartItems:', 'background: yellow; color: black; padding: 3px;', panelInfo?.cartItems); - console.log('%cpanelInfo.cartItems type:', 'background: yellow; color: black; padding: 3px;', typeof panelInfo?.cartItems); - console.log('%cpanelInfo.cartItems length:', 'background: yellow; color: black; padding: 3px;', panelInfo?.cartItems?.length); - console.log('%cpanelInfo.productInfo:', 'background: yellow; color: black; padding: 3px;', panelInfo?.productInfo); - console.log('%cpanelInfo.logInfo:', 'background: yellow; color: black; padding: 3px;', panelInfo?.logInfo); - console.log('[BuyOption][CheckOutPanel] Current panels:', panels?.map((p) => ({ name: p.name, hasModal: !!p.panelInfo?.modal }))); + console.log( + '%cpanelInfo.isFromCart:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.isFromCart + ); + console.log( + '%cpanelInfo.fromCartPanel:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.fromCartPanel + ); + console.log( + '%cpanelInfo.cartItems:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.cartItems + ); + console.log( + '%cpanelInfo.cartItems type:', + 'background: yellow; color: black; padding: 3px;', + typeof panelInfo?.cartItems + ); + console.log( + '%cpanelInfo.cartItems length:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.cartItems?.length + ); + console.log( + '%cpanelInfo.productInfo:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.productInfo + ); + console.log( + '%cpanelInfo.logInfo:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.logInfo + ); + console.log( + '[BuyOption][CheckOutPanel] Current panels:', + panels?.map((p) => ({ name: p.name, hasModal: !!p.panelInfo?.modal })) + ); // PlayerPanel 충돌 방지: PlayerPanel이 있고 modal 상태면 비활성화 - const playerPanelIndex = panels?.findIndex(p => - p.name === Config.panel_names.PLAYER_PANEL || - p.name === Config.panel_names.PLAYER_PANEL_NEW || - p.name === Config.panel_names.MEDIA_PANEL + const playerPanelIndex = panels?.findIndex( + (p) => + p.name === Config.panel_names.PLAYER_PANEL || + p.name === Config.panel_names.PLAYER_PANEL_NEW || + p.name === Config.panel_names.MEDIA_PANEL ); if (playerPanelIndex >= 0) { - console.log('[BuyOption][CheckOutPanel] 🚨 PlayerPanel/MediaPanel detected at index:', playerPanelIndex); + console.log( + '[BuyOption][CheckOutPanel] 🚨 PlayerPanel/MediaPanel detected at index:', + playerPanelIndex + ); console.log('[BuyOption][CheckOutPanel] PlayerPanel info:', panels[playerPanelIndex]); // PlayerPanel/MediaPanel 상태를 비활성화하여 CheckOutPanel과의 충돌 방지 if (panels[playerPanelIndex].panelInfo?.modal) { - console.log('[BuyOption][CheckOutPanel] 🔄 Disabling modal PlayerPanel to prevent conflicts'); + console.log( + '[BuyOption][CheckOutPanel] 🔄 Disabling modal PlayerPanel to prevent conflicts' + ); // 필요하다면 여기서 PlayerPanel 상태를 비활성화하는 액션을 디스패치할 수 있음 // dispatch(updatePanel({ // name: panels[playerPanelIndex].name, @@ -143,38 +164,97 @@ export default function CheckOutPanel({ panelInfo }) { // Mock Mode: panelInfo.productInfo 또는 Redux에서 상품 데이터 사용 const productData = BUYNOW_CONFIG.isMockMode() ? (() => { - console.log('%c🚨🚨🚨 MOCK MODE DATA SELECTION START 🚨🚨🚨', 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;'); - console.log('%cisFromCart condition check:', 'background: yellow; color: black; padding: 3px;'); - console.log('%c - panelInfo?.isFromCart:', 'background: yellow; color: black; padding: 3px;', panelInfo?.isFromCart); - console.log('%c - panelInfo?.cartItems exists:', 'background: yellow; color: black; padding: 3px;', !!panelInfo?.cartItems); - console.log('%c - Array.isArray(panelInfo?.cartItems):', 'background: yellow; color: black; padding: 3px;', Array.isArray(panelInfo?.cartItems)); - console.log('%c - panelInfo?.cartItems.length > 0:', 'background: yellow; color: black; padding: 3px;', panelInfo?.cartItems?.length > 0); + console.log( + '%c🚨🚨🚨 MOCK MODE DATA SELECTION START 🚨🚨🚨', + 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;' + ); + console.log( + '%cisFromCart condition check:', + 'background: yellow; color: black; padding: 3px;' + ); + console.log( + '%c - panelInfo?.isFromCart:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.isFromCart + ); + console.log( + '%c - panelInfo?.cartItems exists:', + 'background: yellow; color: black; padding: 3px;', + !!panelInfo?.cartItems + ); + console.log( + '%c - Array.isArray(panelInfo?.cartItems):', + 'background: yellow; color: black; padding: 3px;', + Array.isArray(panelInfo?.cartItems) + ); + console.log( + '%c - panelInfo?.cartItems.length > 0:', + 'background: yellow; color: black; padding: 3px;', + panelInfo?.cartItems?.length > 0 + ); // ✅ 1순위: CartPanel에서 전달된 cartItems (전체 카트 데이터) - if (panelInfo?.isFromCart && panelInfo?.cartItems && Array.isArray(panelInfo.cartItems) && panelInfo.cartItems.length > 0) { - console.log('%c✅ SUCCESS! Using cartItems from CartPanel (multi-product) ✅', 'background: green; color: white; font-weight: bold; font-size: 14px; padding: 5px;'); - console.log('%ccartItems:', 'background: green; color: white; padding: 3px;', panelInfo.cartItems); - console.log('%ccartItems count:', 'background: green; color: white; padding: 3px;', panelInfo.cartItems.length); + if ( + panelInfo?.isFromCart && + panelInfo?.cartItems && + Array.isArray(panelInfo.cartItems) && + panelInfo.cartItems.length > 0 + ) { + console.log( + '%c✅ SUCCESS! Using cartItems from CartPanel (multi-product) ✅', + 'background: green; color: white; font-weight: bold; font-size: 14px; padding: 5px;' + ); + console.log( + '%ccartItems:', + 'background: green; color: white; padding: 3px;', + panelInfo.cartItems + ); + console.log( + '%ccartItems count:', + 'background: green; color: white; padding: 3px;', + panelInfo.cartItems.length + ); return panelInfo.cartItems; } - console.log('%c❌ FAILED! isFromCart condition FAILED ❌', 'background: red; color: white; font-weight: bold; font-size: 14px; padding: 5px;'); - console.log('%cTrying next condition - productInfo check...', 'background: red; color: white; padding: 3px;'); + console.log( + '%c❌ FAILED! isFromCart condition FAILED ❌', + 'background: red; color: white; font-weight: bold; font-size: 14px; padding: 5px;' + ); + console.log( + '%cTrying next condition - productInfo check...', + 'background: red; color: white; padding: 3px;' + ); // 2순위: BuyOption에서 전달된 productInfo (단일 상품) if (panelInfo?.productInfo) { - console.log('%c[BuyOption][CheckOutPanel] ✅ Mock Mode - Using panelInfo.productInfo (single product):', 'background: green; color: white; font-weight: bold; padding: 5px;', panelInfo.productInfo); + console.log( + '%c[BuyOption][CheckOutPanel] ✅ Mock Mode - Using panelInfo.productInfo (single product):', + 'background: green; color: white; font-weight: bold; padding: 5px;', + panelInfo.productInfo + ); return [panelInfo.productInfo]; } // 3순위: Redux에서 가져온 상품 데이터 if (reduxProductData && Array.isArray(reduxProductData) && reduxProductData.length > 0) { - console.log('%c[BuyOption][CheckOutPanel] ✅ Mock Mode - Using reduxProductData:', 'background: green; color: white; font-weight: bold; padding: 5px;', 'count=' + reduxProductData.length); + console.log( + '%c[BuyOption][CheckOutPanel] ✅ Mock Mode - Using reduxProductData:', + 'background: green; color: white; font-weight: bold; padding: 5px;', + 'count=' + reduxProductData.length + ); return reduxProductData; } // 4순위: 기본 Hardcoded Mock 데이터 (최후의 fallback) - console.error('%c[BuyOption][CheckOutPanel] ⚠️ Mock Mode - Using fallback mock data:', 'background: orange; color: white; font-weight: bold; padding: 5px;', 'panelInfo=', panelInfo, 'reduxProductData=', reduxProductData); + console.error( + '%c[BuyOption][CheckOutPanel] ⚠️ Mock Mode - Using fallback mock data:', + 'background: orange; color: white; font-weight: bold; padding: 5px;', + 'panelInfo=', + panelInfo, + 'reduxProductData=', + reduxProductData + ); return [ { prdtId: 'MOCK_PRODUCT_1', @@ -192,16 +272,37 @@ export default function CheckOutPanel({ panelInfo }) { })() : reduxProductData; - console.log('%c🚨🚨🚨 FINAL PRODUCT DATA RESULT 🚨🚨🚨', 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;'); - console.log('%cisMockMode:', 'background: yellow; color: black; padding: 3px;', BUYNOW_CONFIG.isMockMode()); - console.log('%cproductData loaded:', 'background: yellow; color: black; padding: 3px;', productData && productData.length, 'items'); - console.log('%cproductData[0].prdtId:', 'background: yellow; color: black; padding: 3px;', productData?.[0]?.prdtId); - console.log('%cproductData length:', 'background: yellow; color: black; padding: 3px;', productData?.length || 0); + console.log( + '%c🚨🚨🚨 FINAL PRODUCT DATA RESULT 🚨🚨🚨', + 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;' + ); + console.log( + '%cisMockMode:', + 'background: yellow; color: black; padding: 3px;', + BUYNOW_CONFIG.isMockMode() + ); + console.log( + '%cproductData loaded:', + 'background: yellow; color: black; padding: 3px;', + productData && productData.length, + 'items' + ); + console.log( + '%cproductData[0].prdtId:', + 'background: yellow; color: black; padding: 3px;', + productData?.[0]?.prdtId + ); + console.log( + '%cproductData length:', + 'background: yellow; color: black; padding: 3px;', + productData?.length || 0 + ); console.log('%cproductData:', 'background: yellow; color: black; padding: 3px;', productData); // 표시용으로 모든 상품 데이터 정규화 (없는 필드는 안전한 기본값으로) // Mock 모드에서는 항상 정규화, API 모드에서는 그대로 사용 - const normalizedProductData = productData?.map((prod) => normalizeProductDataForDisplay(prod)) || []; + const normalizedProductData = + productData?.map((prod) => normalizeProductDataForDisplay(prod)) || []; const safeProductData = BUYNOW_CONFIG.isMockMode() ? normalizedProductData : productData; console.log('[BuyOption][CheckOutPanel] productData (normalized):', normalizedProductData); @@ -259,7 +360,10 @@ export default function CheckOutPanel({ panelInfo }) { const spotJob = useRef(new Job((func) => func(), 0)); useEffect(() => { - console.log('[BuyOption][CheckOutPanel] sendLogGNB useEffect - isOrderSuccessful:', isOrderSuccessful); + console.log( + '[BuyOption][CheckOutPanel] sendLogGNB useEffect - isOrderSuccessful:', + isOrderSuccessful + ); let nowMenu; if (isOrderSuccessful) { @@ -321,7 +425,9 @@ export default function CheckOutPanel({ panelInfo }) { // Mock Mode: API 호출 스킵 if (BUYNOW_CONFIG.isMockMode()) { - console.log('[BuyOption][CheckOutPanel] Mock Mode - Skipping checkout total amount calculation'); + console.log( + '[BuyOption][CheckOutPanel] Mock Mode - Skipping checkout total amount calculation' + ); return; } @@ -356,7 +462,9 @@ export default function CheckOutPanel({ panelInfo }) { infoForCheckoutData.dlvrAddrSno && infoForCheckoutData.bilAddrSno ) { - console.log('[BuyOption][CheckOutPanel] ✅ All conditions met - Calling getCheckoutTotalAmt'); + console.log( + '[BuyOption][CheckOutPanel] ✅ All conditions met - Calling getCheckoutTotalAmt' + ); dispatch( getCheckoutTotalAmt( { @@ -364,7 +472,7 @@ export default function CheckOutPanel({ panelInfo }) { dirPurcSelYn: cartSelectInfo.length > 0 ? 'N' : 'Y', bilAddrSno: infoForCheckoutData.bilAddrSno, dlvrAddrSno: infoForCheckoutData.dlvrAddrSno, - isPageLoading: "Y", + isPageLoading: 'Y', orderProductCoupontUse, }, totalAmtValidate @@ -428,12 +536,14 @@ export default function CheckOutPanel({ panelInfo }) { console.log('[CheckOutPanel] onBackClick - Sending reload signal to DetailPanel'); // DetailPanel에 재시작 신호 전달 - dispatch(updatePanel({ - name: Config.panel_names.DETAIL_PANEL, - panelInfo: { - shouldReload: true, - } - })); + dispatch( + updatePanel({ + name: Config.panel_names.DETAIL_PANEL, + panelInfo: { + shouldReload: true, + }, + }) + ); // CheckOutPanel 제거 dispatch(popPanel(Config.panel_names.CHECKOUT_PANEL)); @@ -442,7 +552,10 @@ export default function CheckOutPanel({ panelInfo }) { }, [dispatch, panels]); const toggleOrderSideBar = useCallback(() => { - console.log('[BuyOption][CheckOutPanel] toggleOrderSideBar called - current state:', orderSideBarOpen); + console.log( + '[BuyOption][CheckOutPanel] toggleOrderSideBar called - current state:', + orderSideBarOpen + ); if (!orderSideBarOpen) { dispatch(sendLogCheckOutBtnClick({ btnNm: 'ORDER ITEMS' })); dispatch( @@ -460,7 +573,10 @@ export default function CheckOutPanel({ panelInfo }) { }, [orderSideBarOpen, dispatch]); const toggleOfferSideBar = useCallback(() => { - console.log('[BuyOption][CheckOutPanel] toggleOfferSideBar called - current state:', offerSideBarOpen); + console.log( + '[BuyOption][CheckOutPanel] toggleOfferSideBar called - current state:', + offerSideBarOpen + ); if (!offerSideBarOpen) { dispatch(sendLogCheckOutBtnClick({ btnNm: 'OFFERS & PROMOTION' })); dispatch( @@ -489,7 +605,9 @@ export default function CheckOutPanel({ panelInfo }) { }, [dispatch]); const handlePopPanel = useCallback(() => { - console.log('[BuyOption][CheckOutPanel] handlePopPanel called - dispatching setHidePopup and popPanel'); + console.log( + '[BuyOption][CheckOutPanel] handlePopPanel called - dispatching setHidePopup and popPanel' + ); dispatch(setHidePopup()); dispatch(popPanel()); }, [dispatch]); @@ -564,12 +682,14 @@ export default function CheckOutPanel({ panelInfo }) { console.log('[CheckOutPanel] onCancelCheckoutPanel - Sending reload signal to DetailPanel'); // DetailPanel에 재시작 신호 전달 - dispatch(updatePanel({ - name: Config.panel_names.DETAIL_PANEL, - panelInfo: { - shouldReload: true, - } - })); + dispatch( + updatePanel({ + name: Config.panel_names.DETAIL_PANEL, + panelInfo: { + shouldReload: true, + }, + }) + ); // CheckOutPanel 제거 dispatch(popPanel(Config.panel_names.CHECKOUT_PANEL)); @@ -591,9 +711,7 @@ export default function CheckOutPanel({ panelInfo }) { dispatch(sendLogMyInfoEdit({ btnNm })); }, []); - const checkOutPanelInfo = panels.find( - (panel) => panel.name === "checkoutpanel" - )?.panelInfo; + const checkOutPanelInfo = panels.find((panel) => panel.name === 'checkoutpanel')?.panelInfo; console.log( '[CheckOutPanel] Rendering - orderSideBarOpen:', @@ -635,14 +753,14 @@ export default function CheckOutPanel({ panelInfo }) { fromCartPanel={panelInfo?.fromCartPanel} /> ) : ( */} - + {/* )} */} {/* {BUYNOW_CONFIG.isMockMode() ? ( ) : ( */} - + {/* )} */} @@ -740,8 +858,11 @@ export default function CheckOutPanel({ panelInfo }) { lastTotalPrice={checkOutPanelInfo?.estimatedTotal} /> -
- {console.log('%c[BuyOption][CheckOutPanel] ✅ Component rendering COMPLETE', 'background: lightgreen; color: black; font-weight: bold; padding: 5px;')} +
+ {console.log( + '%c[BuyOption][CheckOutPanel] ✅ Component rendering COMPLETE', + 'background: lightgreen; color: black; font-weight: bold; padding: 5px;' + )}
); diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx index f899b62f..cc068871 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx @@ -53,6 +53,21 @@ import usePrevious from '../../hooks/usePrevious'; import { useVideoPlay } from '../../hooks/useVideoPlay/useVideoPlay'; import ImagePreloader from '../../utils/ImagePreloader'; +// Toggle debug logging for this module (false by default) +const DEBUG_MODE = false; + +const dlog = (...args) => { + if (DEBUG_MODE) console.log(...args); +}; + +const dwarn = (...args) => { + if (DEBUG_MODE) console.warn(...args); +}; + +const derror = (...args) => { + console.error(...args); +}; + // DetailPanelBackground 이미지 imports for preloading import hsn from '../../../assets/images/bg/hsn_new.png'; import koreaKiosk from '../../../assets/images/bg/koreaKiosk_new.png'; @@ -233,23 +248,21 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { // HomePanel 마운트 시 백그라운드로 모든 파트너사 배경 이미지를 미리 로드하여 // DetailPanel 진입 시 로딩 지연을 방지함 useEffect(() => { - console.log('[HomePanel] Starting background image preloading...'); + dlog('[HomePanel] Starting background image preloading...'); // HomePanel의 다른 기능들에 영향을 주지 않도록 비동기로 조용히 실행 setTimeout(() => { ImagePreloader.preloadAllImages(BACKGROUND_IMAGES) .then((results) => { const successCount = results.filter((r) => r !== null).length; - console.log( - `[HomePanel] Background images preloaded: ${successCount}/${results.length} images` - ); + dlog(`[HomePanel] Background images preloaded: ${successCount}/${results.length} images`); // 프리로딩 통계 정보 로깅 (디버깅용) const stats = ImagePreloader.getStats(); - console.log('[HomePanel] Preloader stats:', stats); + dlog('[HomePanel] Preloader stats:', stats); }) .catch((error) => { - console.error('[HomePanel] Background image preloading failed:', error); + derror('[HomePanel] Background image preloading failed:', error); // 프리로딩 실패가 HomePanel 기능에 영향을 주지 않도록 조용히 처리 }); }, 1000); // HomePanel 안정화 후 1초 뒤 시작 @@ -299,7 +312,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const handleOptionalAgree = useCallback(() => { if (!termsIdMap || Object.keys(termsIdMap).length === 0) { if (process.env.NODE_ENV === 'development') { - console.error('[HomePanel] termsIdMap이 없습니다:', termsIdMap); + derror('[HomePanel] termsIdMap이 없습니다:', termsIdMap); } return; } @@ -309,7 +322,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { if (missingTerms.length > 0) { if (process.env.NODE_ENV === 'development') { - console.error('[HomePanel] 누락된 약관 타입:', missingTerms); + derror('[HomePanel] 누락된 약관 타입:', missingTerms); } return; } @@ -329,8 +342,8 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const notTermsList = []; if (process.env.NODE_ENV === 'development') { - console.log('[HomePanel] 현재 termsIdMap:', termsIdMap); - console.log('[HomePanel] 약관 동의 API 호출 파라미터:', { + dlog('[HomePanel] 현재 termsIdMap:', termsIdMap); + dlog('[HomePanel] 약관 동의 API 호출 파라미터:', { termsList, notTermsList, }); @@ -339,13 +352,13 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const callback = (response) => { if (response.retCode === '000' || response.retCode === 0) { if (process.env.NODE_ENV === 'development') { - console.log('[HomePanel] 약관 동의 성공:', response); + dlog('[HomePanel] 약관 동의 성공:', response); } dispatch(updateOptionalTermsAgreement(true)); setOptionalTermsAgreed(true); } else { if (process.env.NODE_ENV === 'development') { - console.error('[HomePanel] 약관 동의 실패:', response); + derror('[HomePanel] 약관 동의 실패:', response); } } }; @@ -355,7 +368,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const handleOptionalTermsClick = useCallback(() => { if (process.env.NODE_ENV === 'development') { - console.log('[HomePanel] 약관 자세히 보기 클릭'); + dlog('[HomePanel] 약관 자세히 보기 클릭'); } setIsOptionalConfirmVisible(false); setIsOptionalTermsVisible(true); @@ -375,7 +388,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const handleOptionalDeclineClick = useCallback(() => { if (process.env.NODE_ENV === 'development') { - console.log('[HomePanel] 거절/다음에 하기 버튼 클릭'); + dlog('[HomePanel] 거절/다음에 하기 버튼 클릭'); } dispatch(updateOptionalTermsAgreement(false)); setIsOptionalConfirmVisible(false); @@ -389,7 +402,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const handleTermsPopupAgree = useCallback(() => { if (process.env.NODE_ENV === 'development') { - console.log('[HomePanel] handleTermsPopupAgree'); + dlog('[HomePanel] handleTermsPopupAgree'); } handleOptionalAgree(); setIsOptionalTermsVisible(false); @@ -439,8 +452,8 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { } if (shouldShowOptionalTermsPopup && !isOptionalConfirmVisible) { - console.log('shouldShowOptionalTermsPopup', shouldShowOptionalTermsPopup); - console.log('HomePanel optionalTermsConfirm 팝업 표시'); + dlog('shouldShowOptionalTermsPopup', shouldShowOptionalTermsPopup); + dlog('HomePanel optionalTermsConfirm 팝업 표시'); const timer = setTimeout(() => { setIsOptionalConfirmVisible(true); @@ -812,14 +825,14 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { const _onFocusedContainerId = useCallback( (containerId) => { setFocusedContainerId(containerId); - console.log('[_onFocusedContainerId] 호출됨:', { + dlog('[_onFocusedContainerId] 호출됨:', { containerId, enterThroughGNB, isOnTop, condition: enterThroughGNB && cbChangePageRef.current && !isOnTop, }); if (enterThroughGNB && cbChangePageRef.current && !isOnTop) { - console.log('[_onFocusedContainerId] ⚠️ 맨 위로 스크롤 강제 실행!'); + dlog('[_onFocusedContainerId] ⚠️ 맨 위로 스크롤 강제 실행!'); Spotlight.resume(); cbChangePageRef.current(0, false); Spotlight.focus(defaultFocus); @@ -1034,7 +1047,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { // 🔽 videoPlayIntentRef가 null인 경우: 비디오 재생 가능한 첫 번째 배너 찾기 if (!videoPlayIntentRef.current && bannerDataList) { - console.log('[HomePanel] *** videoPlayIntentRef가 null - 첫 번째 비디오 배너 검색'); + dlog('[HomePanel] *** videoPlayIntentRef가 null - 첫 번째 비디오 배너 검색'); // HomeBanner.jsx의 defaultFocus 계산 로직과 동일 let targetIndex = 0; @@ -1069,7 +1082,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { if (targetBannerData && videoData) { const bannerId = 'banner' + targetIndex; - console.log('[HomePanel] *** 찾은 비디오 배너:', bannerId, videoData); + dlog('[HomePanel] *** 찾은 비디오 배너:', bannerId, videoData); // videoPlayIntentRef에 값 할당 (HomeBanner.jsx의 초기 재생 로직과 동일) videoPlayIntentRef.current = { @@ -1088,9 +1101,9 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { }; lastPlayedBannerIdRef.current = bannerId; - console.log('[HomePanel] *** videoPlayIntentRef 설정 완료:', videoPlayIntentRef.current); + dlog('[HomePanel] *** videoPlayIntentRef 설정 완료:', videoPlayIntentRef.current); } else { - console.log('[HomePanel] *** ⚠️ 비디오 재생 가능한 배너를 찾지 못함'); + dlog('[HomePanel] *** ⚠️ 비디오 재생 가능한 배너를 찾지 못함'); } } @@ -1104,7 +1117,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { // 🔽 [251118] 현재 스크롤 위치 확인하여 비디오 크기 결정 const currentScrollTop = prevScrollTopRef.current; const shouldShrink = currentScrollTop > 0; - console.log( + dlog( '[HomePanel] *** 비디오 복구 - currentScrollTop:', currentScrollTop, ', shouldShrink:', @@ -1130,9 +1143,9 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { ); // 🔽 DetailPanel에서 돌아온 뒤 포커스를 마지막 포커스 대상에 복원 - console.log('[HomePanel] *** 🎯 Focus 복원 준비'); + dlog('[HomePanel] *** 🎯 Focus 복원 준비'); const targetFocusId = panelInfo.lastFocusedTargetId || lastFocusedTargetRef.current; - console.log( + dlog( '[HomePanel] *** 📍 targetFocusId:', targetFocusId, '(panelInfo.lastFocusedTargetId:', @@ -1142,13 +1155,13 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { ')' ); if (targetFocusId) { - console.log('[HomePanel] *** ⏰ 300ms 후 Spotlight.focus 호출 예정'); + dlog('[HomePanel] *** ⏰ 300ms 후 Spotlight.focus 호출 예정'); setTimeout(() => { - console.log('[HomePanel] *** 🔍 Spotlight.focus 호출:', targetFocusId); + dlog('[HomePanel] *** 🔍 Spotlight.focus 호출:', targetFocusId); Spotlight.focus(targetFocusId); }, 300); } else { - console.log('[HomePanel] *** ⚠️ targetFocusId가 없음 - Focus 복원 스킵'); + dlog('[HomePanel] *** ⚠️ targetFocusId가 없음 - Focus 복원 스킵'); } // refs 초기화 @@ -1156,7 +1169,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { lastPlayedBannerIdRef.current = null; // detailPanelClosed 플래그 초기화 (다음 사이클에서 재사용 방지) - console.log('[HomePanel] *** detailPanelClosed flag 초기화'); + dlog('[HomePanel] *** detailPanelClosed flag 초기화'); dispatch( updateHomeInfo({ name: panel_names.HOME_PANEL, @@ -1236,14 +1249,14 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => { useEffect(() => { const prevModalState = prevPlayerModalStateRef.current; - console.log('[HomePanel] 🔍 Modal 상태 체크:', { + dlog('[HomePanel] 🔍 Modal 상태 체크:', { prevModalState, playerModalState, shouldExecute: prevModalState === false && playerModalState === true, }); if (prevModalState === false && playerModalState === true) { - console.log('>>>>>[HomePanel] ▶️ PlayerPanel이 Fullscreen에서 Banner로 전환됨'); + dlog('>>>>>[HomePanel] ▶️ PlayerPanel이 Fullscreen에서 Banner로 전환됨'); // 0.5초 후 비디오가 재생되는 배너에 포커스 테두리 효과 적용 // const focusTimer = setTimeout(() => { // if (videoPlayIntentRef.current?.bannerId) {