[20250707] 선택약관팝업오픈 조건 수정: gogs->gitlab

This commit is contained in:
djaco
2025-07-07 16:06:49 +09:00
parent 847b16b3a6
commit 19d87b489b
5 changed files with 135 additions and 18 deletions

View File

@@ -27,6 +27,10 @@ export const types = {
SHOW_OPTIONAL_TERMS_CONFIRM_POPUP: "SHOW_OPTIONAL_TERMS_CONFIRM_POPUP",
HIDE_OPTIONAL_TERMS_CONFIRM_POPUP: "HIDE_OPTIONAL_TERMS_CONFIRM_POPUP",
TOGGLE_OPTIONAL_TERMS_CONFIRM: "TOGGLE_OPTIONAL_TERMS_CONFIRM",
// 선택약관 팝업 상태 관리
SET_OPTIONAL_TERMS_POPUP_SHOWN: "SET_OPTIONAL_TERMS_POPUP_SHOWN",
SET_OPTIONAL_TERMS_USER_DECISION: "SET_OPTIONAL_TERMS_USER_DECISION",
RESET_OPTIONAL_TERMS_SESSION: "RESET_OPTIONAL_TERMS_SESSION",
SET_EXIT_APP: "SET_EXIT_APP",
GET_LOGIN_USER_DATA: "GET_LOGIN_USER_DATA",
GET_TERMS_AGREE_YN: "GET_TERMS_AGREE_YN",

View File

@@ -740,3 +740,32 @@ export const enableNotification = () => (dispatch, getState) => {
},
});
};
// 선택약관 팝업 상태 관리 액션 생성자들 (TV 환경 최적화)
export const setOptionalTermsPopupShown = (shown = true) => ({
type: types.SET_OPTIONAL_TERMS_POPUP_SHOWN,
payload: shown,
});
export const setOptionalTermsUserDecision = (decision) => ({
type: types.SET_OPTIONAL_TERMS_USER_DECISION,
payload: decision, // 'agreed' | 'declined' | null
});
export const resetOptionalTermsSession = () => ({
type: types.RESET_OPTIONAL_TERMS_SESSION,
});
// 선택약관 동의 처리를 위한 헬퍼 함수
export const handleOptionalTermsAgree = () => (dispatch) => {
console.log('[CommonActions] 선택약관 동의 처리');
dispatch(setOptionalTermsUserDecision('agreed'));
dispatch(setOptionalTermsPopupShown(true));
};
// 선택약관 거절 처리를 위한 헬퍼 함수
export const handleOptionalTermsDecline = () => (dispatch) => {
console.log('[CommonActions] 선택약관 거절 처리');
dispatch(setOptionalTermsUserDecision('declined'));
dispatch(setOptionalTermsPopupShown(true));
};

View File

@@ -81,7 +81,14 @@ const initialState = {
MST00401: false, // 개인정보처리방침 (필수)
MST00402: false, // 이용약관 (필수)
MST00405: false, // 선택약관 (선택)
}
},
// 선택약관 팝업 상태 관리 (TV 환경 최적화)
optionalTermsPopupFlow: {
popupShown: false, // 팝업 표시 여부
userDecision: null, // 'agreed' | 'declined' | null
agreedInSession: false, // 세션 내 동의 여부 (로컬 상태 기반)
},
};
export const commonReducer = (state = initialState, action) => {
@@ -374,6 +381,39 @@ export const commonReducer = (state = initialState, action) => {
};
}
// 선택약관 팝업 상태 관리 액션들
case types.SET_OPTIONAL_TERMS_POPUP_SHOWN: {
return {
...state,
optionalTermsPopupFlow: {
...state.optionalTermsPopupFlow,
popupShown: action.payload,
},
};
}
case types.SET_OPTIONAL_TERMS_USER_DECISION: {
return {
...state,
optionalTermsPopupFlow: {
...state.optionalTermsPopupFlow,
userDecision: action.payload,
agreedInSession: action.payload === 'agreed',
},
};
}
case types.RESET_OPTIONAL_TERMS_SESSION: {
return {
...state,
optionalTermsPopupFlow: {
popupShown: false,
userDecision: null,
agreedInSession: false,
},
};
}
default:
return state;
}

View File

@@ -12,7 +12,13 @@ import {
// setShowPopup,
fetchCurrentUserHomeTerms,
} from "../../../actions/homeActions";
import { changeAppStatus } from "../../../actions/commonActions";
import {
changeAppStatus,
setOptionalTermsPopupShown,
setOptionalTermsUserDecision,
handleOptionalTermsAgree as handleOptionalTermsAgreeAction,
handleOptionalTermsDecline,
} from "../../../actions/commonActions";
import { setMyPageTermsAgree } from "../../../actions/myPageActions";
import { pushPanel, popPanel } from "../../../actions/panelActions";
import { panel_names } from "../../../utils/Config";
@@ -161,6 +167,9 @@ export default function HomeBanner({
// 선택약관 동의여부
const introTermsAgree = useSelector((state) => state.common.introTermsAgree);
// 새로운 Redux 상태: 선택약관 팝업 플로우 관리
const optionalTermsPopupFlow = useSelector((state) => state.common.optionalTermsPopupFlow);
//------------------------------------------------------------------------------
// 팝업표시 상태
const [isOptionalConfirmVisible, setIsOptionalConfirmVisible] =
@@ -174,17 +183,25 @@ export default function HomeBanner({
console.log('[HomeBanner] Step 1: 상태 확인', {
termsLoading,
isGnbOpened,
optionalTermsAgreed,
optionalTermsAvailable
optionalTermsAvailable,
optionalTermsPopupFlow
});
// optionalTermsAvailable = false면 팝업 표시 안함
if (termsLoading || isGnbOpened || optionalTermsAgreed || !optionalTermsAvailable) {
console.log('[HomeBanner] Early return: 조건 불만족');
// 1. 기본 조건 확인
if (termsLoading || isGnbOpened || !optionalTermsAvailable) {
console.log('[HomeBanner] Early return: 기본 조건 불만족');
return false;
}
// Chromium68 호환성을 위해 Optional Chaining 제거
// 2. 새로운 Redux 상태 확인 (TV 환경 최적화)
if (optionalTermsPopupFlow.popupShown ||
optionalTermsPopupFlow.userDecision ||
optionalTermsPopupFlow.agreedInSession) {
console.log('[HomeBanner] Early return: 이미 처리됨', optionalTermsPopupFlow);
return false;
}
// 3. 서버 데이터 확인
const terms = termsData && termsData.data && termsData.data.terms;
console.log('[HomeBanner] Step 2: termsData 확인', terms);
if (!terms) {
@@ -201,7 +218,7 @@ export default function HomeBanner({
console.log('[HomeBanner] Step 4: 최종 결과', result);
return result;
}, [termsData, termsLoading, isGnbOpened, optionalTermsAgreed, optionalTermsAvailable]);
}, [termsData, termsLoading, isGnbOpened, optionalTermsAvailable, optionalTermsPopupFlow]);
// 선택약관 팝업 표시 여부 ===================================================
@@ -254,7 +271,10 @@ export default function HomeBanner({
if (process.env.NODE_ENV === "development") {
console.log("[HomeBanner] 약관 동의 성공:", response);
}
// 약관 동의 성공 상태 설정
// 새로운 Redux 액션을 사용하여 상태 업데이트
dispatch(setOptionalTermsUserDecision('agreed'));
dispatch(setOptionalTermsPopupShown(true));
// 로컬 상태도 업데이트 (기존 로직 유지)
setOptionalTermsAgreed(true);
// 약관 데이터 갱신
dispatch(fetchCurrentUserHomeTerms());
@@ -289,9 +309,11 @@ export default function HomeBanner({
const handleOptionalDeclineClick = useCallback(() => {
console.log("[HomeBanner] 거절/다음에 하기 버튼 클릭");
// 새로운 Redux 액션을 사용하여 거절 상태 업데이트
dispatch(setOptionalTermsUserDecision('declined'));
dispatch(setOptionalTermsPopupShown(true));
setIsOptionalConfirmVisible(false);
// 거절 처리 로직 추가
}, []);
}, [dispatch]);
// 선택약관 팝업 Close
const handleTermsPopupClosed = useCallback(() => {
@@ -365,26 +387,28 @@ export default function HomeBanner({
// }, 1000);
// }, []);
// 약관 동의 및 선택 약관 팝업 처리
// 약관 동의 및 선택 약관 팝업 처리 (TV 환경 최적화)
useEffect(() => {
if (termsLoading) {
// 약관 데이터 로딩 중에는 아무것도 하지 않음
return;
}
// 선택 약관 팝업을 띄워야 하는 경우
if (shouldShowOptionalTermsPopup) {
// 3초 후에 팝업을 띄우도록 설정
if (shouldShowOptionalTermsPopup && !isOptionalConfirmVisible) {
console.log("shouldShowOptionalTermsPopup", shouldShowOptionalTermsPopup);
console.log("App.js optionalTermsConfirm 팝업 표시");
const timer = setTimeout(() => {
setIsOptionalConfirmVisible(true);
// dispatch(setShowPopup({ activePopup: "optionalTermsConfirm" }));
}, 1000); // 3000 milliseconds = 3 seconds
// 팝업이 실제로 표시된 후에 Redux 상태 업데이트
dispatch(setOptionalTermsPopupShown(true));
}, 1000);
// 컴포넌트 언마운트 시 타이머 클리어
return () => clearTimeout(timer);
}
}, [shouldShowOptionalTermsPopup, termsLoading]);
}, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]);
// const renderItem = useCallback(
// (index, isHorizontal) => {

View File

@@ -17,6 +17,9 @@ import {
setHidePopup,
setShowPopup,
setDeviceRegistered,
setOptionalTermsUserDecision,
setOptionalTermsPopupShown,
resetOptionalTermsSession,
// setTermsAgreeYn,
} from "../../actions/commonActions";
import { registerDevice } from "../../actions/deviceActions";
@@ -357,6 +360,23 @@ function IntroPanelWithOptional({
// ================== SUCCESS ==================
if (newRegDeviceData && newRegDeviceData.retCode === 0) {
dispatch(setDeviceRegistered(true));
// 선택약관 상태를 Redux에 업데이트 (TV 환경 최적화)
if (optionalChecked) {
// 선택약관에 동의한 경우
console.log("[IntroPanel] 선택약관 동의됨 - Redux 상태 업데이트");
dispatch(setOptionalTermsUserDecision('agreed'));
dispatch(setOptionalTermsPopupShown(true));
} else {
// 선택약관에 동의하지 않은 경우 - HomeBanner에서 팝업이 나올 수 있도록 상태를 초기화
console.log("[IntroPanel] 선택약관 미동의 - HomeBanner 팝업 허용을 위해 상태 초기화");
// fetchCurrentUserHomeTerms 완료 후 Redux 상태를 리셋하여 HomeBanner에서 팝업 표시 조건을 정확히 평가할 수 있도록 함
setTimeout(() => {
console.log("[IntroPanel] 약관 데이터 갱신 후 상태 리셋 실행");
dispatch(resetOptionalTermsSession());
}, 1000); // 약관 데이터 갱신 완료를 기다림
}
dispatch(
getWelcomeEventInfo((eventInfos) => {
if (