fix: 선택약관 3차수정
This commit is contained in:
@@ -13,6 +13,7 @@ export const types = {
|
|||||||
REGISTER_DEVICE_INFO: "REGISTER_DEVICE_INFO",
|
REGISTER_DEVICE_INFO: "REGISTER_DEVICE_INFO",
|
||||||
GET_DEVICE_INFO: "GET_DEVICE_INFO",
|
GET_DEVICE_INFO: "GET_DEVICE_INFO",
|
||||||
CLEAR_REGISTER_DEVICE_INFO: "CLEAR_REGISTER_DEVICE_INFO",
|
CLEAR_REGISTER_DEVICE_INFO: "CLEAR_REGISTER_DEVICE_INFO",
|
||||||
|
REGISTER_DEVICE_RESET: "REGISTER_DEVICE_RESET",
|
||||||
|
|
||||||
// common actions
|
// common actions
|
||||||
GET_HTTP_HEADER: "GET_HTTP_HEADER",
|
GET_HTTP_HEADER: "GET_HTTP_HEADER",
|
||||||
@@ -216,4 +217,7 @@ export const types = {
|
|||||||
GET_TERMS_AGREE_YN_START: "GET_TERMS_AGREE_YN_START",
|
GET_TERMS_AGREE_YN_START: "GET_TERMS_AGREE_YN_START",
|
||||||
GET_TERMS_AGREE_YN_SUCCESS: "GET_TERMS_AGREE_YN_SUCCESS",
|
GET_TERMS_AGREE_YN_SUCCESS: "GET_TERMS_AGREE_YN_SUCCESS",
|
||||||
GET_TERMS_AGREE_YN_FAILURE: "GET_TERMS_AGREE_YN_FAILURE",
|
GET_TERMS_AGREE_YN_FAILURE: "GET_TERMS_AGREE_YN_FAILURE",
|
||||||
|
|
||||||
|
// device
|
||||||
|
REQ_REG_DEVICE_INFO: "REQ_REG_DEVICE_INFO",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const OptionalConfirm = ({
|
|||||||
open,
|
open,
|
||||||
spotlightId,
|
spotlightId,
|
||||||
className,
|
className,
|
||||||
|
onClose,
|
||||||
onOptionalTermsClick, // 약관 자세히 보기 버튼 클릭 핸들러
|
onOptionalTermsClick, // 약관 자세히 보기 버튼 클릭 핸들러
|
||||||
onOptionalAgreeClick, // 동의 버튼 클릭 핸들러
|
onOptionalAgreeClick, // 동의 버튼 클릭 핸들러
|
||||||
onOptionalDeclineClick, // 거절 또는 다음에 하기 버튼 클릭 핸들러
|
onOptionalDeclineClick, // 거절 또는 다음에 하기 버튼 클릭 핸들러
|
||||||
@@ -25,6 +26,7 @@ const OptionalConfirm = ({
|
|||||||
spotlightId={spotlightId}
|
spotlightId={spotlightId}
|
||||||
spotlightRestrict="self-only" // 필요에 따라 props로 설정 가능하게 할 수 있습니다.
|
spotlightRestrict="self-only" // 필요에 따라 props로 설정 가능하게 할 수 있습니다.
|
||||||
className={`${css.optionalConfirmPopup} ${className || ''}`.trim()}
|
className={`${css.optionalConfirmPopup} ${className || ''}`.trim()}
|
||||||
|
onClose={onClose}
|
||||||
onOptionalTermsClick={onOptionalTermsClick}
|
onOptionalTermsClick={onOptionalTermsClick}
|
||||||
onOptionalAgreeClick={onOptionalAgreeClick}
|
onOptionalAgreeClick={onOptionalAgreeClick}
|
||||||
onOptionalDeclineClick={onOptionalDeclineClick}
|
onOptionalDeclineClick={onOptionalDeclineClick}
|
||||||
@@ -41,6 +43,8 @@ OptionalConfirm.propTypes = {
|
|||||||
spotlightId: PropTypes.string.isRequired,
|
spotlightId: PropTypes.string.isRequired,
|
||||||
/** 추가적인 CSS 클래스 */
|
/** 추가적인 CSS 클래스 */
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
|
/** 팝업의 닫기 이벤트 핸들러 (ESC 키 등) */
|
||||||
|
onClose: PropTypes.func,
|
||||||
/** 약관 자세히 보기 버튼 클릭 시 호출될 함수 */
|
/** 약관 자세히 보기 버튼 클릭 시 호출될 함수 */
|
||||||
onOptionalTermsClick: PropTypes.func,
|
onOptionalTermsClick: PropTypes.func,
|
||||||
/** 동의 버튼 클릭 시 호출될 함수 */
|
/** 동의 버튼 클릭 시 호출될 함수 */
|
||||||
@@ -55,6 +59,7 @@ OptionalConfirm.propTypes = {
|
|||||||
|
|
||||||
OptionalConfirm.defaultProps = {
|
OptionalConfirm.defaultProps = {
|
||||||
className: '',
|
className: '',
|
||||||
|
onClose: () => console.log('OptionalConfirm: onClose not provided'),
|
||||||
onOptionalTermsClick: () => console.log('OptionalConfirm: onOptionalTermsClick not provided'),
|
onOptionalTermsClick: () => console.log('OptionalConfirm: onOptionalTermsClick not provided'),
|
||||||
onOptionalAgreeClick: () => console.log('OptionalConfirm: onOptionalAgreeClick not provided'),
|
onOptionalAgreeClick: () => console.log('OptionalConfirm: onOptionalAgreeClick not provided'),
|
||||||
onOptionalDeclineClick: () => console.log('OptionalConfirm: onOptionalDeclineClick not provided'),
|
onOptionalDeclineClick: () => console.log('OptionalConfirm: onOptionalDeclineClick not provided'),
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { types } from "../actions/actionTypes";
|
import { types } from "../actions/actionTypes";
|
||||||
|
import {
|
||||||
|
GET_TERMS_AGREE_YN_FAIL,
|
||||||
|
} from "../actions/commonActions";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
regDeviceData: {},
|
regDeviceData: {},
|
||||||
@@ -25,9 +28,13 @@ export const deviceReducer = (state = initialState, action) => {
|
|||||||
case types.CLEAR_REGISTER_DEVICE_INFO:
|
case types.CLEAR_REGISTER_DEVICE_INFO:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
regDeviceInfoData: { retCode: undefined },
|
regDeviceData: null,
|
||||||
|
};
|
||||||
|
case types.REGISTER_DEVICE_RESET:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
regDeviceData: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,6 +321,7 @@ export default function HomeBanner({
|
|||||||
<OptionalConfirm
|
<OptionalConfirm
|
||||||
open={isOptionalConfirmVisible}
|
open={isOptionalConfirmVisible}
|
||||||
spotlightId="optional-confirm-popup"
|
spotlightId="optional-confirm-popup"
|
||||||
|
onClose={handleOptionalDeclineClick}
|
||||||
onOptionalTermsClick={handleOptionalTermsClick}
|
onOptionalTermsClick={handleOptionalTermsClick}
|
||||||
onOptionalAgreeClick={handleOptionalAgreeClick}
|
onOptionalAgreeClick={handleOptionalAgreeClick}
|
||||||
onOptionalDeclineClick={handleOptionalDeclineClick}
|
onOptionalDeclineClick={handleOptionalDeclineClick}
|
||||||
@@ -337,7 +338,7 @@ export default function HomeBanner({
|
|||||||
<TNewPopUp
|
<TNewPopUp
|
||||||
kind="introTermsPopup"
|
kind="introTermsPopup"
|
||||||
open={isOptionalTermsVisible}
|
open={isOptionalTermsVisible}
|
||||||
// onClose={handleTermsPopupClosed}
|
onClose={handleTermsPopupClosed}
|
||||||
onClick={handleTermsPopupClosed}
|
onClick={handleTermsPopupClosed}
|
||||||
onIntroTermsAgreeClick={handleTermsPopupAgree}
|
onIntroTermsAgreeClick={handleTermsPopupAgree}
|
||||||
hasButton
|
hasButton
|
||||||
|
|||||||
@@ -117,24 +117,25 @@ export default function IntroPanel({
|
|||||||
|
|
||||||
// 상태 관리
|
// 상태 관리
|
||||||
const [currentTerms, setCurrentTerms] = useState(null);
|
const [currentTerms, setCurrentTerms] = useState(null);
|
||||||
const [termsChecked, setTermsChecked] = useState(true); // Terms & Conditions 기본 체크
|
const [termsChecked, setTermsChecked] = useState(false); // Terms & Conditions 기본 체크
|
||||||
const [privacyChecked, setPrivacyChecked] = useState(true); // Privacy Policy 기본 체크
|
const [privacyChecked, setPrivacyChecked] = useState(false); // Privacy Policy 기본 체크
|
||||||
const [optionalChecked, setOptionalChecked] = useState(false); // Optional Terms 기본 체크 안됨
|
const [optionalChecked, setOptionalChecked] = useState(false); // Optional Terms 기본 체크 안됨
|
||||||
const [selectAllChecked, setSelectAllChecked] = useState(false);
|
const [selectAllChecked, setSelectAllChecked] = useState(false);
|
||||||
const [focusedItem, setFocusedItem] = useState(null); // 포커스 추적 상태 추가
|
const [focusedItem, setFocusedItem] = useState(null); // 포커스 추적 상태 추가
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
dispatch({ type: types.REGISTER_DEVICE_RESET });
|
||||||
dispatch(sendLogGNB(Config.LOG_MENU.TERMS_CONDITIONS));
|
dispatch(sendLogGNB(Config.LOG_MENU.TERMS_CONDITIONS));
|
||||||
}, []);
|
}, [dispatch]);
|
||||||
|
|
||||||
// 컴포넌트 마운트 시 현재 Redux 상태 로깅
|
// 컴포넌트 마운트 시 현재 Redux 상태 로깅
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
console.log('🔍 IntroPanel 마운트 시 Redux 상태:');
|
// console.log('🔍 IntroPanel 마운트 시 Redux 상태:');
|
||||||
console.log(' - regDeviceData:', regDeviceData);
|
// console.log(' - regDeviceData:', regDeviceData);
|
||||||
console.log(' - regDeviceInfoData:', regDeviceInfoData);
|
// console.log(' - regDeviceInfoData:', regDeviceInfoData);
|
||||||
console.log(' - eventInfos:', eventInfos);
|
// console.log(' - eventInfos:', eventInfos);
|
||||||
console.log(' - termsData:', termsData);
|
// console.log(' - termsData:', termsData);
|
||||||
}, []);
|
// }, []);
|
||||||
|
|
||||||
// 디버깅용 WebOS 버전 로그
|
// 디버깅용 WebOS 버전 로그
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -247,16 +248,16 @@ export default function IntroPanel({
|
|||||||
if (isProcessing) return;
|
if (isProcessing) return;
|
||||||
|
|
||||||
// 필수 약관이 체크되어 있는지 확인
|
// 필수 약관이 체크되어 있는지 확인
|
||||||
if (!termsChecked || !privacyChecked) {
|
// if (!termsChecked || !privacyChecked) {
|
||||||
// 필수 약관이 체크되지 않았을 때 알림
|
// // 필수 약관이 체크되지 않았을 때 알림
|
||||||
// window.alert($L("Please agree to Terms & Conditions and Privacy Policy."));
|
// // window.alert($L("Please agree to Terms & Conditions and Privacy Policy."));
|
||||||
dispatch(setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
// dispatch(setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
||||||
title: $L("Required Terms"),
|
// title: $L("Required Terms"),
|
||||||
text: $L("Please agree to Terms & Conditions and Privacy Policy."),
|
// text: $L("Please agree to Terms & Conditions and Privacy Policy."),
|
||||||
button1Text: $L("OK")
|
// button1Text: $L("OK")
|
||||||
}));
|
// }));
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
setIsProcessing(true);
|
setIsProcessing(true);
|
||||||
// 약관 동의 처리 시작 시 로딩 상태로 설정
|
// 약관 동의 처리 시작 시 로딩 상태로 설정
|
||||||
@@ -352,7 +353,10 @@ export default function IntroPanel({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// isProcessing이 true일 때만 실패 체크 (= handleAgree 클릭 후에만)
|
// isProcessing이 true일 때만 실패 체크 (= handleAgree 클릭 후에만)
|
||||||
if (isProcessing && regDeviceData && regDeviceData.retCode !== 0) {
|
if (isProcessing && regDeviceData && regDeviceData.retCode !== 0) {
|
||||||
console.error("registerDevice 실패:", regDeviceData);
|
console.error(
|
||||||
|
`[IntroPanel] registerDevice 실패: isProcessing=${isProcessing}, retCode=${regDeviceData.retCode}`,
|
||||||
|
regDeviceData
|
||||||
|
);
|
||||||
dispatch(
|
dispatch(
|
||||||
setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
||||||
title: $L("Error"),
|
title: $L("Error"),
|
||||||
@@ -394,13 +398,11 @@ export default function IntroPanel({
|
|||||||
blurTimeout.current = null;
|
blurTimeout.current = null;
|
||||||
}
|
}
|
||||||
setFocusedItem(item);
|
setFocusedItem(item);
|
||||||
setIsRequiredFocused(item === 'required');
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleBlur = useCallback(() => {
|
const handleBlur = useCallback(() => {
|
||||||
blurTimeout.current = setTimeout(() => {
|
blurTimeout.current = setTimeout(() => {
|
||||||
setFocusedItem(null);
|
setFocusedItem(null);
|
||||||
setIsRequiredFocused(false);
|
|
||||||
}, 0);
|
}, 0);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -426,6 +428,32 @@ export default function IntroPanel({
|
|||||||
|
|
||||||
|
|
||||||
const rightPanelContent = useMemo(() => {
|
const rightPanelContent = useMemo(() => {
|
||||||
|
const requiredItemIds = [
|
||||||
|
"termsCheckbox",
|
||||||
|
"termsButton",
|
||||||
|
"privacyCheckbox",
|
||||||
|
"privacyButton",
|
||||||
|
];
|
||||||
|
if (!requiredItemIds.includes(focusedItem)) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{shouldShowBenefitsView ? (
|
||||||
|
<div className={css.optionalDescription}>
|
||||||
|
{$L(
|
||||||
|
'By checking "Optional terms", you allow Shop Time to use your activity (views, purchases, searches, etc.) to show you more relevant content, product recommendations, special offers, and ads. If you do not check, you can still use all basic Shop Time features'
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<OptionalTermsInfo
|
||||||
|
displayMode="image"
|
||||||
|
imageTitle={$L("Agree and Enjoy Special Benefits")}
|
||||||
|
spotlightId="optional-terms-info"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const hasRequiredUnchecked = !termsChecked || !privacyChecked;
|
const hasRequiredUnchecked = !termsChecked || !privacyChecked;
|
||||||
|
|
||||||
// 우선순위 1: 필수 약관이 체크 안됨 → 항상 경고 메시지
|
// 우선순위 1: 필수 약관이 체크 안됨 → 항상 경고 메시지
|
||||||
@@ -433,54 +461,43 @@ export default function IntroPanel({
|
|||||||
return (
|
return (
|
||||||
<div className={css.requiredInfoPanel}>
|
<div className={css.requiredInfoPanel}>
|
||||||
<p className={css.infoText}>{$L("Required Consent")}</p>
|
<p className={css.infoText}>{$L("Required Consent")}</p>
|
||||||
<p className={css.infoText}>{$L("(Necessary for using the service)")}</p>
|
<p className={css.infoText}>
|
||||||
|
{$L("(Necessary for using the service)")}
|
||||||
|
</p>
|
||||||
<div className={css.warningContainer}>
|
<div className={css.warningContainer}>
|
||||||
<p className={css.warningText}>{$L("Please agree to the required Terms & Conditions and")}</p>
|
<p className={css.warningText}>
|
||||||
<p className={css.warningText}>{$L("Privacy Policy to start enjoying Shop Time")}</p>
|
{$L("Please agree to the required Terms & Conditions and")}
|
||||||
|
</p>
|
||||||
|
<p className={css.warningText}>
|
||||||
|
{$L("Privacy Policy to start enjoying Shop Time")}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 우선순위 2: 필수 약관에 포커스 있음 → 필수 약관 안내
|
// 우선순위 2: 필수 약관에 포커스 있음 → 필수 약관 안내
|
||||||
if (isRequiredFocused) {
|
|
||||||
return (
|
|
||||||
<div className={css.requiredInfoPanel}>
|
|
||||||
<p className={css.infoText}>{$L("Required Consent")}</p>
|
|
||||||
<p className={css.infoText}>{$L("(Necessary for using the service)")}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 우선순위 3: 기본값 → 선택 약관 정보
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={css.requiredInfoPanel}>
|
||||||
{shouldShowBenefitsView ? (
|
<p className={css.infoText}>{$L("Required Consent")}</p>
|
||||||
<div className={css.optionalDescription}>
|
<p className={css.infoText}>
|
||||||
{$L('By checking "Optional terms", you allow Shop Time to use your activity (views, purchases, searches, etc.) to show you more relevant content, product recommendations, special offers, and ads. If you do not check, you can still use all basic Shop Time features')}
|
{$L("(Necessary for using the service)")}
|
||||||
</div>
|
</p>
|
||||||
) : (
|
</div>
|
||||||
<OptionalTermsInfo
|
|
||||||
displayMode="image"
|
|
||||||
imageTitle={$L('Agree and Enjoy Special Benefits')}
|
|
||||||
spotlightId="optional-terms-info"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}, [termsChecked, privacyChecked, isRequiredFocused, shouldShowBenefitsView]);
|
}, [termsChecked, privacyChecked, focusedItem, shouldShowBenefitsView]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Spotlight.focus();
|
Spotlight.focus();
|
||||||
}, [popupVisible]);
|
}, [popupVisible]);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (regDeviceInfoData && regDeviceInfoData.retCode === 0) {
|
// if (regDeviceInfoData && regDeviceInfoData.retCode === 0) {
|
||||||
dispatch(setHidePopup());
|
// dispatch(setHidePopup());
|
||||||
dispatch(popPanel(panel_names.INTRO_PANEL));
|
// dispatch(popPanel(panel_names.INTRO_PANEL));
|
||||||
}
|
// }
|
||||||
}, [dispatch, regDeviceInfoData]);
|
// }, [dispatch, regDeviceInfoData]);
|
||||||
|
|
||||||
const description = $L(
|
const description = $L(
|
||||||
"Check out more LIVE SHOWS now and enjoy shopping at Shop Time's special price on your TV by agreeing to the LG TV Shopping Terms and Conditions."
|
"Check out more LIVE SHOWS now and enjoy shopping at Shop Time's special price on your TV by agreeing to the LG TV Shopping Terms and Conditions."
|
||||||
@@ -536,7 +553,7 @@ export default function IntroPanel({
|
|||||||
className={css.customeCheckbox}
|
className={css.customeCheckbox}
|
||||||
selected={termsChecked}
|
selected={termsChecked}
|
||||||
onToggle={handleTermsToggle}
|
onToggle={handleTermsToggle}
|
||||||
onFocus={() => handleFocus('required')}
|
onFocus={() => handleFocus('termsCheckbox')}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
spotlightId="termsCheckbox"
|
spotlightId="termsCheckbox"
|
||||||
ariaLabel={$L("Terms & Conditions checkbox")}
|
ariaLabel={$L("Terms & Conditions checkbox")}
|
||||||
@@ -544,7 +561,7 @@ export default function IntroPanel({
|
|||||||
<TButton
|
<TButton
|
||||||
className={css.termsButton}
|
className={css.termsButton}
|
||||||
onClick={() => handleTermsClick("MST00402")}
|
onClick={() => handleTermsClick("MST00402")}
|
||||||
onFocus={() => handleFocus('required')}
|
onFocus={() => handleFocus('termsButton')}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
spotlightId="termsButton"
|
spotlightId="termsButton"
|
||||||
type={TYPES.terms}
|
type={TYPES.terms}
|
||||||
@@ -562,7 +579,7 @@ export default function IntroPanel({
|
|||||||
className={css.customeCheckbox}
|
className={css.customeCheckbox}
|
||||||
selected={privacyChecked}
|
selected={privacyChecked}
|
||||||
onToggle={handlePrivacyToggle}
|
onToggle={handlePrivacyToggle}
|
||||||
onFocus={() => handleFocus('required')}
|
onFocus={() => handleFocus('privacyCheckbox')}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
spotlightId="privacyCheckbox"
|
spotlightId="privacyCheckbox"
|
||||||
ariaLabel={$L("Privacy Policy checkbox")}
|
ariaLabel={$L("Privacy Policy checkbox")}
|
||||||
@@ -570,7 +587,7 @@ export default function IntroPanel({
|
|||||||
<TButton
|
<TButton
|
||||||
className={css.termsButton}
|
className={css.termsButton}
|
||||||
onClick={() => handleTermsClick("MST00401")}
|
onClick={() => handleTermsClick("MST00401")}
|
||||||
onFocus={() => handleFocus('required')}
|
onFocus={() => handleFocus('privacyButton')}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
spotlightId="privacyButton"
|
spotlightId="privacyButton"
|
||||||
type={TYPES.terms}
|
type={TYPES.terms}
|
||||||
@@ -588,7 +605,7 @@ export default function IntroPanel({
|
|||||||
className={css.customeCheckbox}
|
className={css.customeCheckbox}
|
||||||
selected={optionalChecked}
|
selected={optionalChecked}
|
||||||
onToggle={handleOptionalToggle}
|
onToggle={handleOptionalToggle}
|
||||||
onFocus={() => handleFocus('optional')}
|
onFocus={() => handleFocus('optionalCheckbox')}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
spotlightId="optionalCheckbox"
|
spotlightId="optionalCheckbox"
|
||||||
ariaLabel={$L("Optional Terms checkbox")}
|
ariaLabel={$L("Optional Terms checkbox")}
|
||||||
@@ -596,7 +613,7 @@ export default function IntroPanel({
|
|||||||
<TButton
|
<TButton
|
||||||
className={css.termsButton}
|
className={css.termsButton}
|
||||||
onClick={() => handleOptionalTermsClick("MST00405")}
|
onClick={() => handleOptionalTermsClick("MST00405")}
|
||||||
onFocus={() => handleFocus('optional')}
|
onFocus={() => handleFocus('optionalButton')}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
spotlightId="optionalButton"
|
spotlightId="optionalButton"
|
||||||
type={TYPES.terms}
|
type={TYPES.terms}
|
||||||
@@ -619,6 +636,8 @@ export default function IntroPanel({
|
|||||||
className={css.selectAllCheckbox}
|
className={css.selectAllCheckbox}
|
||||||
selected={selectAllChecked}
|
selected={selectAllChecked}
|
||||||
onToggle={handleSelectAllToggle}
|
onToggle={handleSelectAllToggle}
|
||||||
|
onFocus={() => handleFocus('selectAllCheckbox')}
|
||||||
|
onBlur={handleBlur}
|
||||||
spotlightId="selectAllCheckbox"
|
spotlightId="selectAllCheckbox"
|
||||||
ariaLabel={$L("Select All checkbox")}
|
ariaLabel={$L("Select All checkbox")}
|
||||||
/>
|
/>
|
||||||
@@ -632,6 +651,8 @@ export default function IntroPanel({
|
|||||||
<TButton
|
<TButton
|
||||||
className={css.agreeButton}
|
className={css.agreeButton}
|
||||||
onClick={handleAgree}
|
onClick={handleAgree}
|
||||||
|
onFocus={() => handleFocus('agreeButton')}
|
||||||
|
onBlur={handleBlur}
|
||||||
spotlightId="agreeButton"
|
spotlightId="agreeButton"
|
||||||
type={TYPES.agree}
|
type={TYPES.agree}
|
||||||
ariaLabel={$L("Agree to terms")}
|
ariaLabel={$L("Agree to terms")}
|
||||||
@@ -643,6 +664,8 @@ export default function IntroPanel({
|
|||||||
<TButton
|
<TButton
|
||||||
className={css.disagreeButton}
|
className={css.disagreeButton}
|
||||||
onClick={handleDisagree}
|
onClick={handleDisagree}
|
||||||
|
onFocus={() => handleFocus('disagreeButton')}
|
||||||
|
onBlur={handleBlur}
|
||||||
spotlightId="disagreeButton"
|
spotlightId="disagreeButton"
|
||||||
type={TYPES.agree}
|
type={TYPES.agree}
|
||||||
ariaLabel={$L("Do not agree to terms")}
|
ariaLabel={$L("Do not agree to terms")}
|
||||||
@@ -710,8 +733,8 @@ export default function IntroPanel({
|
|||||||
hasButton
|
hasButton
|
||||||
button1Text={popupState.button1Text || $L("OK")}
|
button1Text={popupState.button1Text || $L("OK")}
|
||||||
hasText
|
hasText
|
||||||
title={$L("Required Terms")}
|
title={popupState.title || ""}
|
||||||
text={$L("Please agree to Terms & Conditions and Privacy Policy.")}
|
text={popupState.text || ""}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default function TermsOfService({ title, cbScrollTo }) {
|
|||||||
const [optionalDisagreePopupOpen, setOptionalDisagreePopupOpen] =
|
const [optionalDisagreePopupOpen, setOptionalDisagreePopupOpen] =
|
||||||
useState(false);
|
useState(false);
|
||||||
const [showCheckboxAlert, setShowCheckboxAlert] = useState(false);
|
const [showCheckboxAlert, setShowCheckboxAlert] = useState(false);
|
||||||
|
const agreePopupTimeoutRef = useRef(null);
|
||||||
|
|
||||||
const { popupVisible } = useSelector((state) => state.common?.popup);
|
const { popupVisible } = useSelector((state) => state.common?.popup);
|
||||||
const { optionalTermsAgree } = useSelector((state) => state.common);
|
const { optionalTermsAgree } = useSelector((state) => state.common);
|
||||||
@@ -60,16 +60,33 @@ export default function TermsOfService({ title, cbScrollTo }) {
|
|||||||
);
|
);
|
||||||
const [spotlightDisabled, setSpotlightDisabled] = useState(true);
|
const [spotlightDisabled, setSpotlightDisabled] = useState(true);
|
||||||
const [termsList, setTermsList] = useState([]);
|
const [termsList, setTermsList] = useState([]);
|
||||||
|
const termsListRef = useRef(termsList);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const focusJob = useRef(null);
|
const focusJob = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (agreePopupTimeoutRef.current) {
|
||||||
|
clearTimeout(agreePopupTimeoutRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
dispatch(fetchCurrentUserHomeTerms());
|
dispatch(fetchCurrentUserHomeTerms());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// console.log(
|
||||||
|
// "[TermsOfService] termsData:",
|
||||||
|
// JSON.stringify(termsData, null, 2)
|
||||||
|
// );
|
||||||
|
// console.log(
|
||||||
|
// "[TermsOfService] empTermsData:",
|
||||||
|
// JSON.stringify(empTermsData, null, 2)
|
||||||
|
// );
|
||||||
const newTabList = [];
|
const newTabList = [];
|
||||||
const tempList = [];
|
const tempList = [];
|
||||||
const newTrmsCdList = [];
|
const newTrmsCdList = [];
|
||||||
@@ -106,11 +123,19 @@ export default function TermsOfService({ title, cbScrollTo }) {
|
|||||||
|
|
||||||
setTabList(newTabList);
|
setTabList(newTabList);
|
||||||
setTermsList(tempList);
|
setTermsList(tempList);
|
||||||
|
// console.log(
|
||||||
|
// "[TermsOfService] Final termsList:",
|
||||||
|
// JSON.stringify(tempList, null, 2)
|
||||||
|
// );
|
||||||
setTrmsCdList(newTrmsCdList);
|
setTrmsCdList(newTrmsCdList);
|
||||||
|
|
||||||
setSpotlightDisabled(false);
|
setSpotlightDisabled(false);
|
||||||
}, [termsData, empTermsData, webOSVersion]);
|
}, [termsData, empTermsData, webOSVersion]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
termsListRef.current = termsList;
|
||||||
|
}, [termsList]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (termsData && termsData.data && termsData.data.terms) {
|
if (termsData && termsData.data && termsData.data.terms) {
|
||||||
dispatch(getTermsAgreeYn());
|
dispatch(getTermsAgreeYn());
|
||||||
@@ -216,39 +241,47 @@ export default function TermsOfService({ title, cbScrollTo }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleOptionalAgree = useCallback(() => {
|
const handleOptionalAgree = useCallback(() => {
|
||||||
console.log(
|
// console.log(
|
||||||
"handleOptionalAgree called with isChecked:",
|
// "handleOptionalAgree called with isChecked:",
|
||||||
isOptionalChecked
|
// isOptionalChecked
|
||||||
);
|
// );
|
||||||
if (isOptionalChecked) {
|
// if (isOptionalChecked) {
|
||||||
const firstThreeTermIds = termsList
|
const firstThreeTermIds = termsList
|
||||||
.slice(0, 3)
|
.slice(0, 3)
|
||||||
.map((term) => term.termsId)
|
.map((term) => term.termsId)
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
if (firstThreeTermIds.length > 0) {
|
if (firstThreeTermIds.length > 0) {
|
||||||
const payload = { termsList: firstThreeTermIds, notTermsList: [] };
|
const payload = { termsList: firstThreeTermIds, notTermsList: [] };
|
||||||
console.log("Dispatching setMyPageTermsAgree with payload:", payload);
|
// console.log("Dispatching setMyPageTermsAgree with payload:", payload);
|
||||||
dispatch(
|
dispatch(
|
||||||
setMyPageTermsAgree(payload, (response) => {
|
setMyPageTermsAgree(payload, (response) => {
|
||||||
console.log("setMyPageTermsAgree callback response:", response);
|
// console.log("setMyPageTermsAgree callback response:", response);
|
||||||
if (response.retCode === "000" || response.retCode === 0) {
|
if (response.retCode === "000" || response.retCode === 0) {
|
||||||
console.log("Optional terms agreement successful.");
|
console.log("Optional terms agreement successful.");
|
||||||
// 약관 동의의 후 약관 정보 조회
|
// 약관 동의의 후 약관 정보 조회
|
||||||
dispatch(fetchCurrentUserHomeTerms());
|
dispatch(fetchCurrentUserHomeTerms());
|
||||||
setAgreePopup(true);
|
setAgreePopup(true);
|
||||||
} else {
|
|
||||||
console.error("Optional terms agreement failed:", response);
|
if (agreePopupTimeoutRef.current) {
|
||||||
|
clearTimeout(agreePopupTimeoutRef.current);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
);
|
agreePopupTimeoutRef.current = setTimeout(() => {
|
||||||
} else {
|
setAgreePopup(false);
|
||||||
console.log("No terms found to agree to.");
|
}, 3000);
|
||||||
}
|
} else {
|
||||||
|
console.error("Optional terms agreement failed:", response);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log("Checkbox not checked, not proceeding with agreement.");
|
// console.log("No terms found to agree to.");
|
||||||
setShowCheckboxAlert(true);
|
|
||||||
}
|
}
|
||||||
|
// } else {
|
||||||
|
// console.log("Checkbox not checked, not proceeding with agreement.");
|
||||||
|
// setShowCheckboxAlert(true);
|
||||||
|
// }
|
||||||
}, [dispatch, termsList, isOptionalChecked]);
|
}, [dispatch, termsList, isOptionalChecked]);
|
||||||
|
|
||||||
const handleOptionalDisagree = useCallback(() => {
|
const handleOptionalDisagree = useCallback(() => {
|
||||||
@@ -256,32 +289,43 @@ export default function TermsOfService({ title, cbScrollTo }) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const confirmOptionalDisagree = useCallback(() => {
|
const confirmOptionalDisagree = useCallback(() => {
|
||||||
const optionalTerm = termsList.find(
|
const currentTermsList = termsListRef.current;
|
||||||
|
// console.log("optionalTermsAgree:", currentTermsList);
|
||||||
|
const optionalTerm = currentTermsList.find(
|
||||||
(term) => term.trmsTpCd === "MST00405"
|
(term) => term.trmsTpCd === "MST00405"
|
||||||
);
|
);
|
||||||
|
// console.log("optionalTerm:", JSON.stringify(optionalTerm, null, 2));
|
||||||
|
|
||||||
|
// if (optionalTerm) {
|
||||||
|
// console.log("optionalTerm.termsId:", optionalTerm.termsId);
|
||||||
|
// }
|
||||||
|
|
||||||
if (optionalTerm && optionalTerm.termsId) {
|
if (optionalTerm && optionalTerm.termsId) {
|
||||||
const payload = {
|
const payload = {
|
||||||
mandatoryIncludeYn: "N",
|
mandatoryIncludeYn: "N",
|
||||||
termsList: [optionalTerm.termsId],
|
termsList: [optionalTerm.termsId],
|
||||||
};
|
};
|
||||||
console.log("Dispatching setMyTermsWithdraw with payload:", payload);
|
// console.log("Dispatching setMyTermsWithdraw with payload:", payload);
|
||||||
// 선택약관 철회
|
// 선택약관 철회
|
||||||
dispatch(setMyTermsWithdraw(payload, (response) => {
|
dispatch(
|
||||||
console.log("setMyTermsWithdraw callback response:", response);
|
setMyTermsWithdraw(payload, (response) => {
|
||||||
if (response.retCode === "000" || response.retCode === 0) {
|
// console.log("setMyTermsWithdraw callback response:", response);
|
||||||
console.log("Optional terms withdrawal successful.");
|
if (response.retCode === "000" || response.retCode === 0) {
|
||||||
// 약관 철회 후 약관 정보 조회
|
console.log("Optional terms withdrawal successful.");
|
||||||
dispatch(fetchCurrentUserHomeTerms());
|
// 약관 철회 후 약관 정보 조회
|
||||||
setIsOptionalChecked(false);
|
dispatch(fetchCurrentUserHomeTerms());
|
||||||
} else {
|
setIsOptionalChecked(false);
|
||||||
console.error("Optional terms withdrawal failed:", response);
|
} else {
|
||||||
}
|
console.error("Optional terms withdrawal failed:", response);
|
||||||
}));
|
}
|
||||||
|
setOptionalDisagreePopupOpen(false);
|
||||||
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log("No optional term found to disagree.");
|
// console.log("No optional term found to disagree.");
|
||||||
|
setOptionalDisagreePopupOpen(false);
|
||||||
}
|
}
|
||||||
setOptionalDisagreePopupOpen(false);
|
}, [dispatch]);
|
||||||
}, [termsList, dispatch]);
|
|
||||||
|
|
||||||
const onCancelDisagree = useCallback(() => {
|
const onCancelDisagree = useCallback(() => {
|
||||||
// setDisagreeConfirmOpen(false);
|
// setDisagreeConfirmOpen(false);
|
||||||
@@ -462,23 +506,27 @@ export default function TermsOfService({ title, cbScrollTo }) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TPopUp
|
<TPopUp
|
||||||
kind="textPopup"
|
kind="exitPopup"
|
||||||
open={agreePopup}
|
open={agreePopup}
|
||||||
onClose={() => setAgreePopup(false)}
|
onClose={() => setAgreePopup(false)}
|
||||||
hasButton
|
|
||||||
button1Text={$L("OK")}
|
|
||||||
hasText
|
hasText
|
||||||
title={$L("Agreement Complete")}
|
title={$L("")}
|
||||||
text={$L("Your agreement has been processed.")}
|
text={$L(
|
||||||
|
"From now on, you can receive personalized shopping benefits."
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 새로 추가된 optionalAgreement 팝업 */}
|
{/* 새로 추가된 optionalAgreement 팝업 */}
|
||||||
<TPopUp
|
<TPopUp
|
||||||
kind="optionalAgreement"
|
kind="exitPopup"
|
||||||
open={optionalDisagreePopupOpen}
|
open={optionalDisagreePopupOpen}
|
||||||
onClose={() => setOptionalDisagreePopupOpen(false)}
|
onClose={() => setOptionalDisagreePopupOpen(false)}
|
||||||
onClick={confirmOptionalDisagree}
|
onExit={confirmOptionalDisagree}
|
||||||
|
hasButton
|
||||||
|
button1Text={$L("Yes")}
|
||||||
|
button2Text={$L("No")}
|
||||||
hasText
|
hasText
|
||||||
|
title={$L("")}
|
||||||
text={$L("You will not receive personalized shopping benefits")}
|
text={$L("You will not receive personalized shopping benefits")}
|
||||||
/>
|
/>
|
||||||
{/* 필수약관 체크 확인 팝업 */}
|
{/* 필수약관 체크 확인 팝업 */}
|
||||||
|
|||||||
Reference in New Issue
Block a user