/* * © 2021. NHN Commerce Corp. All rights reserved. * NHN Corp. PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * @author choisohyun * @since 2021.6.30 * */ $(() => { shopby.my.modifyMember = { smsTimer: null, emailTimer: null, mallJoinConfig: shopby.cache.getMall().mallJoinConfig, agreements: null, captcha: shopby.helper.captcha(), emailCaptcha: shopby.helper.captcha('emailCaptcha'), smsCaptcha: shopby.helper.captcha('smsCaptcha'), async initiate() { shopby.my.menu.init('#myPageLeftMenu'); await this.render(); this.bindEvents(); }, async render() { shopby.my.menu.init('#myPageLeftMenu'); $('#certifyPassword').render(await this.getMemberId()); this.captcha = this.captcha || shopby.helper.captcha(); }, async getMemberId() { const profile = await shopby.api.member.getProfile(); return { memberId: profile.data.memberId }; }, bindEvents() { $('#btnCertifyCancel').on('click', () => history.back()); $('#btnPwCertify').on('click', this.certifyPassword.bind(this)).enterKeyup('#confirmPassword'); }, async certifyPassword() { const $password = $('#confirmPassword'); const password = $password.val().trim(); try { this._validatePassword(password); } catch (error) { shopby.alert({ message: '비밀번호를 정확하게 입력해주세요.' }, () => $password.focus()); return; } const request = { requestBody: { password } }; try { await this.captcha.submitCode(true); await shopby.api.member.postProfileCheckPassword(request); $('.my_page_password').hide(); this.captcha.reset(); } catch (e) { const isInvalidCode = e.code === 'M0306' || e.code === 'CP9001'; if (isInvalidCode) { this.captcha.retry(); this.captcha.errorHandler(e); } throw e; } const userInfo = await shopby.api.member.postProfileNonMasking(request); await this.initiateModifyForm(userInfo.data); }, async initiateModifyForm(userInfo) { const initTimer = authType => new shopby.helper.timer( this._onTimerTicked(authType), this._onTimerEnded(authType), this._onTimeCleared(authType), ); this.smsTimer = initTimer('sms'); this.emailTimer = initTimer('email'); $('#modifyMember').render(await this.getFormData(userInfo)); this.bindFormEvents(); $('#marketingInfoUsageAgreed').prop('checked', new Set(userInfo.agreedTerms).has('MARKETING_INFO_USAGE')); $('#marketingReceiveAgreed').prop('checked', userInfo.directMailAgreed || userInfo.smsAgreed); $('#directMailAgreed').prop('checked', userInfo.directMailAgreed); $('#smsAgreed').prop('checked', userInfo.smsAgreed); if (this.mallJoinConfig.authenticationType === 'AUTHENTICATION_BY_PHONE') { window.shopKcpCallback = async (result, key) => { if (!result) { shopby.alert('본인 인증에 실패하였습니다.'); return; } const { data: checkCI } = await shopby.api.member.getProfileCiExists({ queryString: { ci: result.ci } }); if (checkCI && checkCI.exist) { const messageType = checkCI.status === 'WITHDRAWN' ? 'kcpWithdrawn' : 'kcpExistMember'; shopby.alert(shopby.message[messageType], shopby.goLogin); } else if (!checkCI || !checkCI.exist) { shopby.localStorage.setItemWithExpire(shopby.cache.key.member.kcpAuth, result); this.authKey = key; this.updateKcpInfo(result); } }; } else { shopby.localStorage.removeItem(shopby.cache.key.member.kcpAuth); } }, async getFormData(userInfo) { const { email, birthday, agreedTerms } = userInfo; const { mall, mallJoinConfig, memberJoinConfig } = shopby.cache.getMall(); const [emailId, emailDomain] = email ? email.split('@') : ['', '']; const dayFormatter = type => (birthday ? Number(dayjs(birthday).format(type)) : 0); const joinTermsAgreements = ['USE', 'PI_COLLECTION_AND_USE_REQUIRED'].concat(agreedTerms); const agreements = await shopby.helper.member.getAgreements(null, null, joinTermsAgreements); let usableTerms = {}; const agreementsTerms = agreements.reduce( (acc, { key, ...rest }) => { const marketingTermKeys = new Set(['MARKETING_INFO_USAGE', 'MARKETING_RECEIVE']); if (marketingTermKeys.has(key)) { acc.marketingAgreements.push({ key, ...rest }); } else { acc.agreements.push({ key, ...rest }); } usableTerms[key.toLowerCase()] = { used: rest.used }; return acc; }, { agreements: [], marketingAgreements: [] }, ); this.agreements = agreementsTerms.agreements; this.marketingAgreements = agreementsTerms.marketingAgreements; return { mallJoinConfig, mallName: mall.mallName, memberJoinConfig, agreements: this.agreements, marketingAgreements: this.marketingAgreements, isAllChecked: this.agreements.every(({ checked }) => checked), selectOptions: { yearList: shopby.helper.member.last120YearsAgo, monthList: shopby.helper.member.monthList, dayList: shopby.helper.member.dayList, }, userInfo: { ...userInfo, emailId, emailDomain, year: dayFormatter('YYYY'), month: dayFormatter('M'), day: dayFormatter('D'), }, usableTerms, }; }, bindFormEvents() { // form $('#passwordChange').on('click', this.togglePasswordInput); $('#memberRegisterForm') .on('keyup', 'input', this.changeValidInput.bind(this)) .on('blur', 'input', this.blurValidInput.bind(this)) .on('change', 'select', shopby.helper.member.changeSelectedBirth) .on('click', '#mobileReAuth', shopby.helper.member.openKcpCallback) .on('click', 'button[name="sendAuth"]', this.sendAuthentication.bind(this)) .on('click', 'button[name="confirmAuth"]', this.confirmAuthentication.bind(this)); $('#btnPostcode').on('click', this.findAddress.bind(this)); // terms $('#allAgree').on('change', this.onChangeAllAgreed.bind(this)); $('input:checkbox[name="termItem"]').on('change', this.onChangeTermItem.bind(this)); $('.agreement_detail').on('click', this.onClickAgreementDetail.bind(this)); $('input:checkbox[id="marketingInfoUsageAgreed"]').on('change', this.onChangeMarketingInfoUsageAgreed.bind(this)); $('input:checkbox[id="marketingReceiveAgreed"]').on('change', this.onChangeMarketingReceiveAgreed.bind(this)); $('input:checkbox[id="directMailAgreed"]').on('change', this.onChangeDirectMailAgreed.bind(this)); $('input:checkbox[id="smsAgreed"]').on('change', this.onChangeSmsAgreed.bind(this)); $('#btnCancel').on('click', () => history.back()); $('#btnModify').on('click', this.modifyMember.bind(this)); }, updateKcpInfo({ name, ci, phone, sexCode, birthday }) { const [year, month, day] = dayjs(birthday).format('YYYY-M-D').split('-'); $('#ci').val(ci).prop('disabled', true); $('#memberName').val(name).prop('disabled', true); $('#mobileNo').val(phone).prop('disabled', true); $('select[name="birthYear"]').html(``).prop('disabled', true); $('select[name="birthMonth"]') .html(``) .prop('disabled', true); $('select[name="birthDay"]').html(``).prop('disabled', true); if (sexCode === '01') { $('#sexMan').prop('checked', true); } else if (sexCode === '02') { $('#sexWoman').prop('checked', true); } else { $('#sexNon').prop('checked', true); } $('input[name="sex"]').prop('disabled', true); $('#mobileReAuth').text('재인증'); }, togglePasswordInput() { $('#passwordWrap').show(); }, changeValidInput({ key, target }) { const { pattern } = target.dataset; if (key.includes('Arrow') || !pattern) return; const { value } = target; let validInput = value.replace(shopby.regex[pattern], ''); if (pattern === 'userid') { const count = (value.match(shopby.regex.at) || []).length; validInput = count > 1 ? validInput.substring(0, value.length - 1) : validInput; } $(target).val(validInput); }, async blurValidInput({ target }) { const $target = $(target); const $warnMessage = $target.closest('.member_warning').find('.warning_message'); const { name, value, dataset } = target; const resultMessage = await this._validateForm(name, value, dataset.userInfo || null); shopby.regex.mobileNo.lastIndex = 0; // test 사용시 lastIndex를 기억하기 때문에 초기화 해줘야 이후 실행이 잘 됨. const successValidation = resultMessage.includes('success') || resultMessage === ''; const errorInput = $target.closest('.member_warning').find('input'); if (name.includes('email') && !resultMessage.includes('success')) { $warnMessage.hide(); const id = $('#emailId'); const domain = $('#emailDomain'); if (!id.val() || !shopby.regex.emailId.test(id.val())) { id.focus(); } else if (!domain.val() || !shopby.regex.emailId.test(domain.val())) { domain.focus(); } } if (resultMessage.length > 0) { $warnMessage.text(shopby.message[resultMessage]).show(); } else { $warnMessage.hide(); } $warnMessage.data('usable', successValidation); if ($warnMessage.data('usable') === false) { errorInput.addClass('fail_valid'); } else { errorInput.removeClass('fail_valid'); } }, async sendAuthentication({ target }) { const $target = $(target); const $warnMessage = $target.closest('.member_warning').find('.warning_message'); const authType = $target.data('authType'); const { value, errorMessage, key } = shopby.helper.member.getCurrentAuth(authType); const $invalidInput = $target.parents('.member_warning').find(`input[name=${key}]`); if (value.length === 0 || value === '@') { $warnMessage.text(errorMessage).show(); $invalidInput.addClass('fail_valid'); shopby.alert(errorMessage); return; } const $sendButton = $(`.btn_send_${authType}`); if ($sendButton.text() === '재인증') { $(`.${authType}_box, .auth_${authType}`).find('input').val(''); $(`input[name="${key}"], input[name="auth_${authType}"]`).attr('disabled', false); $sendButton.text('인증번호 발송'); return; } if ($invalidInput.attr('class').includes('fail_valid')) { shopby.alert($warnMessage.text().split('.')[0]); return; } const usable = $warnMessage.data('usable') || value; if (!usable) return; const { data } = await shopby.api.auth.postAuthentications({ requestBody: { memberName: $('input[name="memberName"]').val(), notiAccount: value, type: authType.toUpperCase(), usage: authType === 'sms' ? 'CHANGE_MOBILE_NO' : 'CHANGE_EMAIL', }, }); shopby.alert( `인증번호가 발송되었습니다.
${authType.toUpperCase()}로 발송된 인증번호 입력하여 인증을 완료해 주세요.`, () => { $(`input[name="auth_${authType}"]`).focus(); $target.hide(); }, ); const targetTimer = authType === 'sms' ? this.smsTimer : this.emailTimer; targetTimer.start(data.remainTime); $(`.auth_${authType}`).show(); $(`.auth_${authType} .warning_message`).hide(); }, async confirmAuthentication({ target }) { const authType = $(target).data('authType'); const captcha = this[`${authType}Captcha`]; const certificatedNumber = $(`input[name="auth_${authType}"]`).val(); if (authType === 'email') { this.emailCaptcha = this.emailCaptcha || shopby.helper.captcha('emailCaptcha'); } else if (authType === 'sms') { this.smsCaptcha = this.smsCaptcha || shopby.helper.captcha('smsCaptcha'); } try { const { value } = shopby.helper.member.getCurrentAuth(authType); (await captcha) && captcha.submitCode(true); await shopby.api.auth.getAuthentications({ queryString: { notiAccount: value, type: authType.toUpperCase(), usage: authType === 'sms' ? 'CHANGE_MOBILE_NO' : 'CHANGE_EMAIL', certificatedNumber, }, }); const targetTimer = authType === 'sms' ? this.smsTimer : this.emailTimer; targetTimer.clear(); captcha && captcha.reset(); $(`.btn_send_${authType}`).show(); } catch (e) { console.error(e); if (certificatedNumber.length === 0) { shopby.alert('인증번호를 입력해주세요.'); } else { $(`.auth_${authType} .warning_message`).text('올바른 인증번호가 아닙니다.').show(); if (e.code === 'E0008' || e.code === 'CP9001') { captcha && captcha.retry(); captcha && captcha.errorHandler(e); } } } }, findAddress() { shopby.popup('find-address', null, data => { if (data.state === 'close') return; $('#zipCd').val(data.zipCode); $('#address').val(data.address); $('#jibunAddress').val(data.jibunAddress); shopby.alert('상세주소를 입력해주시기 바랍니다.', () => $('input[name="detailAddress"]').focus()); }); }, onChangeAllAgreed({ target }) { const checked = $(target).prop('checked'); $('input:checkbox[name="termItem"]') .filter((_, selector) => !$(selector).prop('disabled')) .prop('checked', checked); $('input:checkbox[name="termMarketing"]').prop('checked', checked); }, onChangeTermItem() { const checked = this.agreements.length + 1 === $('input[name=termItem]:checked').length; $('#allAgree').prop('checked', checked); }, onClickAgreementDetail({ target }) { const termKey = $(target).data('term-id'); let title = $(`label[for=agreeCheckbox-${termKey}]`).text(); let contents = this.agreements.find(({ key }) => key === termKey)?.contents; if (termKey === 'marketing_info_usage' || termKey === 'marketing_receive') { const term = this.marketingAgreements.find(({ key }) => key === termKey.toUpperCase()); title = term?.label; contents = term?.contents; } shopby.popup('terms', { title, contents }, function (data) { if (data.state === 'ok') { $(`input:checkbox[id=agreeCheckbox-${termKey}]`).prop('checked', true); } }); }, async modifyMember() { const inputWaringMessage = $('.member_warning').find('.warning_message'); const isValid = shopby.helper.member.checkValidInput(inputWaringMessage); const failValidInput = $('.fail_valid').siblings('.warning_message').html(); try { if (!isValid) { shopby.alert(failValidInput); return; } shopby.helper.member.submitValidation(); } catch (error) { shopby.alert({ message: error.message }); return; } await shopby.api.member.putProfile({ requestBody: this._memberInfo }); const updateKcp = shopby.localStorage.getItemWithExpire(shopby.cache.key.member.kcpAuth); if (updateKcp) { await shopby.api.member.postProfileRename({ requestBody: { key: this.authKey } }); } shopby.alert('회원 정보수정되었습니다.', () => location.replace('/pages/my/mypage.html')); }, _validatePassword(password) { if (!password) { throw new Error('비밀번호를 입력해주세요.'); } }, _validateForm(type, value, originValue) { const { member } = shopby.helper; switch (type) { case 'memberId': return member.userIdValidation(value); case 'password': return member.passwordValidation(value); case 'passwordChk': return member.passwordChkValidation(value); case 'memberName': return member.nameValidation(value); case 'nickname': return member.nicknameValidation(value, originValue); case 'email': return member.emailValidation(originValue); case 'mobileNo': case 'telephoneNo': return member.mobileNoValidation(value); default: return ''; } }, get _memberInfo() { const certificated = !!($('#authSMS').val() || $('#authEmail').val() || $('#ci').val()); const joinTermsAgreements = $('input:checkbox[name="termItem"]:checked:not(:disabled)') .map(function () { const termKey = $(this).data('term-id'); if (termKey !== 'JOIN_POSSIBLE_AGE') return termKey; }) .get(); const marketingInfoUsageAgreed = $('input[id="marketingInfoUsageAgreed"]').is(':checked'); // 마케팅 목적 개인정보 수집/이용 동의 if (marketingInfoUsageAgreed) joinTermsAgreements.push('MARKETING_INFO_USAGE'); return { memberId: $('input[name="memberId"]').val(), //영문6자이상 password: $('input[name="password"]').val() || null, //영문+숫자+특수문자 memberName: $('input[name="memberName"]').val(), //이름 nickname: $('input[name="nickname"]').val(), //닉네임 email: shopby.helper.member.emailValue, //이메일 directMailAgreed: $('#directMailAgreed').is(':checked'), //메일 알림 동의 여부 boolean telephoneNo: $('input[name="telephoneNo"]').val(), //전화번호 예.023457890 mobileNo: $('input[name="mobileNo"]').val(), //핸드폰번호 예.01012347890 smsAgreed: $('#smsAgreed').is(':checked'), //sms 알림 동의 여부 boolean pushNotificationAgreed: $('input[name="pushNotificationAgreed"]').is(':checked') || false, //푸시 알림 동의 여부 boolean zipCd: $('input[name="zipCd"]').val(), //우편번호 address: $('input[name="address"]').val(), //도로명 주소 detailAddress: $('input[name="detailAddress"]').val(), //도로명 상세주소 jibunAddress: $('input[name="jibunAddress"]').val(), //지번 주소 jibunDetailAddress: $('input[name="detailAddress"]').val(), //지번 상세주소 sex: $('input[name="sex"]:checked').val(), //성별 birthday: this._birthday, //생일 예.19981209 countryCd: shopby.cache.getMall().mall.countryCode, //국적 joinTermsAgreements, //약관동의 array recommenderId: $('input[name="recommenderId"]').val(), //추천인 아이디 ci: $('input[name="ci"]').val(), //본인인증 후 가입시 필요한 식별 번호 certificated, //인증확인 여부 boolean }; }, get _birthday() { const selectedYear = $('select[name="birthYear"]').val(); const selectedMonth = $('select[name="birthMonth"]').val(); const selectedDay = $('select[name="birthDay"]').val(); const allSelected = selectedYear !== '0' && selectedMonth !== '0' && selectedDay !== '0'; const unitDigit = num => (Number(num) < 10 ? `0${num}` : `${num}`); return allSelected ? `${selectedYear}${unitDigit(selectedMonth)}${unitDigit(selectedDay)}` : ''; }, _onTimerTicked(authType) { return time => { $(`.auth_${authType} .timer`).html(time); $(`.btn_confirm_${authType}`).css('display', 'inline'); }; }, _onTimerEnded(authType) { return () => { $(`.auth_${authType} .timer`).html('시간초과'); $(`.auth_${authType} .timer`) .closest('div') .find('.warning_message') .text('유효시간이 초과되었습니다. 다시 [인증번호 발송] 클릭하여 발급된 인증번호를 입력해주세요.') .show(); $(`.btn_send_${authType}`).show(); $(`.btn_confirm_${authType}`).css('display', 'none'); }; }, _onTimeCleared(authType) { return () => { if (authType === 'email') { $(`input[name="${authType}"]`).attr('disabled', true); } else if (authType === 'sms') { $(`input[name="mobileNo"]`).attr('disabled', true); } $(`.btn_send_${authType}`).text('재인증'); $(`.auth_${authType} .timer`).html(''); $(`.auth_${authType},.auth_${authType} .warning_message`).hide(); }; }, /* 마케팅 목적 개인정보 수집/이용, 광고성 수신 동의 */ // 동의항목 체크박스 컨트롤 changeAgreementsCheckbox(elementIds, checked) { elementIds.forEach(elementId => { $(`#${elementId}`).prop('checked', checked); }); }, // 마케팅 목적의 개인정보/수집 이용 동의 onChangeMarketingInfoUsageAgreed({ target }) { const targetIds = ['marketingInfoUsageAgreed', 'marketingReceiveAgreed', 'directMailAgreed', 'smsAgreed']; const checked = $(target).is(':checked'); this.changeAgreementsCheckbox(targetIds, checked); }, // 광고성 수신 동의 onChangeMarketingReceiveAgreed({ target }) { const targetIds = ['marketingInfoUsageAgreed', 'marketingReceiveAgreed', 'directMailAgreed', 'smsAgreed']; const checked = $(target).is(':checked'); this.changeAgreementsCheckbox(targetIds, checked); }, // 이메일 수신 동의 onChangeDirectMailAgreed({ target }) { let agreementsElementIds = []; const checked = $(target).is(':checked'); if (checked) { agreementsElementIds = ['marketingInfoUsageAgreed', 'marketingReceiveAgreed']; } else { const isSmsAgreedChecked = $('#smsAgreed').is(':checked'); if (!isSmsAgreedChecked) { // // SMS 수신 동의 미동의 일 경우 광고성 수신 동의 체크 해제 agreementsElementIds = ['marketingReceiveAgreed']; } } this.changeAgreementsCheckbox(agreementsElementIds, checked); }, // SMS 수신 동의 onChangeSmsAgreed({ target }) { const checked = $(target).is(':checked'); const agreementsElementIds = ['marketingInfoUsageAgreed', 'marketingReceiveAgreed']; if (checked) { this.changeAgreementsCheckbox(agreementsElementIds, checked); } else { const isEmailAgreedChecked = $('#directMailAgreed').is(':checked'); // 이메일 수신 동의 미동의 일 경우 전체 체크 해제 if (!isEmailAgreedChecked) { this.changeAgreementsCheckbox(agreementsElementIds, checked); } } }, }; shopby.start.initiate(shopby.my.modifyMember.initiate.bind(shopby.my.modifyMember)); });