diff --git a/com.twin.app.shoptime/src/App/App.js b/com.twin.app.shoptime/src/App/App.js index 4712854d..d05a3635 100644 --- a/com.twin.app.shoptime/src/App/App.js +++ b/com.twin.app.shoptime/src/App/App.js @@ -185,7 +185,7 @@ function AppBase(props) { // return () => stopFocusMonitoring(); // }, []); - // 임시 작업용 코드 + // 임시 작업용 코드 -> 인트로 팝업 표시 // useEffect(() => { // const timer = setTimeout(() => { // dispatch( @@ -388,7 +388,7 @@ function AppBase(props) { }, [webOSVersion, deviceId]); - // 테스트용 팝업 표시 + // 테스트용 인트로 화면 표시 // useEffect(() => { // setTimeout(() => { // console.log("App.js optionalTermsTest 팝업 표시"); diff --git a/com.twin.app.shoptime/src/components/TButtonTab/TButtonTab.module.less b/com.twin.app.shoptime/src/components/TButtonTab/TButtonTab.module.less index 99ef1ad9..0276fa6d 100644 --- a/com.twin.app.shoptime/src/components/TButtonTab/TButtonTab.module.less +++ b/com.twin.app.shoptime/src/components/TButtonTab/TButtonTab.module.less @@ -2,7 +2,8 @@ @import "../../style/utils.module.less"; .tabs { - .size(@w: 1680px, @h: 67px); + // .size(@w: 1680px, @h: 67px); + .size(@w: 100%, @h: 67px); display: flex; position: relative; diff --git a/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.jsx b/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.jsx index 0174c50f..4cf6dc7d 100644 --- a/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.jsx +++ b/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.jsx @@ -13,6 +13,7 @@ import { cancelFocusElement, focusElement } from "../../actions/commonActions"; import { SpotlightIds } from "../../utils/SpotlightIds"; import CustomImage from "../CustomImage/CustomImage"; import TButton from "../TButton/TButton"; +import TButtonScroller from "../TButtonScroller/TButtonScroller"; import css from "./TNewPopUp.module.less"; import { $L } from "../../utils/helperMethods"; @@ -67,6 +68,7 @@ const KINDS = [ "optionalAgreement", "normal", "optionalConfirm", + "figmaTermsPopup", ]; // 각 kind별 클래스명 매핑 @@ -224,6 +226,17 @@ const CLASS_MAPPINGS = { text: "optionalConfirmText", buttonContainer: "optionalConfirmButtonContainer", contentContainer: "optionalConfirmContentContainer" // 👈 추가 + }, + figmaTermsPopup: { + info: "figmaTermsInfo", + contentContainer: "figmaTermsContentContainer", + termsCard: "figmaTermsCard", + titleBar: "figmaTermsTitleBar", + titleText: "figmaTermsTitleText", + contentBody: "figmaTermsContentBody", + buttonContainer: "figmaTermsButtonContainer", + agreeButton: "figmaTermsAgreeButton", + closeButton: "figmaTermsCloseButton" } }; @@ -314,6 +327,8 @@ export default function TNewPopUp({ focusTarget = 'introTermsAgreeBtn'; } else if (kind === 'optionalConfirm') { focusTarget = 'optionalConfirmAgreeBtn'; + } else if (kind === 'figmaTermsPopup') { + focusTarget = 'figma-terms-close'; } else if (spotlightId) { focusTarget = spotlightId; } @@ -609,7 +624,7 @@ export default function TNewPopUp({ {/* 다른 종류들의 children */} - {kind !== "optionalAgreement" && kind !== "optionalConfirm" && children} + {kind !== "optionalAgreement" && kind !== "optionalConfirm" && kind !== "figmaTermsPopup" && children} {hasIndicator && ( <> @@ -712,6 +727,49 @@ export default function TNewPopUp({ )} + + {/* [추가] figmaTermsPopup을 위한 전용 렌더링 블록 */} + {kind === "figmaTermsPopup" && ( +
+
+
+
+ {title} +
+
+
+ +
+ +
+
+ + {/* 기획 변경으로 Agree 버튼 임시 숨김 처리 + + {$L('Agree')} + + */} + + {$L('Close')} + + +
+ )} ); diff --git a/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.module.less b/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.module.less index d346ad87..412283fc 100644 --- a/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.module.less +++ b/com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.module.less @@ -1029,6 +1029,77 @@ } } } + + /* 👇 새로운 약관 팝업 스타일 */ + &.figmaTermsPopup { + .figmaTermsInfo { + .size(@w: 1064px, @h: 750px); + padding: 60px 57px 40px; + background: #E6EBF0; + box-shadow: 0px 20px 12px rgba(0, 0, 0, 0.30); + border-radius: 4px; + } + + .figmaTermsContentContainer { + display: flex; + flex-direction: column; + gap: 40px; + } + + .figmaTermsCard { + background: white; + border-radius: 4px; + border: 1px solid #CCCCCC; + overflow: hidden; + display: flex; + flex-direction: column; + } + + .figmaTermsTitleBar { + padding: 17px 31px; + border-bottom: 1px solid #CCCCCC; + } + + .figmaTermsTitleText { + color: #C70850; + font-size: 30px; + font-weight: 700; + } + + .figmaTermsContentBody { + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; + + .scrollerContent { + padding: 31px; + font-size: 26px; + line-height: 1.5; + } + } + + .figmaTermsButtonContainer { + display: flex; + justify-content: center; + gap: 12px; + } + + .figmaTermsAgreeButton { + .size(240px, 80px); + + // type="agree"의 포커스 시 font-size 변경을 막음 + &.focused, + &:focus { // :focus도 함께 처리 + font-size: 30px !important; + } + } + + .figmaTermsCloseButton { + // TButton의 기본 스타일을 그대로 사용하도록 크기만 지정 + .size(240px, 80px); + } + } } // optionalConfirm일 때만 기존 위치 스타일 무력화 diff --git a/com.twin.app.shoptime/src/views/IntroPanel/IntroPanel.new.jsx b/com.twin.app.shoptime/src/views/IntroPanel/IntroPanel.new.jsx index 8db3180c..3cca51d4 100644 --- a/com.twin.app.shoptime/src/views/IntroPanel/IntroPanel.new.jsx +++ b/com.twin.app.shoptime/src/views/IntroPanel/IntroPanel.new.jsx @@ -1,6 +1,7 @@ // src: views/IntroPanel/IntroPanel.new.jsx -import React, { useCallback, useEffect, useState, useMemo } from "react"; +import React, { useCallback, useEffect, useState, useMemo, useRef } from "react"; +import { flushSync } from "react-dom"; import { useDispatch, useSelector } from "react-redux"; @@ -12,7 +13,7 @@ import { setExitApp, setHidePopup, setShowPopup, - setTermsAgreeYn, + // setTermsAgreeYn, } from "../../actions/commonActions"; import { registerDevice } from "../../actions/deviceActions"; import { getWelcomeEventInfo } from "../../actions/eventActions"; @@ -24,12 +25,12 @@ import { } from "../../actions/logActions"; import { popPanel, pushPanel } from "../../actions/panelActions"; import TButton, { TYPES } from "../../components/TButton/TButton"; -import TButtonScroller from "../../components/TButtonScroller/TButtonScroller"; -import TButtonTab from "../../components/TButtonTab/TButtonTab"; +// import TButtonScroller from "../../components/TButtonScroller/TButtonScroller"; +// import TButtonTab from "../../components/TButtonTab/TButtonTab"; import TCheckBoxSquare from "../../components/TCheckBox/TCheckBoxSquare"; import TPanel from "../../components/TPanel/TPanel"; import TPopUp, { CONTENT_TYPES } from "../../components/TPopUp/TPopUp"; -// import TNewPopUp from "../../components/TPopUp/TNewPopUp"; +import TNewPopUp from "../../components/TPopUp/TNewPopUp"; import OptionalTermsInfo from "../MyPagePanel/MyPageSub/TermsOfService/OptionalTermsInfo"; import useDebugKey from "../../hooks/useDebugKey"; import * as Config from "../../utils/Config"; @@ -56,7 +57,9 @@ export default function IntroPanel({ delete rest.panelInfo; useDebugKey({}); - const dispatch = useDispatch(); const termsData = useSelector((state) => state.home.termsData); + const dispatch = useDispatch(); + const blurTimeout = useRef(null); + const termsData = useSelector((state) => state.home.termsData); const { popupVisible, activePopup, ...popupState } = useSelector( (state) => state.common.popup ); @@ -69,13 +72,7 @@ export default function IntroPanel({ // registerDevice API 호출 중 여부 const [isProcessing, setIsProcessing] = useState(false); const [showExitMessagePopup, setShowExitMessagePopup] = useState(false); - -// const introTermsData = termsData?.data?.terms.filter( -// (item) => item.trmsTpCd === "MST00401" || item.trmsTpCd === "MST00402" -// ); -// const optionalTermsData = termsData?.data?.terms.filter( -// (item) => item.trmsTpCd === "MST00405" -// ); + const [isRequiredFocused, setIsRequiredFocused] = useState(false); const introTermsData = useMemo(() => { return termsData?.data?.terms.filter( @@ -124,6 +121,7 @@ export default function IntroPanel({ const [privacyChecked, setPrivacyChecked] = useState(true); // Privacy Policy 기본 체크 const [optionalChecked, setOptionalChecked] = useState(false); // Optional Terms 기본 체크 안됨 const [selectAllChecked, setSelectAllChecked] = useState(false); + const [focusedItem, setFocusedItem] = useState(null); // 포커스 추적 상태 추가 useEffect(() => { dispatch(sendLogGNB(Config.LOG_MENU.TERMS_CONDITIONS)); @@ -163,31 +161,23 @@ export default function IntroPanel({ // Select All 상태 업데이트 useEffect(() => { - setSelectAllChecked(termsChecked && privacyChecked && optionalChecked); + const allChecked = termsChecked && privacyChecked && optionalChecked; + setSelectAllChecked(allChecked); + if (allChecked) { + Spotlight.focus("agreeButton"); + } }, [termsChecked, privacyChecked, optionalChecked]); - // 컴포넌트 마운트 후 1.5초 뒤에 agreeButton으로 강제 포커스 + // 컴포넌트 마운트 후 0.5초 뒤에 selectAllCheckbox으로 강제 포커스 useEffect(() => { - // 1.5초(1500ms) 후에 실행될 타이머 설정 const focusTimer = setTimeout(() => { - console.log('[Focus] 1.5초 후 agreeButton으로 강제 포커스 시도'); - - // focusById 함수를 사용하여 강제 포커스 (force: true) - const focusSuccess = focusById('agreeButton', true); - - if (focusSuccess) { - console.log('[Focus] agreeButton 포커스 성공'); - } else { - console.warn('[Focus] agreeButton 포커스 실패'); - } - }, 1500); + focusById("selectAllCheckbox"); + }, 500); - // 컴포넌트 언마운트 시 타이머 정리 return () => { clearTimeout(focusTimer); - console.log('[Focus] agreeButton 포커스 타이머 정리됨'); }; - }, []); // 빈 dependency 배열로 컴포넌트 마운트 시에만 실행 + }, []); // 약관 팝업 동의여부에 따른 이벤트 핸들러 const handleTermsAgree = useCallback(() => { @@ -334,6 +324,22 @@ export default function IntroPanel({ } }, [dispatch, activePopup]); + const handleFocus = useCallback((item) => { + if (blurTimeout.current) { + clearTimeout(blurTimeout.current); + blurTimeout.current = null; + } + setFocusedItem(item); + setIsRequiredFocused(item === 'required'); + }, []); + + const handleBlur = useCallback(() => { + blurTimeout.current = setTimeout(() => { + setFocusedItem(null); + setIsRequiredFocused(false); + }, 0); + }, []); + // 체크박스 핸들러들 const handleTermsToggle = useCallback(({ selected }) => { setTermsChecked(selected); @@ -353,12 +359,55 @@ export default function IntroPanel({ setPrivacyChecked(selected); setOptionalChecked(selected); }, []); + + const rightPanelContent = useMemo(() => { + const hasRequiredUnchecked = !termsChecked || !privacyChecked; - useEffect(() => { - Spotlight.focus("selectAllCheckbox"); - }, []); + // 우선순위 1: 필수 약관이 체크 안됨 → 항상 경고 메시지 + if (hasRequiredUnchecked) { + return ( +
+

{$L("Required Consent")}

+

{$L("(Necessary for using the service)")}

+
+

{$L("Please agree to the required Terms & Conditions and")}

+

{$L("Privacy Policy to start enjoying Shop Time")}

+
+
+ ); + } + // 우선순위 2: 필수 약관에 포커스 있음 → 필수 약관 안내 + if (isRequiredFocused) { + return ( +
+

{$L("Required Consent")}

+

{$L("(Necessary for using the service)")}

+

{$L("Thank you for agreeing to required terms!")}

+
+ ); + } + + // 우선순위 3: 기본값 → 선택 약관 정보 + return ( + <> + {shouldShowBenefitsView ? ( +
+ {$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')} +
+ ) : ( + + )} + + ); + }, [termsChecked, privacyChecked, isRequiredFocused, shouldShowBenefitsView]); + + useEffect(() => { Spotlight.focus(); }, [popupVisible]); @@ -408,6 +457,17 @@ export default function IntroPanel({ const title = "welcome to shoptime!"; delete rest.isOnTop; + // [추가] 약관 종류에 따라 팝업 제목을 반환하는 헬퍼 함수 + const getTermsPopupTitle = (terms) => { + if (!terms) return ''; + switch (terms.trmsTpCd) { + case "MST00401": return $L("Privacy Policy"); + case "MST00402": return $L("Terms & Conditions"); + case "MST00405": return $L("Optional Terms"); + default: return ''; + } + }; + return ( handleFocus('required')} + onBlur={handleBlur} spotlightId="termsCheckbox" ariaLabel={$L("Terms & Conditions checkbox")} /> handleTermsClick("MST00402")} + onFocus={() => handleFocus('required')} + onBlur={handleBlur} spotlightId="termsButton" type={TYPES.terms} ariaLabel={$L("View Terms & Conditions")} > - + {$L("Terms & Conditions")} @@ -467,17 +531,21 @@ export default function IntroPanel({ className={css.customeCheckbox} selected={privacyChecked} onToggle={handlePrivacyToggle} + onFocus={() => handleFocus('required')} + onBlur={handleBlur} spotlightId="privacyCheckbox" ariaLabel={$L("Privacy Policy checkbox")} /> handleTermsClick("MST00401")} + onFocus={() => handleFocus('required')} + onBlur={handleBlur} spotlightId="privacyButton" type={TYPES.terms} ariaLabel={$L("View Privacy Policy")} > - + {$L("Privacy Policy")} @@ -489,12 +557,16 @@ export default function IntroPanel({ className={css.customeCheckbox} selected={optionalChecked} onToggle={handleOptionalToggle} + onFocus={() => handleFocus('optional')} + onBlur={handleBlur} spotlightId="optionalCheckbox" ariaLabel={$L("Optional Terms checkbox")} /> handleOptionalTermsClick("MST00405")} + onFocus={() => handleFocus('optional')} + onBlur={handleBlur} spotlightId="optionalButton" type={TYPES.terms} ariaLabel={$L("View Optional Terms")} @@ -506,19 +578,7 @@ export default function IntroPanel({
- {shouldShowBenefitsView ? ( - // WebOS 텍스트 표시 버전 (4.5, 6.0, 22): 기존 텍스트 설명 -
- {$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')} -
- ) : ( - // WebOS 이미지 표시 버전 (4.0, 5.0, 23, 24): OptionalTermsInfo 컴포넌트로 이미지 표시 - - )} + {rightPanelContent}
@@ -544,6 +604,8 @@ export default function IntroPanel({ spotlightId="agreeButton" type={TYPES.agree} ariaLabel={$L("Agree to terms")} + disabled={!termsChecked || !privacyChecked} + spotlightDisabled={!termsChecked || !privacyChecked} > {$L("Agree")} @@ -562,19 +624,37 @@ export default function IntroPanel({ {/* 약관 보기 팝업 */} {activePopup === Config.ACTIVE_POPUP.termsPopup && ( - - )} {/* DO NOT AGREE */} + <> + {/* + + */} + + {/* TermsPopup 호출은 완전히 삭제 */} + + {/* TNewPopUp을 사용한 새로운 팝업 구현 */} + + + )} + + {/* DO NOT AGREE */} {activePopup === Config.ACTIVE_POPUP.exitPopup && ( - )} {/* ALERT POPUP (필수 약관 알림) */} + )} + + {/* ALERT POPUP (필수 약관 알림) */} {activePopup === Config.ACTIVE_POPUP.alertPopup && ( )} + {/* Final Exit Message Popup */} {showExitMessagePopup && ( section { color: @COLOR_GRAY06; @@ -10,9 +19,12 @@ .introLayout { width: 100%; height: 100%; - padding: 45.5px 43px; + padding-top: 45.5px; + padding-bottom: 45.5px; + padding-left: 43px; + padding-right: 43px; flex-direction: column; - justify-content: flex-start; + justify-content: space-between; align-items: center; gap: 40px; display: inline-flex; @@ -136,7 +148,6 @@ will-change: transform; .termsText { - // color: #207847; color: black; font-size: 35px; font-family: 'LG Smart UI'; @@ -144,37 +155,26 @@ line-height: 35px; word-wrap: break-word; transition: color 0.3s ease; + + &.required { + color: @COLOR_GREEN; + } } - // ✅ 포커스 상태 (화살표 키 네비게이션용) + // ✅ 포커스 및 호버 상태 (통합) &.focused, &:focus, - &:focus-visible { + &:focus-visible, + &:hover { outline: 4px #C91D53 solid !important; outline-offset: 2px !important; - background-color: rgba(201, 29, 83, 0.1) !important; transform: translateY(-2px) !important; box-shadow: 0 4px 12px rgba(201, 29, 83, 0.3) !important; .termsText { - // color: #C70850 !important; font-weight: bold !important; } } - - // ✅ 호버 효과 (마우스용) - &:hover { - outline: 2px #C91D53 solid; - outline-offset: 2px; - background-color: rgba(201, 29, 83, 0.1); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(201, 29, 83, 0.3); - - .termsText { - color: #C70850; - font-weight: bold; - } - } } } } .termsRightPanel { @@ -255,7 +255,7 @@ transition: all 0.3s ease; // 포커스 상태 - &.focused { + &.focused:not(:disabled) { background-color: #a40640 !important; border-color: #a40640 !important; color: white !important; @@ -263,7 +263,7 @@ } // 호버 효과 - &:hover { + &:hover:not(:disabled) { background-color: #a40640 !important; border-color: #a40640 !important; color: white !important; @@ -342,71 +342,6 @@ } } -// ✅ 로컬 체크박스 스타일 (전체 교체) -// .customCheckbox { -// width: 45px; -// height: 45px; -// position: relative; - -// // 기본 상자 스타일 -// &:before { -// content: ''; -// width: 42px; -// height: 42px; -// background-color: @COLOR_WHITE; -// border: 2px solid @COLOR_GRAY02; -// border-radius: 4px; -// display: block; -// transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; -// } - -// // --- 상태별 스타일 정의 --- - -// // [상태 2] 선택됨: 선택되면 배경을 진한 붉은색으로 만듭니다. -// &.selected:before { -// background-color: #C91D53; -// border-color: #C91D53; -// } - -// // [상태 3] 포커스 받았지만, 선택은 안됨: 이때만 배경을 연한 붉은색으로 만듭니다. -// &.focused:not(.selected):before { -// background-color: rgba(201, 29, 83, 0.1); -// } - -// // [상태 1] 포커스 받음: 어떤 상태든 포커스를 받으면 굵고 붉은 테두리와 그림자 효과를 줍니다. -// // 이 규칙을 다른 상태들보다 아래에 두어 우선순위를 높입니다. -// &.focused:before { -// border: 4px solid #C91D53; -// box-shadow: 0 0 10px rgba(199, 8, 80, 0.3); -// } - -// // [상태 4] 선택됨 (체크마크): 선택되었을 때만 체크마크를 표시합니다. -// &.selected:after { -// content: '✓'; -// color: @COLOR_WHITE; -// font-size: 24px; -// font-weight: bold; -// position: absolute; -// top: 50%; -// left: 50%; -// transform: translate(-50%, -50%); -// } - -// // [상태 5] 비활성화됨 -// &.disabled:before { -// background-color: @COLOR_GRAY01; -// border-color: @COLOR_GRAY02; -// opacity: 0.5; -// } - -// // [상태 6] 비활성화 상태에서 포커스 받음 -// &.disabled.focused:before { -// background-color: #C91D53; -// border-color: #C91D53; // 비활성화 포커스는 배경색만 변경하므로, 테두리는 포커스 기본 스타일을 따름 -// opacity: 1; -// } -// } - // ✅ 로컬 체크박스 스타일 (전체 교체) .customCheckbox { width: 45px; @@ -463,4 +398,31 @@ left: 50%; transform: translate(-50%, -50%); } +} + +// ✅ [추가] 필수 약관 안내 패널 스타일 +.requiredInfoPanel { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; // 왼쪽 정렬 +} + +.infoText { + color: @COLOR_GRAY; + font-size: 28px; + line-height: 1.4; +} + +.warningContainer { + margin-top: 20px; +} + +.warningText { + color: @COLOR_RED; + font-size: 28px; + line-height: 1.4; + font-weight: bold; } \ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/OptionalTermsInfo.module.less b/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/OptionalTermsInfo.module.less index efb78ee7..b7f984af 100644 --- a/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/OptionalTermsInfo.module.less +++ b/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/OptionalTermsInfo.module.less @@ -80,10 +80,10 @@ transition: transform 0.3s ease, box-shadow 0.3s ease; } -.benefitImage:hover { - transform: scale(1.08); - box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2); -} +// .benefitImage:hover { +// transform: scale(1.08); +// box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2); +// } .imageCount1 .benefitImage { height: 95%; diff --git a/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/TermsOfService.jsx b/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/TermsOfService.jsx index 628aa6e8..54dd19a6 100644 --- a/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/TermsOfService.jsx +++ b/com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/TermsOfService.jsx @@ -10,6 +10,7 @@ import { useDispatch, useSelector } from "react-redux"; import Spotlight from "@enact/spotlight"; import { Job } from "@enact/core/util"; +import classnames from "classnames"; import { changeLocalSettings, @@ -283,6 +284,10 @@ export default function TermsOfService({ title, cbScrollTo }) { // setDisagreeConfirmOpen(false); }, []); + const isOptionalTab = useMemo(() => { + return termsList[selectedTab]?.trmsTpCd === "MST00405"; + }, [termsList, selectedTab]); + const termsAriaLabel = useMemo(() => { if (!termsList || !termsList[selectedTab]) return ""; @@ -300,37 +305,46 @@ export default function TermsOfService({ title, cbScrollTo }) {
-
+
- -
-
-
- +
+ {isOptionalTab ? ( +
+
+
+ ) : ( + +
+
+
+ + )} +
{termsList[selectedTab]?.trmsTpCd === "MST00405" ? (
setOptionalDisagreePopupOpen(false)} onClick={confirmOptionalDisagree} hasText - text={$L("Are you sure you want to disagree with the optional terms?")} + text={$L("You will not receive personalized shopping benefits")} /> {/* 필수약관 체크 확인 팝업 */}