835 lines
27 KiB
JavaScript
835 lines
27 KiB
JavaScript
// src: views/IntroPanel/IntroPanel.new.jsx
|
|
|
|
import React, {
|
|
useCallback,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState,
|
|
} from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import Region from "@enact/sandstone/Region";
|
|
import Spotlight from "@enact/spotlight";
|
|
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
|
import {
|
|
setExitApp,
|
|
setHidePopup,
|
|
setShowPopup,
|
|
// setTermsAgreeYn,
|
|
} from "../../actions/commonActions";
|
|
import { registerDevice } from "../../actions/deviceActions";
|
|
import { getWelcomeEventInfo } from "../../actions/eventActions";
|
|
// import { fetchCurrentUserHomeTermsPromise } from "../../actions/homeActions";
|
|
import {
|
|
sendLogGNB,
|
|
sendLogTerms,
|
|
sendLogTotalRecommend,
|
|
} 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 TCheckBoxSquare from "../../components/TCheckBox/TCheckBoxSquare";
|
|
import TPanel from "../../components/TPanel/TPanel";
|
|
import TPopUp from "../../components/TPopUp/TPopUp";
|
|
import TNewPopUp from "../../components/TPopUp/TNewPopUp";
|
|
// import OptionalTermsInfo from "../MyPagePanel/MyPageSub/TermsOfService/OptionalTermsInfo";
|
|
import useDebugKey from "../../hooks/useDebugKey";
|
|
import useSafeFocusState from "../../hooks/useSafeFocusState";
|
|
import useTermsStateMachine from "../../hooks/useTermsStateMachine";
|
|
import useRightPanelContent from "../../hooks/useRightPanelContent";
|
|
import * as Config from "../../utils/Config";
|
|
import { panel_names } from "../../utils/Config";
|
|
import { $L } from "../../utils/helperMethods";
|
|
import css from "./IntroPanel.new.module.less";
|
|
import { types } from "../../actions/actionTypes";
|
|
import { focusById } from "../../utils/spotlight-utils";
|
|
|
|
const Container = SpotlightContainerDecorator(
|
|
{ enterTo: "last-focused" },
|
|
"div",
|
|
);
|
|
|
|
export default function IntroPanel({
|
|
// children,
|
|
// isTabActivated,
|
|
// handleCancel,
|
|
spotlightId,
|
|
...rest
|
|
}) {
|
|
delete rest.isTabActivated;
|
|
delete rest.panelInfo;
|
|
|
|
useDebugKey({});
|
|
const dispatch = useDispatch();
|
|
// const blurTimeout = useRef(null);
|
|
const termsData = useSelector((state) => state.home.termsData);
|
|
const termsIdMap = useSelector((state) => state.home.termsIdMap);
|
|
const { popupVisible, activePopup, ...popupState } = useSelector(
|
|
(state) => state.common.popup,
|
|
);
|
|
// const eventInfos = useSelector((state) => state.event.eventData);
|
|
const regDeviceData = useSelector((state) => state.device.regDeviceData);
|
|
// const regDeviceInfoData = useSelector(
|
|
// (state) => state.device.regDeviceInfoData
|
|
// );
|
|
|
|
// registerDevice API 호출 중 여부
|
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
const [showExitMessagePopup, setShowExitMessagePopup] = useState(false);
|
|
// race condition 방지를 위한 안전장치
|
|
const processingTimeoutRef = useRef(null);
|
|
// const [isRequiredFocused, setIsRequiredFocused] = useState(false);
|
|
|
|
const { focusedItem, setFocusAsync, clearFocusAsync } = useSafeFocusState();
|
|
const { state: termsState, updateStateAsync } = useTermsStateMachine();
|
|
const {
|
|
termsChecked,
|
|
privacyChecked,
|
|
optionalChecked,
|
|
selectAllChecked,
|
|
error: termsError, // 훅의 에러 상태를 가져옴
|
|
} = termsState;
|
|
|
|
const introTermsData = useMemo(() => {
|
|
return (
|
|
termsData?.data?.terms.filter(
|
|
(item) => item.trmsTpCd === "MST00401" || item.trmsTpCd === "MST00402",
|
|
) || []
|
|
);
|
|
}, [termsData]);
|
|
|
|
const optionalTermsData = useMemo(() => {
|
|
return (
|
|
termsData?.data?.terms.filter(
|
|
(item) => item.trmsTpCd === "MST00405" || item.trmsTpCd === "MST00406",
|
|
) || []
|
|
);
|
|
}, [termsData]);
|
|
|
|
const webOSVersion = useSelector(
|
|
(state) => state.common.appStatus?.webOSVersion,
|
|
);
|
|
// WebOS 버전별 UI 표시 모드 결정
|
|
// 이미지 표시: 4.0, 5.0, 23, 24
|
|
// 텍스트 표시: 4.5, 6.0, 22
|
|
const shouldShowBenefitsView = useMemo(() => {
|
|
if (!webOSVersion) return false;
|
|
|
|
const version = String(webOSVersion);
|
|
|
|
// 텍스트 표시 버전들
|
|
const textVersions = ["4.5", "6.0", "22"];
|
|
|
|
// 이미지 표시 버전들
|
|
const imageVersions = ["4.0", "5.0", "23", "24"];
|
|
|
|
// 텍스트 버전인지 확인
|
|
const shouldShowText = textVersions.includes(version);
|
|
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.log("🔍 WebOS 버전별 UI 모드:");
|
|
console.log(" - webOSVersion:", version);
|
|
console.log(" - shouldShowText (텍스트 모드):", shouldShowText);
|
|
console.log(" - 텍스트 버전들:", textVersions);
|
|
console.log(" - 이미지 버전들:", imageVersions);
|
|
}
|
|
|
|
return shouldShowText;
|
|
}, [webOSVersion]);
|
|
|
|
// 상태 관리
|
|
const [currentTerms, setCurrentTerms] = useState(null);
|
|
|
|
useEffect(() => {
|
|
dispatch({ type: types.REGISTER_DEVICE_RESET });
|
|
dispatch(sendLogGNB(Config.LOG_MENU.TERMS_CONDITIONS));
|
|
}, [dispatch]);
|
|
|
|
// 컴포넌트 마운트 시 현재 Redux 상태 로깅
|
|
// useEffect(() => {
|
|
// console.log('🔍 IntroPanel 마운트 시 Redux 상태:');
|
|
// console.log(' - regDeviceData:', regDeviceData);
|
|
// console.log(' - regDeviceInfoData:', regDeviceInfoData);
|
|
// console.log(' - eventInfos:', eventInfos);
|
|
// console.log(' - termsData:', termsData);
|
|
// }, []);
|
|
|
|
// 디버깅용 WebOS 버전 로그
|
|
useEffect(() => {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.log("🔍 IntroPanel WebOS 버전 정보:");
|
|
console.log(" - webOSVersion:", webOSVersion);
|
|
console.log(" - shouldShowBenefitsView:", shouldShowBenefitsView);
|
|
}
|
|
}, [webOSVersion, shouldShowBenefitsView]);
|
|
|
|
useEffect(() => {
|
|
if (showExitMessagePopup) {
|
|
const timer = setTimeout(() => {
|
|
dispatch(setExitApp());
|
|
dispatch(
|
|
sendLogTotalRecommend({
|
|
contextName: Config.LOG_CONTEXT_NAME.SHOPTIME,
|
|
messageId: Config.LOG_MESSAGE_ID.VIEW_CHANGE,
|
|
visible: false,
|
|
}),
|
|
);
|
|
}, 3000);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [showExitMessagePopup, dispatch]);
|
|
|
|
// 컴포넌트 마운트 후 0.5초 뒤에 selectAllCheckbox으로 강제 포커스
|
|
useEffect(() => {
|
|
const focusTimer = setTimeout(() => {
|
|
focusById("selectAllCheckbox");
|
|
}, 500);
|
|
|
|
return () => {
|
|
clearTimeout(focusTimer);
|
|
};
|
|
}, []);
|
|
|
|
// [추가] useTermsStateMachine의 에러 상태를 감지하여 팝업으로 표시
|
|
useEffect(() => {
|
|
if (termsError) {
|
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
|
title: $L("Error"),
|
|
text: termsError.message,
|
|
button1Text: $L("OK")
|
|
}));
|
|
}
|
|
}, [termsError, dispatch]);
|
|
|
|
// 약관 팝업 동의여부에 따른 이벤트 핸들러
|
|
const handleTermsAgree = useCallback(() => {
|
|
if (!currentTerms) {
|
|
return;
|
|
}
|
|
const termType = currentTerms.trmsTpCd;
|
|
if (termType === "MST00402") {
|
|
updateStateAsync({ termsChecked: true });
|
|
} else if (termType === "MST00401") {
|
|
updateStateAsync({ privacyChecked: true });
|
|
} else if (termType === "MST00405") {
|
|
// Optional Terms
|
|
updateStateAsync({ optionalChecked: true });
|
|
}
|
|
// 팝업 닫기
|
|
dispatch(setHidePopup());
|
|
}, [currentTerms, dispatch, updateStateAsync]);
|
|
|
|
const handleTermsClick = useCallback(
|
|
(trmsTpCdList) => {
|
|
if (introTermsData) {
|
|
const selectedTerms = introTermsData.find(
|
|
(term) => term.trmsTpCd === trmsTpCdList,
|
|
);
|
|
|
|
setCurrentTerms(selectedTerms);
|
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.termsPopup));
|
|
|
|
const logTpNo =
|
|
trmsTpCdList === "MST00402"
|
|
? Config.LOG_TP_NO.TERMS.TEARMS_CONDITIONS
|
|
: Config.LOG_TP_NO.TERMS.PRIVACY_POLICY;
|
|
dispatch(sendLogTerms({ logTpNo }));
|
|
}
|
|
},
|
|
[introTermsData, dispatch],
|
|
);
|
|
|
|
const handleOptionalTermsClick = useCallback(
|
|
(trmsTpCdList) => {
|
|
if (optionalTermsData) {
|
|
const selectedTerms = optionalTermsData.find(
|
|
(term) => term.trmsTpCd === trmsTpCdList,
|
|
);
|
|
|
|
setCurrentTerms(selectedTerms);
|
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.termsPopup));
|
|
|
|
// const logTpNo =
|
|
// trmsTpCdList === "MST00402"
|
|
// ? Config.LOG_TP_NO.TERMS.TEARMS_CONDITIONS
|
|
// : Config.LOG_TP_NO.TERMS.PRIVACY_POLICY;
|
|
// dispatch(sendLogTerms({ logTpNo }));
|
|
}
|
|
},
|
|
[optionalTermsData, dispatch],
|
|
);
|
|
|
|
const onClose = useCallback(() => {
|
|
dispatch(setHidePopup());
|
|
}, [dispatch]);
|
|
|
|
const handleAgree = useCallback(() => {
|
|
console.log("[IntroPanel] handleAgree isProcessing=", isProcessing);
|
|
if (isProcessing){
|
|
return;
|
|
}
|
|
|
|
// 필수 약관이 체크되어 있는지 확인
|
|
// if (!termsChecked || !privacyChecked) {
|
|
// // 필수 약관이 체크되지 않았을 때 알림
|
|
// // window.alert($L("Please agree to Terms & Conditions and Privacy Policy."));
|
|
// dispatch(setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
|
// title: $L("Required Terms"),
|
|
// text: $L("Please agree to Terms & Conditions and Privacy Policy."),
|
|
// button1Text: $L("OK")
|
|
// }));
|
|
// return;
|
|
// }
|
|
|
|
setIsProcessing(true);
|
|
|
|
// 안전장치: 30초 후 자동으로 isProcessing 해제
|
|
processingTimeoutRef.current = setTimeout(() => {
|
|
console.warn("[IntroPanel] handleAgree 타임아웃 - isProcessing 강제 해제");
|
|
setIsProcessing(false);
|
|
}, 30000);
|
|
|
|
// 약관 동의 처리 시작 시 로딩 상태로 설정
|
|
dispatch({ type: types.GET_TERMS_AGREE_YN_START });
|
|
|
|
// Redux에서 가져온 termsIdMap을 사용하여 동적으로 약관 ID 매핑
|
|
const agreeTerms = [];
|
|
|
|
if (termsChecked && termsIdMap["MST00402"]) {
|
|
agreeTerms.push(termsIdMap["MST00402"]); // 이용약관
|
|
}
|
|
if (privacyChecked && termsIdMap["MST00401"]) {
|
|
agreeTerms.push(termsIdMap["MST00401"]); // 개인정보처리방침
|
|
}
|
|
if (optionalChecked && termsIdMap["MST00405"]) {
|
|
agreeTerms.push(termsIdMap["MST00405"]); // 선택약관
|
|
}
|
|
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.log("[IntroPanel] 현재 termsIdMap:", termsIdMap);
|
|
console.log("[IntroPanel] 최종 전송될 agreeTerms:", agreeTerms);
|
|
}
|
|
|
|
dispatch(
|
|
registerDevice(
|
|
{ agreeTerms: agreeTerms },
|
|
(newRegDeviceData) => {
|
|
if (newRegDeviceData && newRegDeviceData.retCode === 0) {
|
|
dispatch(
|
|
getWelcomeEventInfo((eventInfos) => {
|
|
if (
|
|
eventInfos &&
|
|
Object.keys(eventInfos.data).length > 0 &&
|
|
webOSVersion
|
|
) {
|
|
let displayWelcomeEventPanel = false;
|
|
|
|
if (
|
|
eventInfos.data?.welcomeEventFlag === "Y" ||
|
|
(eventInfos.data?.welcomeBillCpnEventFlag === "Y" &&
|
|
Number(webOSVersion) >= 6)
|
|
) {
|
|
displayWelcomeEventPanel = true;
|
|
}
|
|
|
|
dispatch(
|
|
sendLogTerms({ logTpNo: Config.LOG_TP_NO.TERMS.AGREE }),
|
|
);
|
|
|
|
if (displayWelcomeEventPanel) {
|
|
dispatch(
|
|
pushPanel({
|
|
name: panel_names.WELCOME_EVENT_PANEL,
|
|
panelInfo: { eventInfos: eventInfos.data },
|
|
}),
|
|
);
|
|
}
|
|
}
|
|
dispatch(popPanel(panel_names.INTRO_PANEL));
|
|
setIsProcessing(false);
|
|
clearTimeout(processingTimeoutRef.current); // 타임아웃 정리
|
|
}),
|
|
);
|
|
} else {
|
|
dispatch(
|
|
setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
|
title: $L("Error"),
|
|
text: $L("Device registration failed. Please try again."),
|
|
button1Text: $L("OK"),
|
|
}),
|
|
);
|
|
setIsProcessing(false);
|
|
clearTimeout(processingTimeoutRef.current); // 타임아웃 정리
|
|
}
|
|
},
|
|
() => {
|
|
dispatch(
|
|
setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
|
title: $L("Error"),
|
|
text: $L("Device registration failed. Please try again."),
|
|
button1Text: $L("OK"),
|
|
}),
|
|
);
|
|
setIsProcessing(false);
|
|
clearTimeout(processingTimeoutRef.current); // 타임아웃 정리
|
|
},
|
|
),
|
|
);
|
|
}, [
|
|
termsChecked,
|
|
privacyChecked,
|
|
optionalChecked,
|
|
dispatch,
|
|
isProcessing,
|
|
webOSVersion,
|
|
termsIdMap,
|
|
]);
|
|
|
|
// 실패 감지를 위한 useEffect 추가
|
|
useEffect(() => {
|
|
// isProcessing이 true일 때만 실패 체크 (= handleAgree 클릭 후에만)
|
|
if (isProcessing && regDeviceData && regDeviceData.retCode !== 0) {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.error(
|
|
`[IntroPanel] registerDevice 실패: isProcessing=${isProcessing}, retCode=${regDeviceData.retCode}`,
|
|
regDeviceData,
|
|
);
|
|
}
|
|
dispatch(
|
|
setShowPopup(Config.ACTIVE_POPUP.alertPopup, {
|
|
title: $L("Error"),
|
|
text: $L("Device registration failed. Please try again."),
|
|
button1Text: $L("OK"),
|
|
}),
|
|
);
|
|
setIsProcessing(false);
|
|
clearTimeout(processingTimeoutRef.current); // 타임아웃 정리
|
|
}
|
|
}, [regDeviceData, dispatch, isProcessing]); // isProcessing 의존성 추가
|
|
|
|
// 컴포넌트 언마운트 시 타임아웃 정리
|
|
useEffect(() => {
|
|
return () => {
|
|
if (processingTimeoutRef.current) {
|
|
clearTimeout(processingTimeoutRef.current);
|
|
}
|
|
};
|
|
}, []);
|
|
|
|
const handleDisagree = useCallback(() => {
|
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.exitPopup));
|
|
dispatch(sendLogTerms({ logTpNo: Config.LOG_TP_NO.TERMS.DO_NOT_AGREE }));
|
|
}, [dispatch]);
|
|
|
|
const onExit = useCallback(() => {
|
|
dispatch(setHidePopup());
|
|
setShowExitMessagePopup(true);
|
|
dispatch(setExitApp());
|
|
dispatch(
|
|
sendLogTotalRecommend({
|
|
contextName: Config.LOG_CONTEXT_NAME.SHOPTIME,
|
|
messageId: Config.LOG_MESSAGE_ID.VIEW_CHANGE,
|
|
visible: false,
|
|
}),
|
|
);
|
|
}, [dispatch]);
|
|
|
|
const onCancel = useCallback(() => {
|
|
if (activePopup === null) {
|
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.exitPopup));
|
|
}
|
|
}, [dispatch, activePopup]);
|
|
|
|
const handleFocus = useCallback(
|
|
(item) => {
|
|
setFocusAsync(item);
|
|
},
|
|
[setFocusAsync]
|
|
);
|
|
|
|
const handleBlur = useCallback(() => {
|
|
clearFocusAsync(0);
|
|
}, [clearFocusAsync]);
|
|
|
|
// 체크박스 핸들러들
|
|
const handleTermsToggle = useCallback(
|
|
async ({ selected }) => {
|
|
try {
|
|
const newState = await updateStateAsync({ termsChecked: selected });
|
|
if (newState.termsChecked && newState.privacyChecked && newState.optionalChecked) {
|
|
setTimeout(() => Spotlight.focus("agreeButton"), 100);
|
|
}
|
|
} catch (error) {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.error("Toggle failed:", error);
|
|
}
|
|
}
|
|
},
|
|
[updateStateAsync]
|
|
);
|
|
|
|
const handlePrivacyToggle = useCallback(
|
|
async ({ selected }) => {
|
|
try {
|
|
const newState = await updateStateAsync({ privacyChecked: selected });
|
|
if (newState.termsChecked && newState.privacyChecked && newState.optionalChecked) {
|
|
setTimeout(() => Spotlight.focus("agreeButton"), 100);
|
|
}
|
|
} catch (error) {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.error("Toggle failed:", error);
|
|
}
|
|
}
|
|
},
|
|
[updateStateAsync]
|
|
);
|
|
|
|
const handleOptionalToggle = useCallback(
|
|
async ({ selected }) => {
|
|
try {
|
|
const newState = await updateStateAsync({ optionalChecked: selected });
|
|
if (newState.termsChecked && newState.privacyChecked && newState.optionalChecked) {
|
|
setTimeout(() => Spotlight.focus("agreeButton"), 100);
|
|
}
|
|
} catch (error) {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.error("Toggle failed:", error);
|
|
}
|
|
}
|
|
},
|
|
[updateStateAsync]
|
|
);
|
|
|
|
const handleSelectAllToggle = useCallback(
|
|
async ({ selected }) => {
|
|
try {
|
|
const newState = await updateStateAsync({ selectAllChecked: selected });
|
|
if (newState.selectAllChecked) {
|
|
setTimeout(() => Spotlight.focus("agreeButton"), 100);
|
|
}
|
|
} catch (error) {
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.error("Toggle failed:", error);
|
|
}
|
|
}
|
|
},
|
|
[updateStateAsync]
|
|
);
|
|
|
|
const handleTermsClickMST00402 = useCallback(
|
|
() => handleTermsClick("MST00402"),
|
|
[handleTermsClick],
|
|
);
|
|
const handleTermsClickMST00401 = useCallback(
|
|
() => handleTermsClick("MST00401"),
|
|
[handleTermsClick],
|
|
);
|
|
const handleOptionalTermsClickMST00405 = useCallback(
|
|
() => handleOptionalTermsClick("MST00405"),
|
|
[handleOptionalTermsClick],
|
|
);
|
|
|
|
const handleFocusTermsCheckbox = useCallback(
|
|
() => handleFocus("termsCheckbox"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusTermsButton = useCallback(
|
|
() => handleFocus("termsButton"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusPrivacyCheckbox = useCallback(
|
|
() => handleFocus("privacyCheckbox"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusPrivacyButton = useCallback(
|
|
() => handleFocus("privacyButton"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusOptionalCheckbox = useCallback(
|
|
() => handleFocus("optionalCheckbox"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusOptionalButton = useCallback(
|
|
() => handleFocus("optionalButton"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusSelectAllCheckbox = useCallback(
|
|
() => handleFocus("selectAllCheckbox"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusAgreeButton = useCallback(
|
|
() => handleFocus("agreeButton"),
|
|
[handleFocus],
|
|
);
|
|
const handleFocusDisagreeButton = useCallback(
|
|
() => handleFocus("disagreeButton"),
|
|
[handleFocus],
|
|
);
|
|
|
|
const rightPanelContent = useRightPanelContent(
|
|
focusedItem,
|
|
termsChecked,
|
|
privacyChecked,
|
|
shouldShowBenefitsView
|
|
);
|
|
|
|
useEffect(() => {
|
|
Spotlight.focus();
|
|
}, [popupVisible]);
|
|
|
|
// useEffect(() => {
|
|
// if (regDeviceInfoData && regDeviceInfoData.retCode === 0) {
|
|
// dispatch(setHidePopup());
|
|
// dispatch(popPanel(panel_names.INTRO_PANEL));
|
|
// }
|
|
// }, [dispatch, regDeviceInfoData]);
|
|
|
|
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.",
|
|
);
|
|
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 (
|
|
<Region title={title + description}>
|
|
<TPanel
|
|
className={css.panel}
|
|
isTabActivated={false}
|
|
handleCancel={onCancel}
|
|
spotlightId={spotlightId}
|
|
>
|
|
<Container {...rest} className={css.introLayout}>
|
|
{/* 첫 번째 영역: 헤더 섹션 */}
|
|
<div className={css.headerSection}>
|
|
<div className={css.titleContainer}>
|
|
<div className={css.welcomeText}>{$L("Welcome to")}</div>
|
|
<div className={css.brandContainer}>
|
|
<span className={css.shopText}>{$L("Sh")}</span>
|
|
<span className={css.oText}>{$L("o")}</span>
|
|
<span className={css.timeText}>{$L("pTime !")}</span>
|
|
</div>
|
|
</div>
|
|
<div className={css.descriptionContainer}>
|
|
<div className={css.descriptionText}>{description}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 두 번째 영역: 약관 섹션 */}
|
|
<div className={css.termsSection}>
|
|
<div className={css.termsLeftPanel}>
|
|
{/* Terms & Conditions */}
|
|
<div className={css.termsItem}>
|
|
<TCheckBoxSquare
|
|
className={css.customeCheckbox}
|
|
selected={termsChecked}
|
|
onToggle={handleTermsToggle}
|
|
onFocus={handleFocusTermsCheckbox}
|
|
onBlur={handleBlur}
|
|
spotlightId="termsCheckbox"
|
|
ariaLabel={$L("Terms & Conditions checkbox")}
|
|
/>
|
|
<TButton
|
|
className={css.termsButton}
|
|
onClick={handleTermsClickMST00402}
|
|
onFocus={handleFocusTermsButton}
|
|
onBlur={handleBlur}
|
|
spotlightId="termsButton"
|
|
type={TYPES.terms}
|
|
ariaLabel={$L("View Terms & Conditions")}
|
|
>
|
|
<span className={`${css.termsText} ${css.required}`}>
|
|
{$L("Terms & Conditions")}
|
|
</span>
|
|
</TButton>
|
|
</div>
|
|
|
|
{/* Privacy Policy */}
|
|
<div className={css.termsItem}>
|
|
<TCheckBoxSquare
|
|
className={css.customeCheckbox}
|
|
selected={privacyChecked}
|
|
onToggle={handlePrivacyToggle}
|
|
onFocus={handleFocusPrivacyCheckbox}
|
|
onBlur={handleBlur}
|
|
spotlightId="privacyCheckbox"
|
|
ariaLabel={$L("Privacy Policy checkbox")}
|
|
/>
|
|
<TButton
|
|
className={css.termsButton}
|
|
onClick={handleTermsClickMST00401}
|
|
onFocus={handleFocusPrivacyButton}
|
|
onBlur={handleBlur}
|
|
spotlightId="privacyButton"
|
|
type={TYPES.terms}
|
|
ariaLabel={$L("View Privacy Policy")}
|
|
>
|
|
<span className={`${css.termsText} ${css.required}`}>
|
|
{$L("Privacy Policy")}
|
|
</span>
|
|
</TButton>
|
|
</div>
|
|
|
|
{/* Optional Terms */}
|
|
<div className={css.termsItem}>
|
|
<TCheckBoxSquare
|
|
className={css.customeCheckbox}
|
|
selected={optionalChecked}
|
|
onToggle={handleOptionalToggle}
|
|
onFocus={handleFocusOptionalCheckbox}
|
|
onBlur={handleBlur}
|
|
spotlightId="optionalCheckbox"
|
|
ariaLabel={$L("Optional Terms checkbox")}
|
|
/>
|
|
<TButton
|
|
className={css.termsButton}
|
|
onClick={handleOptionalTermsClickMST00405}
|
|
onFocus={handleFocusOptionalButton}
|
|
onBlur={handleBlur}
|
|
spotlightId="optionalButton"
|
|
type={TYPES.terms}
|
|
ariaLabel={$L("View Optional Terms")}
|
|
>
|
|
<span className={css.termsText}>{$L("Optional Terms")}</span>
|
|
</TButton>
|
|
</div>
|
|
</div>
|
|
<div className={css.termsRightPanel}>{rightPanelContent}</div>
|
|
</div>
|
|
|
|
{/* 세 번째 영역: Select All */}
|
|
<div className={css.selectAllSection}>
|
|
<TCheckBoxSquare
|
|
className={css.selectAllCheckbox}
|
|
selected={selectAllChecked}
|
|
onToggle={handleSelectAllToggle}
|
|
onFocus={handleFocusSelectAllCheckbox}
|
|
onBlur={handleBlur}
|
|
spotlightId="selectAllCheckbox"
|
|
ariaLabel={$L("Select All checkbox")}
|
|
/>
|
|
<span className={css.selectAllText}>{$L("Select All")}</span>
|
|
</div>
|
|
|
|
{/* 네 번째 영역: 버튼 섹션 */}
|
|
<div className={css.buttonSection}>
|
|
<TButton
|
|
className={css.agreeButton}
|
|
onClick={handleAgree}
|
|
onFocus={handleFocusAgreeButton}
|
|
onBlur={handleBlur}
|
|
spotlightId="agreeButton"
|
|
type={TYPES.agree}
|
|
ariaLabel={$L("Agree to terms")}
|
|
disabled={!termsChecked || !privacyChecked}
|
|
spotlightDisabled={!termsChecked || !privacyChecked}
|
|
>
|
|
{$L("Agree")}
|
|
</TButton>
|
|
<TButton
|
|
className={css.disagreeButton}
|
|
onClick={handleDisagree}
|
|
onFocus={handleFocusDisagreeButton}
|
|
onBlur={handleBlur}
|
|
spotlightId="disagreeButton"
|
|
type={TYPES.agree}
|
|
ariaLabel={$L("Do not agree to terms")}
|
|
>
|
|
{$L("Do Not Agree")}
|
|
</TButton>
|
|
</div>
|
|
</Container>
|
|
</TPanel>
|
|
|
|
{/* 약관 보기 팝업 */}
|
|
{activePopup === Config.ACTIVE_POPUP.termsPopup && (
|
|
<>
|
|
{/*
|
|
<TPopUp
|
|
kind="introTermsPopup"
|
|
contentType={CONTENT_TYPES.TERMS}
|
|
open={popupVisible}
|
|
onClose={onClose}
|
|
onTermsAgree={handleTermsAgree}
|
|
termsData={currentTerms}
|
|
hasButton
|
|
button1Text={$L("Agree")}
|
|
button2Text={$L("Close")}
|
|
spotlightId="tPopupBtn1"
|
|
/>
|
|
*/}
|
|
|
|
{/* TermsPopup 호출은 완전히 삭제 */}
|
|
|
|
{/* TNewPopUp을 사용한 새로운 팝업 구현 */}
|
|
<TNewPopUp
|
|
open={popupVisible}
|
|
kind="figmaTermsPopup"
|
|
title={getTermsPopupTitle(currentTerms)}
|
|
text={currentTerms?.trmsCntt || ""}
|
|
onClose={onClose} // Close 버튼 핸들러 연결
|
|
/>
|
|
</>
|
|
)}
|
|
|
|
{/* DO NOT AGREE */}
|
|
{activePopup === Config.ACTIVE_POPUP.exitPopup && (
|
|
<TPopUp
|
|
kind="exitPopup"
|
|
open={popupVisible}
|
|
onExit={onExit}
|
|
onClose={onClose}
|
|
hasButton
|
|
button1Text={$L("Exit")}
|
|
button2Text={$L("Cancel")}
|
|
hasText
|
|
title={$L("Exit Shop Time")}
|
|
text={$L("Are you sure you want to exit Shop Time?")}
|
|
/>
|
|
)}
|
|
|
|
{/* ALERT POPUP (필수 약관 알림) */}
|
|
{activePopup === Config.ACTIVE_POPUP.alertPopup && (
|
|
<TPopUp
|
|
kind="textPopup"
|
|
open={popupVisible}
|
|
onClose={onClose}
|
|
hasButton
|
|
button1Text={popupState.button1Text || $L("OK")}
|
|
hasText
|
|
title={popupState.title || ""}
|
|
text={popupState.text || ""}
|
|
/>
|
|
)}
|
|
|
|
{/* Final Exit Message Popup */}
|
|
{showExitMessagePopup && (
|
|
<TPopUp
|
|
kind="textPopup"
|
|
open={showExitMessagePopup}
|
|
hasText
|
|
title={$L("Exit Shop Time")}
|
|
text={$L(
|
|
"Thank you for using the Shop Time, and we hope to see you again. The app will close in 3 seconds.",
|
|
)}
|
|
/>
|
|
)}
|
|
</Region>
|
|
);
|
|
}
|