(() => { const { pageHelper, EventManager, utils: { changeProfileFormVerifyMap, handleFocusEvent, isSignedIn }, constants, } = ShopbySkin; const termsInformationModule = document.querySelector('terms-information'); if (isSignedIn()) { if (!document.referrer || location.href === document.referrer) { history.back(); return; } location.href = document.referrer; } const signUpFormHelper = pageHelper.signUpFormHelper(); const containerEl = document.querySelector(`[shopby-helper-key="sign-up-form"]`); const profileExtraInformationEl = document.querySelector('profile-extra-information'); signUpFormHelper.initialize({ helperKey: 'sign-up-form', }); const extractTermsAgreements = (termsInformation) => { // 광고성 수신 동의 항목은 subTerms 내부에 있는 필드를 사용하기 때문에 joinTermsAgreements 필드에 사용할 동의 항목 리스트에서는 제거 const filteredMarketingTerms = termsInformation?.marketingTerms?.filter(({ termsType }) => termsType !== constants.MARKETING_RECEIVE) || []; return [...(termsInformation?.terms || []), ...filteredMarketingTerms]; }; const flattenRequest = (helper) => { const { profileBasicInformation, profileNicknameInformation, profileEmailInformation, profileSmsInformation, profileCertification, profileOptionalInformation, termsInformation, profileExtraInformation, } = helper.getState(); const { directMailAgreed, smsAgreed } = ( termsInformation.marketingTerms.find(({ termsType }) => termsType === constants.MARKETING_RECEIVE)?.subTerms || [] ).reduce( (acc, term) => { acc[term.id] = { value: term.checked ?? false }; return acc; }, { directMailAgreed: {}, smsAgreed: {} } ); const joinTermsAgreements = extractTermsAgreements(termsInformation); return { ...profileBasicInformation, ...profileEmailInformation, ...profileSmsInformation, ...profileCertification, ...profileOptionalInformation, extraInfo: profileExtraInformation?.extraInfoContents, nickname: profileNicknameInformation?.nickname, joinTermsAgreements, customTerms: termsInformation?.customTerms, directMailAgreed, smsAgreed, }; }; const checkInvalidProfileForm = (request) => { // eslint-disable-next-line complexity const errors = Object.keys(changeProfileFormVerifyMap)?.map((key) => { const value = request?.[key]?.value ?? ''; switch (key) { case 'memberId': return { ...changeProfileFormVerifyMap?.[key]({ value, isDuplicated: request?.memberId?.isDuplicate, isDormantMemberId: !!request?.isRecentlyExitedMember, }), field: key, }; case 'passwordConfirm': return { ...changeProfileFormVerifyMap?.[key]({ value, comparisonValue: request?.password?.value }), field: key, }; case 'memberName': return { ...changeProfileFormVerifyMap?.[key]({ value, isRequired: request?.memberName?.isRequired }), field: key, }; case 'nickname': return { ...changeProfileFormVerifyMap?.[key]({ value, isDuplicated: request?.nickname?.isDuplicate, isRequired: request?.nickname?.isRequired, }), field: key, }; case 'email': return { ...changeProfileFormVerifyMap?.[key]({ value, isDuplicated: request?.email?.isDuplicate, isRequired: request?.email?.isRequired, }), field: key, }; case 'mobileNo': case 'telephoneNo': return { ...changeProfileFormVerifyMap?.[key]({ value, isRequired: request?.[key]?.isRequired }), field: key, }; case 'detailAddress': return { ...changeProfileFormVerifyMap?.[key]({ value, zipCode: request?.zipCd, isRequired: request?.detailAddress?.isRequired, }), field: key, }; case 'birthday': case 'sex': return { ...changeProfileFormVerifyMap?.[key]({ value, isRequired: request?.[key]?.isRequired }), field: key, }; case 'extraInfo': return { ...changeProfileFormVerifyMap?.[key](request.extraInfo), field: key }; case 'joinTermsAgreements': return { ...changeProfileFormVerifyMap?.[key](request.joinTermsAgreements), field: key }; case 'customTerms': return { ...changeProfileFormVerifyMap?.[key](request.customTerms), field: key }; default: return { ...changeProfileFormVerifyMap?.[key]({ value, isRequired: request?.[key]?.isRequired }), field: key, }; } }); return errors.filter((error) => !error.isValid); }; // eslint-disable-next-line complexity const checkCertificatedValidation = (request) => { const invalidEmail = request?.emailCertificationStatus === 'INITIAL'; const invalidSmsInternalCertification = request?.smsCertificationStatus === 'INITIAL'; const invalidSmsExternalAuthentication = request?.smsCertificationStatus === 'SMS_AUTHENTICATION' && !request?.ci; if (invalidEmail || invalidSmsInternalCertification || invalidSmsExternalAuthentication) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `${invalidEmail ? '이메일 인증을 진행해 주세요.' : '휴대폰 인증을 진행해 주세요.'}`, onClose: () => { handleFocusEvent({ containerEl, fields: invalidEmail ? 'email' : 'mobileNo' }); }, }); return false; } const message = request.certificatedNumber?.length ? '인증을 진행해주세요.' : '인증번호를 입력해주세요.'; if (request.certificated && (!request.certificated.value || !request.certificated.isValid)) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `${request.certificated.message ?? message}`, onClose: () => { handleFocusEvent({ containerEl, fields: 'certificatedNumber' }); }, }); return false; } return true; }; /* 마케팅 약관 체크 이벤트 핸들러 */ /** * 하위 약관 체크 처리 (이메일/SMS 수신 동의 시) * - 하위 약관을 체크하면 해당 부모 약관과 다른 모든 마케팅 약관도 체크 */ const handleCheckSubTerm = (marketingTerms, parentTermType, targetId, checked) => marketingTerms.map((term) => { const isParentTerm = term.termsType === parentTermType; if (isParentTerm) { return { ...term, checked, subTerms: term.subTerms?.map((subTerm) => (subTerm.id === targetId ? { ...subTerm, checked } : subTerm)), }; } // 하위 약관 체크 시 모든 마케팅 약관 체크 return { ...term, checked }; }); /** * 하위 약관 체크 해제 처리 * - 이메일 수신 동의(directMailAgreed) 해제: 부모 약관만 해제 * - 기타 약관 해제 + 다른 하위 약관이 모두 체크된 경우: 해당 약관만 해제 * - 기타 약관 해제 + 다른 하위 약관이 체크 안된 경우: 모든 마케팅 약관 해제 */ const handleUncheckSubTerm = (marketingTerms, parentTermType, targetId, checked) => { const parentTerm = marketingTerms.find(({ termsType }) => termsType === parentTermType); const subTerms = parentTerm?.subTerms; if (!subTerms) { return marketingTerms; } // 다른 하위 약관들이 모두 체크되어 있는지 확인 const otherSubTerms = subTerms.filter(({ id }) => id !== targetId); const isOtherSubTermsAllChecked = otherSubTerms.length > 0 ? otherSubTerms.every((subTerm) => subTerm.checked) : false; const nextSubTerms = subTerms.map((subTerm) => (subTerm.id === targetId ? { ...subTerm, checked } : subTerm)); return marketingTerms.map((term) => { const isParentTerm = term.termsType === parentTermType; // 다른 하위 약관이 모두 체크된 경우: 해당 약관만 해제 if (isOtherSubTermsAllChecked) { return isParentTerm ? { ...term, subTerms: nextSubTerms } : term; } // 이메일 수신 동의 해제: 부모 약관만 해제 if (targetId === 'directMailAgreed') { return isParentTerm ? { ...term, checked, subTerms: nextSubTerms } : term; } // 기타 약관 해제: 모든 마케팅 약관 해제 if (isParentTerm) { return { ...term, checked, subTerms: nextSubTerms }; } return { ...term, checked }; }); }; const CLICK_EVENT_HANDLER_MAP = { // eslint-disable-next-line complexity EMAIL_CERTIFICATION: async (helper) => { const { profileEmailInformation } = helper.getState(); const isInvalidEmail = profileEmailInformation?.email.value === '@' || !profileEmailInformation?.email.isValid; if (isInvalidEmail) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `${profileEmailInformation?.email.message ?? '이메일을 입력해주세요.'}`, }); return; } if (profileEmailInformation?.emailCertificationStatus === 'INITIAL') { await helper.sendCertificationCode(profileEmailInformation.email.value, 'EMAIL'); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '인증번호가 발송되었습니다.', }); } else { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '인증번호를 재발송하시겠습니까?', onConfirm: async () => { await helper.sendCertificationCode(profileEmailInformation.email.value, 'EMAIL'); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '인증번호가 발송되었습니다.', }); }, }); } }, // eslint-disable-next-line complexity SMS_CERTIFICATION: async (helper) => { const { profileSmsInformation } = helper.getState(); const isInvalidMobileNo = !profileSmsInformation?.mobileNo.value || !profileSmsInformation?.mobileNo.isValid; if (isInvalidMobileNo) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `${profileSmsInformation?.mobileNo.message ?? '휴대폰 번호를 입력해주세요.'}`, }); return; } if (profileSmsInformation?.smsCertificationStatus === 'INITIAL') { await helper.sendCertificationCode(profileSmsInformation.mobileNo.value, 'SMS'); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '인증번호가 발송되었습니다.', }); } else { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '인증번호를 재발송하시겠습니까?', onConfirm: async () => { await helper.sendCertificationCode(profileSmsInformation.mobileNo.value, 'SMS'); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '인증번호가 발송되었습니다.', }); }, }); } }, AUTHENTICATION_BY_PHONE: () => { EventManager.fire('OPEN_LAYER_MODAL', { name: 'kcp-sms-authentication', data: { type: 'JOIN_TIME' }, onClose: ({ reason, state }) => { if (reason === 'DID_SUBMIT') { ShopbySkin.EventManager.fire('SUCCESS_AUTHENTICATION_SMS', state); } }, }); }, SEARCH_ZIP_CODE: () => { EventManager.fire('OPEN_LAYER_MODAL', { isFull: false, modalAddClass: 'search-zip-code', name: 'page-zip-code', onClose: ({ reason, state }) => { if (reason === 'DID_SUBMIT') { ShopbySkin.EventManager.fire('SELECT_ZIP_CODE', { moduleKey: 'profile-optional-information', state, }); } }, }); }, SHOW_TERM_DETAIL: ({ elTarget, helper }) => { const { termsInformation } = helper.getState(); if (!termsInformation) { return; } const mergedTerms = [ ...termsInformation.terms, ...termsInformation.customTerms, ...termsInformation.marketingTerms, ]; const selectedTerm = mergedTerms.find((term) => elTarget.getAttribute('shopby-term-id') === term.id.toString()); EventManager.fire('OPEN_LAYER_MODAL', { name: 'term-detail', data: selectedTerm, }); }, // eslint-disable-next-line complexity SUBMIT: async (helper) => { await profileExtraInformationEl?.refetchConfigMemberExtraInfo(); const flattedRequest = flattenRequest(helper); const invalidRequest = checkInvalidProfileForm(flattedRequest); if (invalidRequest?.length) { const [error] = invalidRequest; EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `${error.message}`, onClose: () => { handleFocusEvent({ containerEl, fields: error.field }); EventManager.fire('INVALID_PROFILE_FORM', { data: invalidRequest, }); }, }); return; } if (!checkCertificatedValidation(flattedRequest)) { return; } const { data } = await helper.submit(flattedRequest); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '회원가입이 완료되었습니다.', onClose: () => { if (data.memberStatus === 'PENDING') { location.replace('/pages/sign-up/sign-up-pending.html'); } else { location.replace('/pages/sign-up/sign-up-complete.html'); } }, }); }, HANDLE_DELETE_IMAGE_BTN_CLICK: (_, event) => { event.preventDefault(); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '첨부파일을 삭제하시겠습니까?', onConfirm: () => { const extraInfoNo = event.target.closest('[shopby-extra-info-no]').getAttribute('shopby-extra-info-no'); profileExtraInformationEl.deleteImage(extraInfoNo); }, }); }, CHECK_MARKETING_TERMS: (helper, event) => { const { termsInformation } = helper.getState(); const nextMarketingTerms = termsInformationModule.setMarketingTermsAllCheck( termsInformation.marketingTerms, event.target.checked ); const isAllCheckedTerms = termsInformationModule.getAllCheckedTerms(); const isAllChecked = isAllCheckedTerms && nextMarketingTerms.every((term) => term.checked); termsInformationModule.store.setState({ marketingTerms: nextMarketingTerms, isAllChecked, }); }, CHECK_MARKETING_SUB_TERMS: (helper, event) => { const { termsInformation } = helper.getState(); const { marketingTerms } = termsInformation; const { target } = event; const { checked, value } = target; const parentTermType = target.getAttribute('shopby-parent-term-type'); const nextMarketingTerms = checked ? handleCheckSubTerm(marketingTerms, parentTermType, value, checked) : handleUncheckSubTerm(marketingTerms, parentTermType, value, checked); const flattedMarketingTerms = termsInformationModule.flattenMarketingTerms(nextMarketingTerms); const isAllChecked = termsInformationModule.getAllCheckedTerms() && flattedMarketingTerms.every((term) => term.checked); termsInformationModule.store.setState({ marketingTerms: nextMarketingTerms, isAllChecked, }); }, }; const clickEventListener = (event) => { const { target } = event; const action = target.getAttribute('shopby-action'); if (action === 'SHOW_TERM_DETAIL') { CLICK_EVENT_HANDLER_MAP[action]?.({ helper: signUpFormHelper, elTarget: target, }); } else { CLICK_EVENT_HANDLER_MAP[action]?.(signUpFormHelper, event); } }; containerEl.addEventListener('click', clickEventListener); })();