fix: 선택약관 미존재 조건 반영
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
"axios": "^0.21.1",
|
||||
"google-libphonenumber": "^3.2.34",
|
||||
"ilib": "^14.3.0",
|
||||
"lodash": "4.17.21",
|
||||
"patch-package": "^8.0.0",
|
||||
"postinstall-postinstall": "^2.1.0",
|
||||
"prop-types": "^15.6.2",
|
||||
@@ -52,9 +53,12 @@
|
||||
"react-player": "^1.15.3",
|
||||
"react-redux": "^7.2.3",
|
||||
"redux": "^3.7.2",
|
||||
"redux-thunk": "^2.3.0"
|
||||
"redux-thunk": "2.3.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"chrome 38"
|
||||
]
|
||||
],
|
||||
"devDependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,8 @@ function AppBase(props) {
|
||||
const termsData = useSelector((state) => state.home.termsData);
|
||||
|
||||
useEffect(() => {
|
||||
if (termsData?.data?.terms) {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (termsData && termsData.data && termsData.data.terms) {
|
||||
dispatch(getTermsAgreeYn());
|
||||
}
|
||||
}, [termsData, dispatch]);
|
||||
@@ -166,7 +167,8 @@ function AppBase(props) {
|
||||
);
|
||||
// const macAddress = useSelector((state) => state.common.macAddress);
|
||||
|
||||
const deviceCountryCode = httpHeader?.["X-Device-Country"] || "";
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
const deviceCountryCode = httpHeader && httpHeader["X-Device-Country"] || "";
|
||||
|
||||
useEffect(() => {
|
||||
if (!cursorVisible && !Spotlight.getCurrent()) {
|
||||
@@ -214,21 +216,29 @@ function AppBase(props) {
|
||||
|
||||
// called by [receive httpHeader, launch, relaunch]
|
||||
const initService = useCallback(
|
||||
|
||||
(haveyInit = true) => {
|
||||
/*
|
||||
|
||||
// console.log(
|
||||
// "<<<<<<<<<<<<< appinfo >>>>>>>>>>>>{heavyInit, appinfo} ",
|
||||
// haveyInit,
|
||||
// appinfo
|
||||
// );
|
||||
|
||||
console.log(
|
||||
"<<<<<<<<<<<<< appinfo >>>>>>>>>>>>{heavyInit, appinfo} ",
|
||||
haveyInit,
|
||||
appinfo
|
||||
"[App.js] initService,httpHeaderRef.current",
|
||||
httpHeaderRef.current
|
||||
);
|
||||
*/
|
||||
console.log("[App.js] haveyInit", haveyInit);
|
||||
|
||||
if (httpHeaderRef.current) {
|
||||
if (haveyInit) {
|
||||
dispatch(changeAppStatus({ connectionFailed: false }));
|
||||
if (typeof window === "object" && window.PalmSystem) {
|
||||
dispatch(
|
||||
changeAppStatus({
|
||||
cursorVisible: window.PalmSystem?.cursor?.visibility,
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
cursorVisible: window.PalmSystem && window.PalmSystem.cursor && window.PalmSystem.cursor.visibility,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -246,11 +256,12 @@ function AppBase(props) {
|
||||
);
|
||||
|
||||
// pyh TODO: edit or delete later (line 196 ~ 198)
|
||||
if (launchParams?.bypass) {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (launchParams && launchParams.bypass) {
|
||||
dispatch(handleBypassLink(launchParams.bypass));
|
||||
}
|
||||
if (launchParams?.contentTarget) {
|
||||
dispatch(handleDeepLink(launchParams?.contentTarget));
|
||||
if (launchParams && launchParams.contentTarget) {
|
||||
dispatch(handleDeepLink(launchParams.contentTarget));
|
||||
} else {
|
||||
dispatch(
|
||||
sendLogTotalRecommend({
|
||||
@@ -297,7 +308,8 @@ function AppBase(props) {
|
||||
foreGroundChangeTimer = setTimeout(() => {
|
||||
console.log(
|
||||
"visibility changed !!! ==> set to foreground cursorVisible",
|
||||
JSON.stringify(window.PalmSystem?.cursor?.visibility)
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
JSON.stringify(window.PalmSystem && window.PalmSystem.cursor && window.PalmSystem.cursor.visibility)
|
||||
); // eslint-disable-line no-console
|
||||
if (platform.platformName !== "webos") {
|
||||
//for debug
|
||||
@@ -311,7 +323,8 @@ function AppBase(props) {
|
||||
dispatch(
|
||||
changeAppStatus({
|
||||
isAppForeground: true,
|
||||
cursorVisible: window.PalmSystem?.cursor?.visibility,
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
cursorVisible: window.PalmSystem && window.PalmSystem.cursor && window.PalmSystem.cursor.visibility,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ export const types = {
|
||||
// home actions
|
||||
GET_HOME_TERMS: "GET_HOME_TERMS",
|
||||
SET_TERMS_ID_MAP: "SET_TERMS_ID_MAP",
|
||||
SET_OPTIONAL_TERMS_AVAILABILITY: "SET_OPTIONAL_TERMS_AVAILABILITY",
|
||||
GET_HOME_MENU: "GET_HOME_MENU",
|
||||
GET_HOME_LAYOUT: "GET_HOME_LAYOUT",
|
||||
GET_HOME_MAIN_CONTENTS: "GET_HOME_MAIN_CONTENTS",
|
||||
|
||||
@@ -17,12 +17,20 @@ export const getHomeTerms = (props) => (dispatch, getState) => {
|
||||
});
|
||||
|
||||
// 약관 ID 매핑을 별도로 생성하여 저장
|
||||
if (response.data?.data?.terms) {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (response.data && response.data.data && response.data.data.terms) {
|
||||
const termsIdMap = {};
|
||||
let hasOptionalTerms = false; // MST00405 존재 여부 확인
|
||||
|
||||
response.data.data.terms.forEach(term => {
|
||||
if (term.trmsTpCd && term.trmsId) {
|
||||
termsIdMap[term.trmsTpCd] = term.trmsId;
|
||||
}
|
||||
|
||||
// MST00405 선택약관 존재 여부 확인
|
||||
if (term.trmsTpCd === "MST00405") {
|
||||
hasOptionalTerms = true;
|
||||
}
|
||||
});
|
||||
|
||||
dispatch({
|
||||
@@ -30,8 +38,21 @@ export const getHomeTerms = (props) => (dispatch, getState) => {
|
||||
payload: termsIdMap,
|
||||
});
|
||||
|
||||
// 선택약관 존재 여부 상태 설정
|
||||
// TODO: 테스트용 - 임시로 false 강제 설정
|
||||
const forceDisableOptionalTerms = false; // 테스트 완료 후 false로 변경
|
||||
const finalOptionalTermsValue = forceDisableOptionalTerms ? false : hasOptionalTerms;
|
||||
|
||||
dispatch({
|
||||
type: types.SET_OPTIONAL_TERMS_AVAILABILITY,
|
||||
payload: finalOptionalTermsValue,
|
||||
});
|
||||
|
||||
console.log("[optionalTermsAvailable] 실제값:", hasOptionalTerms, "강제설정값:", finalOptionalTermsValue);
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.log("약관 ID 매핑 생성:", termsIdMap);
|
||||
console.log("선택약관 존재 여부:", hasOptionalTerms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +101,20 @@ export const fetchCurrentUserHomeTerms = () => (dispatch, getState) => {
|
||||
});
|
||||
|
||||
// 약관 ID 매핑을 별도로 생성하여 저장
|
||||
if (response.data?.data?.terms) {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (response.data && response.data.data && response.data.data.terms) {
|
||||
const termsIdMap = {};
|
||||
let hasOptionalTerms = false; // MST00405 존재 여부 확인
|
||||
|
||||
response.data.data.terms.forEach(term => {
|
||||
if (term.trmsTpCd && term.trmsId) {
|
||||
termsIdMap[term.trmsTpCd] = term.trmsId;
|
||||
}
|
||||
|
||||
// MST00405 선택약관 존재 여부 확인
|
||||
if (term.trmsTpCd === "MST00405") {
|
||||
hasOptionalTerms = true;
|
||||
}
|
||||
});
|
||||
|
||||
dispatch({
|
||||
@@ -93,8 +122,20 @@ export const fetchCurrentUserHomeTerms = () => (dispatch, getState) => {
|
||||
payload: termsIdMap,
|
||||
});
|
||||
|
||||
// 선택약관 존재 여부 상태 설정
|
||||
// TODO: 테스트용 - 임시로 false 강제 설정
|
||||
const forceDisableOptionalTerms = false; // 테스트 완료 후 false로 변경
|
||||
const finalOptionalTermsValue = forceDisableOptionalTerms ? false : hasOptionalTerms;
|
||||
|
||||
dispatch({
|
||||
type: types.SET_OPTIONAL_TERMS_AVAILABILITY,
|
||||
payload: finalOptionalTermsValue,
|
||||
});
|
||||
console.log("[optionalTermsAvailable] 실제값:", hasOptionalTerms, "강제설정값:", finalOptionalTermsValue);
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.log("약관 ID 매핑 생성:", termsIdMap);
|
||||
console.log("선택약관 존재 여부:", hasOptionalTerms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,12 +210,20 @@ export const fetchCurrentUserHomeTermsSafe = () => async (dispatch, getState) =>
|
||||
});
|
||||
|
||||
// 약관 ID 매핑을 별도로 생성하여 저장
|
||||
if (result.data?.data?.terms) {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (result.data && result.data.data && result.data.data.terms) {
|
||||
const termsIdMap = {};
|
||||
let hasOptionalTerms = false; // MST00405 존재 여부 확인
|
||||
|
||||
result.data.data.terms.forEach(term => {
|
||||
if (term.trmsTpCd && term.trmsId) {
|
||||
termsIdMap[term.trmsTpCd] = term.trmsId;
|
||||
}
|
||||
|
||||
// MST00405 선택약관 존재 여부 확인
|
||||
if (term.trmsTpCd === "MST00405") {
|
||||
hasOptionalTerms = true;
|
||||
}
|
||||
});
|
||||
|
||||
dispatch({
|
||||
@@ -182,8 +231,19 @@ export const fetchCurrentUserHomeTermsSafe = () => async (dispatch, getState) =>
|
||||
payload: termsIdMap,
|
||||
});
|
||||
|
||||
// 선택약관 존재 여부 상태 설정 2025-07-03
|
||||
// TODO: 테스트용 - 임시로 false 강제 설정
|
||||
const forceDisableOptionalTerms = false; // 테스트 완료 후 false로 변경
|
||||
const finalOptionalTermsValue = forceDisableOptionalTerms ? false : hasOptionalTerms;
|
||||
|
||||
dispatch({
|
||||
type: types.SET_OPTIONAL_TERMS_AVAILABILITY,
|
||||
payload: finalOptionalTermsValue,
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.log("약관 ID 매핑 생성:", termsIdMap);
|
||||
console.log("선택약관 존재 여부 - 실제값:", hasOptionalTerms, "강제설정값:", finalOptionalTermsValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,11 +255,12 @@ export const fetchCurrentUserHomeTermsSafe = () => async (dispatch, getState) =>
|
||||
return { success: true, data: result.data };
|
||||
} else {
|
||||
// retCode가 0이 아닌 일반적인 API 에러
|
||||
console.error("API returned non-zero retCode:", result.data?.retCode);
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
console.error("API returned non-zero retCode:", result.data && result.data.retCode);
|
||||
dispatch({ type: types.GET_TERMS_AGREE_YN_FAILURE });
|
||||
return {
|
||||
success: false,
|
||||
message: result.data?.retMsg || "서버 오류가 발생했습니다."
|
||||
message: (result.data && result.data.retMsg) || "서버 오류가 발생했습니다."
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ const initialState = {
|
||||
isPaused: false,
|
||||
},
|
||||
termsIdMap: {}, // added new property to initialState
|
||||
optionalTermsAvailable: false, // 선택약관 존재 여부
|
||||
};
|
||||
|
||||
export const homeReducer = (state = initialState, action) => {
|
||||
@@ -42,6 +43,12 @@ export const homeReducer = (state = initialState, action) => {
|
||||
termsIdMap: action.payload,
|
||||
};
|
||||
|
||||
case types.SET_OPTIONAL_TERMS_AVAILABILITY:
|
||||
return {
|
||||
...state,
|
||||
optionalTermsAvailable: action.payload,
|
||||
};
|
||||
|
||||
case types.GET_HOME_MENU: {
|
||||
let menuItems = [];
|
||||
|
||||
|
||||
223
com.twin.app.shoptime/src/utils/dataHelpers.js
Normal file
223
com.twin.app.shoptime/src/utils/dataHelpers.js
Normal file
@@ -0,0 +1,223 @@
|
||||
// src/utils/dataHelpers.js
|
||||
|
||||
/**
|
||||
* @fileoverview webOS TV 데이터 처리 유틸리티 함수들
|
||||
*
|
||||
* Chromium68 기반 구형 webOS TV 호환성을 위해 Optional Chaining(?.) 대신
|
||||
* lodash를 사용하여 안전한 객체 속성 접근을 제공합니다.
|
||||
*
|
||||
* Optional Chaining은 Chrome 80+에서만 지원되므로,
|
||||
* Chromium68 환경에서는 문법 오류가 발생할 수 있습니다.
|
||||
*
|
||||
* @author Your Team
|
||||
* @since 2.0.0
|
||||
* @requires lodash
|
||||
*/
|
||||
|
||||
import { get, isEmpty, isArray } from 'lodash';
|
||||
|
||||
/**
|
||||
* 객체의 중첩된 속성에 안전하게 접근합니다.
|
||||
* Optional Chaining(obj?.prop?.nested) 대신 사용하는 호환성 함수입니다.
|
||||
*
|
||||
* @param {Object|Array|null|undefined} obj - 접근할 객체
|
||||
* @param {string|Array} path - 접근할 속성 경로 (점 표기법 또는 배열)
|
||||
* @param {*} [defaultValue=null] - 값이 없을 때 반환할 기본값
|
||||
* @returns {*} 찾은 값 또는 기본값
|
||||
*
|
||||
* @example
|
||||
* // 기존 Optional Chaining 방식 (Chromium68에서 작동 안함)
|
||||
* // const city = user?.profile?.address?.city;
|
||||
*
|
||||
* // 호환성을 위한 새로운 방식
|
||||
* const user = { profile: { address: { city: 'Seoul' } } };
|
||||
* const city = safeGet(user, 'profile.address.city'); // 'Seoul'
|
||||
* const country = safeGet(user, 'profile.address.country', 'Unknown'); // 'Unknown'
|
||||
*
|
||||
* // 배열 접근
|
||||
* const items = [{ name: 'Apple' }, { name: 'Banana' }];
|
||||
* const firstItem = safeGet(items, '[0].name'); // 'Apple'
|
||||
* const thirdItem = safeGet(items, '[2].name', 'Not Found'); // 'Not Found'
|
||||
*
|
||||
* // webOS API 응답 처리
|
||||
* const deviceInfo = safeGet(webOSResponse, 'device.modelName', 'Unknown TV');
|
||||
*/
|
||||
export const safeGet = (obj, path, defaultValue = null) =>
|
||||
get(obj, path, defaultValue);
|
||||
|
||||
/**
|
||||
* 데이터가 유효한 배열인지 확인합니다.
|
||||
* API 응답이나 상태 데이터가 렌더링 가능한 배열 형태인지 검증할 때 사용합니다.
|
||||
*
|
||||
* @param {*} data - 검증할 데이터
|
||||
* @returns {boolean} 유효한 배열이면 true, 아니면 false
|
||||
*
|
||||
* @example
|
||||
* // API 응답 검증
|
||||
* const apiResponse = { data: { products: [] } };
|
||||
* const products = safeGet(apiResponse, 'data.products', []);
|
||||
*
|
||||
* if (hasValidData(products)) {
|
||||
* // 안전하게 배열 렌더링
|
||||
* return products.map(product => <ProductCard key={product.id} {...product} />);
|
||||
* } else {
|
||||
* return <EmptyState message="상품이 없습니다" />;
|
||||
* }
|
||||
*
|
||||
* // 다양한 케이스 테스트
|
||||
* hasValidData([1, 2, 3]); // true
|
||||
* hasValidData([]); // false (빈 배열)
|
||||
* hasValidData(null); // false
|
||||
* hasValidData(undefined); // false
|
||||
* hasValidData({}); // false (객체)
|
||||
* hasValidData('string'); // false (문자열)
|
||||
*/
|
||||
export const hasValidData = (data) =>
|
||||
!isEmpty(data) && isArray(data);
|
||||
|
||||
/**
|
||||
* API 응답에서 데이터 부분을 안전하게 추출합니다.
|
||||
* 일반적인 API 응답 구조에서 실제 데이터 객체를 가져올 때 사용합니다.
|
||||
*
|
||||
* @param {Object} response - API 응답 객체
|
||||
* @param {string} [dataPath='data'] - 데이터가 위치한 경로
|
||||
* @returns {Object} 추출된 데이터 객체 (기본값: 빈 객체)
|
||||
*
|
||||
* @example
|
||||
* // 일반적인 API 응답 구조
|
||||
* const apiResponse = {
|
||||
* status: 'success',
|
||||
* data: {
|
||||
* products: [...],
|
||||
* pagination: { ... },
|
||||
* metadata: { ... }
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* // 데이터 추출
|
||||
* const responseData = getApiData(apiResponse); // { products: [...], pagination: {...}, ... }
|
||||
* const products = safeGet(responseData, 'products', []);
|
||||
*
|
||||
* // 커스텀 경로 지정
|
||||
* const nestedResponse = {
|
||||
* result: {
|
||||
* payload: {
|
||||
* items: [...]
|
||||
* }
|
||||
* }
|
||||
* };
|
||||
* const payloadData = getApiData(nestedResponse, 'result.payload'); // { items: [...] }
|
||||
*
|
||||
* // webOS 서비스 응답 처리
|
||||
* const webOSServiceResponse = {
|
||||
* returnValue: true,
|
||||
* response: {
|
||||
* deviceList: [...]
|
||||
* }
|
||||
* };
|
||||
* const serviceData = getApiData(webOSServiceResponse, 'response'); // { deviceList: [...] }
|
||||
*
|
||||
* // 오류나 빈 응답 처리
|
||||
* const emptyResponse = null;
|
||||
* const safeData = getApiData(emptyResponse); // {} (빈 객체)
|
||||
*/
|
||||
export const getApiData = (response, dataPath = 'data') =>
|
||||
get(response, dataPath, {});
|
||||
|
||||
/**
|
||||
* 추가 유틸리티 함수들 - webOS TV 환경에서 자주 사용되는 패턴들
|
||||
*/
|
||||
|
||||
/**
|
||||
* 객체에 특정 속성이 존재하는지 안전하게 확인합니다.
|
||||
*
|
||||
* @param {Object} obj - 확인할 객체
|
||||
* @param {string} path - 확인할 속성 경로
|
||||
* @returns {boolean} 속성이 존재하면 true
|
||||
*
|
||||
* @example
|
||||
* const settings = { user: { preferences: { theme: 'dark' } } };
|
||||
*
|
||||
* // 기존 방식 (Chromium68에서 위험)
|
||||
* // const hasTheme = settings?.user?.preferences?.theme !== undefined;
|
||||
*
|
||||
* // 호환성 방식
|
||||
* const hasTheme = safeHas(settings, 'user.preferences.theme'); // true
|
||||
* const hasLanguage = safeHas(settings, 'user.preferences.language'); // false
|
||||
*/
|
||||
export const safeHas = (obj, path) => {
|
||||
return get(obj, path) !== undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* 배열의 첫 번째 요소를 안전하게 가져옵니다.
|
||||
*
|
||||
* @param {Array} array - 대상 배열
|
||||
* @param {*} [defaultValue=null] - 기본값
|
||||
* @returns {*} 첫 번째 요소 또는 기본값
|
||||
*
|
||||
* @example
|
||||
* const products = [{ id: 1, name: 'TV' }, { id: 2, name: 'Phone' }];
|
||||
* const firstProduct = safeFirst(products); // { id: 1, name: 'TV' }
|
||||
*
|
||||
* const emptyArray = [];
|
||||
* const firstItem = safeFirst(emptyArray, { id: 0, name: 'Default' }); // { id: 0, name: 'Default' }
|
||||
*/
|
||||
export const safeFirst = (array, defaultValue = null) => {
|
||||
return hasValidData(array) ? array[0] : defaultValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* 문자열이 비어있지 않은지 확인합니다.
|
||||
*
|
||||
* @param {string} str - 확인할 문자열
|
||||
* @returns {boolean} 유효한 문자열이면 true
|
||||
*
|
||||
* @example
|
||||
* isValidString('Hello'); // true
|
||||
* isValidString(''); // false
|
||||
* isValidString(null); // false
|
||||
* isValidString(undefined); // false
|
||||
* isValidString(' '); // false (공백만 있는 경우)
|
||||
*/
|
||||
export const isValidString = (str) => {
|
||||
return typeof str === 'string' && str.trim().length > 0;
|
||||
};
|
||||
|
||||
// 사용 예시를 위한 실제 webOS TV 컴포넌트에서의 활용
|
||||
/**
|
||||
* @example 실제 컴포넌트에서의 사용법
|
||||
*
|
||||
* import { safeGet, hasValidData, getApiData } from '../utils/dataHelpers';
|
||||
*
|
||||
* const ProductList = ({ apiResponse }) => {
|
||||
* // API 응답에서 안전하게 데이터 추출
|
||||
* const responseData = getApiData(apiResponse);
|
||||
* const products = safeGet(responseData, 'products', []);
|
||||
* const totalCount = safeGet(responseData, 'pagination.total', 0);
|
||||
*
|
||||
* // 데이터 유효성 검사
|
||||
* if (!hasValidData(products)) {
|
||||
* return <div>상품이 없습니다.</div>;
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <div>
|
||||
* <h2>상품 목록 ({totalCount}개)</h2>
|
||||
* {products.map(product => {
|
||||
* const productName = safeGet(product, 'name', '이름 없음');
|
||||
* const productPrice = safeGet(product, 'price.amount', 0);
|
||||
* const productImage = safeGet(product, 'images[0].url', '/default-image.jpg');
|
||||
*
|
||||
* return (
|
||||
* <div key={product.id}>
|
||||
* <img src={productImage} alt={productName} />
|
||||
* <h3>{productName}</h3>
|
||||
* <p>{productPrice}원</p>
|
||||
* </div>
|
||||
* );
|
||||
* })}
|
||||
* </div>
|
||||
* );
|
||||
* };
|
||||
*/
|
||||
@@ -146,11 +146,16 @@ export default function HomeBanner({
|
||||
|
||||
const termsData = useSelector((state) => state.home.termsData);
|
||||
const termsIdMap = useSelector((state) => state.home.termsIdMap);
|
||||
const optionalTermsData = useSelector((state) =>
|
||||
state.home.termsData?.data?.terms.find(
|
||||
(term) => term.trmsTpCd === "MST00405",
|
||||
),
|
||||
const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable);
|
||||
const optionalTermsData = useSelector((state) => {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (state.home.termsData && state.home.termsData.data && state.home.termsData.data.terms) {
|
||||
return state.home.termsData.data.terms.find(
|
||||
(term) => term.trmsTpCd === "MST00405"
|
||||
);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
const termsLoading = useSelector((state) => state.common.termsLoading);
|
||||
const isGnbOpened = useSelector((state) => state.common.isGnbOpened);
|
||||
// 선택약관 동의여부
|
||||
@@ -166,13 +171,21 @@ export default function HomeBanner({
|
||||
|
||||
// 선택약관 팝업 표시 여부 ===================================================
|
||||
const shouldShowOptionalTermsPopup = useMemo(() => {
|
||||
console.log('[HomeBanner] Step 1: termsLoading, isGnbOpened, optionalTermsAgreed 상태 확인', { termsLoading, isGnbOpened, optionalTermsAgreed });
|
||||
if (termsLoading || isGnbOpened || optionalTermsAgreed) {
|
||||
console.log('[HomeBanner] Early return: 조건 불만족 (termsLoading || isGnbOpened || optionalTermsAgreed)');
|
||||
console.log('[HomeBanner] Step 1: 상태 확인', {
|
||||
termsLoading,
|
||||
isGnbOpened,
|
||||
optionalTermsAgreed,
|
||||
optionalTermsAvailable
|
||||
});
|
||||
|
||||
// optionalTermsAvailable = false면 팝업 표시 안함
|
||||
if (termsLoading || isGnbOpened || optionalTermsAgreed || !optionalTermsAvailable) {
|
||||
console.log('[HomeBanner] Early return: 조건 불만족');
|
||||
return false;
|
||||
}
|
||||
|
||||
const terms = termsData?.data?.terms;
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
const terms = termsData && termsData.data && termsData.data.terms;
|
||||
console.log('[HomeBanner] Step 2: termsData 확인', terms);
|
||||
if (!terms) {
|
||||
console.log('[HomeBanner] Early return: terms가 존재하지 않음');
|
||||
@@ -188,7 +201,7 @@ export default function HomeBanner({
|
||||
|
||||
console.log('[HomeBanner] Step 4: 최종 결과', result);
|
||||
return result;
|
||||
}, [termsData, termsLoading, isGnbOpened, optionalTermsAgreed]);
|
||||
}, [termsData, termsLoading, isGnbOpened, optionalTermsAgreed, optionalTermsAvailable]);
|
||||
|
||||
// 선택약관 팝업 표시 여부 ===================================================
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import BasicIntroPanel from "./IntroPanel.jsx";
|
||||
import Region from "@enact/sandstone/Region";
|
||||
import Spotlight from "@enact/spotlight";
|
||||
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||
@@ -54,7 +55,23 @@ const Container = SpotlightContainerDecorator(
|
||||
const MAX_RETRY_ATTEMPTS = 5;
|
||||
const RETRY_DELAY_MS = 1500; // 1.5 seconds
|
||||
|
||||
export default function IntroPanel({
|
||||
// 조건부 IntroPanel 컴포넌트 (선택약관 존재 여부에 따라 다른 컴포넌트 렌더링)
|
||||
export default function IntroPanel(props) {
|
||||
const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable);
|
||||
|
||||
// 선택약관이 없으면 기존 IntroPanel.jsx 사용
|
||||
if (!optionalTermsAvailable) {
|
||||
console.log('[IntroPanel.new] optionalTermsAvailable = false, 기존 IntroPanel 사용');
|
||||
return <BasicIntroPanel {...props} />;
|
||||
}
|
||||
|
||||
// 선택약관이 있으면 고급 IntroPanel 사용
|
||||
console.log('[IntroPanel.new] optionalTermsAvailable = true, 고급 IntroPanel 사용');
|
||||
return <IntroPanelWithOptional {...props} />;
|
||||
}
|
||||
|
||||
// 선택약관 포함 고급 IntroPanel 컴포넌트
|
||||
function IntroPanelWithOptional({
|
||||
// children,
|
||||
// isTabActivated,
|
||||
// handleCancel,
|
||||
@@ -101,24 +118,32 @@ export default function IntroPanel({
|
||||
} = termsState;
|
||||
|
||||
const introTermsData = useMemo(() => {
|
||||
return (
|
||||
termsData?.data?.terms.filter(
|
||||
(item) => item.trmsTpCd === "MST00401" || item.trmsTpCd === "MST00402",
|
||||
) || []
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (termsData && termsData.data && termsData.data.terms) {
|
||||
return termsData.data.terms.filter(
|
||||
(item) => item.trmsTpCd === "MST00401" || item.trmsTpCd === "MST00402"
|
||||
);
|
||||
}
|
||||
return [];
|
||||
}, [termsData]);
|
||||
|
||||
const optionalTermsData = useMemo(() => {
|
||||
return (
|
||||
termsData?.data?.terms.filter(
|
||||
(item) => item.trmsTpCd === "MST00405" || item.trmsTpCd === "MST00406",
|
||||
) || []
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (termsData && termsData.data && termsData.data.terms) {
|
||||
return termsData.data.terms.filter(
|
||||
(item) => item.trmsTpCd === "MST00405" || item.trmsTpCd === "MST00406"
|
||||
);
|
||||
}
|
||||
return [];
|
||||
}, [termsData]);
|
||||
|
||||
const webOSVersion = useSelector(
|
||||
(state) => state.common.appStatus?.webOSVersion,
|
||||
);
|
||||
const webOSVersion = useSelector((state) => {
|
||||
// Chromium68 호환성을 위해 Optional Chaining 제거
|
||||
if (state.common && state.common.appStatus && state.common.appStatus.webOSVersion) {
|
||||
return state.common.appStatus.webOSVersion;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
// const webOSVersion = 4.5;
|
||||
// WebOS 버전별 UI 표시 모드 결정
|
||||
|
||||
Reference in New Issue
Block a user