(() => { const { pageHelper, EventManager, utils, actions, constants } = ShopbySkin; const { unescapeHTML } = utils; const { NOTICE_MODAL_TYPE, PAGE } = constants; const CONTENT_HEIGHT_THRESHOLD = 500; const productOptionAction = actions.getProductOptionAction(); const extraProductOptionAction = actions.getExtraProductOptionAction(); const productOptionEls = document.querySelectorAll('product-purchase-v2'); const orderSheetAppCardEl = document.querySelector('order-sheet-app-card'); const selectProductOptionEl = document.querySelector('select-product-option'); const selectedOptionsEl = document.querySelector('selected-options'); const extraProductOptionEl = document.querySelector('extra-products'); const extraProductSelectedOptionsEl = document.querySelector('extra-product-selected-options'); let productDetailData = {} EventManager.on('QUERY_PRODUCT_DETAIL', async (product) => { productDetailData = product; await productOptionAction.fetchOptions(product.productNo, { productInfo: product, }); productOptionAction.fetchOptionSelector(); setTimeout(()=>{ document.querySelector('.review-count' ).innerHTML = Number(product?.counter?.reviewCnt || 0).toLocaleString() + '개 리뷰'; document.querySelector('.review-count-star' ).innerHTML = Number(product?.reviewRate || 0).toFixed(1) ; }, 500); }); EventManager.on('PRODUCT_DETAIL_CONTENT_LOADED', () => { const imgs = document.querySelector('product-detail').querySelectorAll('img'); utils.lazyLoad({ imgEls: imgs }); //배송정보 안내문구 const deliveryInfo = document.querySelector('.btn_delivery_info'); const deliveryCon = document.querySelector('.custom_delivery_con'); const deliveryClose = document.querySelector('.custom_delivery_con > .btn_close'); deliveryInfo.addEventListener('click', function () { deliveryCon.classList.toggle('dn'); }); deliveryClose.addEventListener('click', function () { deliveryCon.classList.toggle('dn'); }); }); EventManager.on('QUERY_EXTRA_PRODUCTS_BY_PRODUCT_NO', (product) => { extraProductOptionAction.fetchExtraProductOptions(product.productNo, product); extraProductOptionAction.fetchExtraProductOptionSelector(); }); EventManager.on('PRODUCT_DETAIL_OPTION_IMAGES_LOADED', () => { const imgs = document.querySelector('[slot="optionImages"]')?.querySelectorAll('img'); if (!imgs) { return; } utils.lazyLoad({ imgEls: imgs }); }); // 이미지 로드를 Promise로 변환하는 헬퍼 함수 const waitForImageLoad = (image) => new Promise((resolve) => { // 이미 로드된 이미지는 즉시 resolve if (image.complete && image.naturalHeight !== 0) { resolve(); } else { // 로드되지 않은 이미지만 onload 이벤트 등록 image.onload = () => resolve(); // 로드 실패 시에도 resolve (무한 대기 방지) image.onerror = () => resolve(); } }); // 모든 이미지 로드를 기다리는 함수 const waitForAllImagesLoad = (images) => Promise.allSettled(Array.from(images).map(waitForImageLoad)); // 컨텐츠 사이즈 체크 후 UI 업데이트 const updateContentVisibility = (contentEl) => { if (contentEl.offsetHeight > CONTENT_HEIGHT_THRESHOLD) { const target = document.querySelector('[shopby-element="product-content"]'); target.classList.add('hidden'); const moreBtnTarget = document.querySelector('[shopby-element="TOGGLE_SHOW_MORE"]'); moreBtnTarget.classList.remove('hidden'); } }; EventManager.on('CHECK_PRODUCT_CONTENT_SIZE', () => { // 상품 펼쳐보기 버튼 생성, hidden 처리 const getProductDetailContentElement = () => document.querySelector('[shopby-element="product-content-detail"]'); let isProcessing = false; let observer = null; const checkContentSize = () => { const contentEl = getProductDetailContentElement(); if (!contentEl) return; const imageEls = contentEl.querySelectorAll('img'); waitForAllImagesLoad(imageEls).then(() => { // 처리 완료 후 observer 해제 (중복 실행 방지) if (observer) { observer.disconnect(); } updateContentVisibility(contentEl); observer = null; isProcessing = false; }); }; observer = new ResizeObserver(() => { // 이미 처리 중이면 중복 실행 방지 if (isProcessing) return; isProcessing = true; checkContentSize(); }); const observerTarget = getProductDetailContentElement(); observerTarget && observer.observe(observerTarget); // 상품 펼쳐보기 버튼 생성, hidden 처리 END }); const searchParams = new URLSearchParams(location.search); const productNo = searchParams.get('productNo'); const channelType = searchParams.get('channelType'); const trackingKey = searchParams.get('trackingKey'); const cartAction = actions.getCartAction(); utils.setChannelType(channelType); const { productDetailHelper } = pageHelper; const { initialize, deleteProductInquiryBy, searchReviewsV2 } = productDetailHelper(); initialize({ productNo, channelType, cartAction, productOptionAction, extraProductOptionAction, disableInitFetchProductOptions: true, }); EventManager.on('QUERY_PRODUCT_DETAIL', (data) => { // EventManager.fire('CHANGE_SUB_TITLE', { // subTitle: data?.baseInfo?.productName, // }); // 외부스크립트 등록 기능. 삭제금지 ShopbyExternalScript?.setGlobalObjectSb({ product: { ...data } }); }); const redirectLoginPage = () => { const nextUrl = `${location.origin}${constants.PAGE.SIGN_IN}`; utils.moveTo({ url: `${nextUrl}?from=${encodeURIComponent(location.href)}`, }); }; const getController = (target) => { const controllerId = target.getAttribute('shopby-controller-id') || target.closest('[shopby-controller-id]').getAttribute('shopby-controller-id'); if (!controllerId) { return null; } const { data } = productOptionAction.fetchOptionSelector(controllerId); return data; }; const validationMap = { receiverName: (value) => { if (!value) { return { message: '받는 사람을 입력해주세요', slotName: 'shippingInfo.receiverName', }; } return false; }, receiverAddress: (value) => { if (!value) { return { message: '주소를 입력해주세요.', slotName: 'shippingInfo.receiverAddress', }; } return false; }, receiverDetailAddress: (value) => { if (!value) { return { message: '상세 주소를 입력해주세요.', slotName: 'shippingInfo.receiverDetailAddress', }; } return false; }, receiverContact1: (value) => { const MIN_CONTACT_LENGTH = 10; const slotName = 'shippingInfo.receiverContact1'; if (!value) { return { message: '받는 사람 휴대폰 번호를 입력해주세요.', slotName, }; } if (value.length < MIN_CONTACT_LENGTH) { return { message: '휴대폰번호는 10자~12자 이내로 입력해주세요.', slotName, }; } return false; }, }; const checkValidation = ({ data, fields }) => { let errorInfo = null; for (let i = 0; i < fields.length; i += 1) { const fieldName = fields[i]; if (!validationMap[fieldName]) { continue; } const error = validationMap[fieldName](data[fieldName].trim(), data); if (error) { errorInfo = error; break; } } if (errorInfo?.message) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `${errorInfo.message}`, }); return false; } return true; }; const getExtraProductController = (target) => { const controllerId = target.closest('[shopby-controller-id]')?.getAttribute('shopby-controller-id'); if (!controllerId || !extraProductSelectedOptionsEl) { return null; } const { extraProductsControllers } = extraProductSelectedOptionsEl.store.state; return extraProductsControllers.find((controller) => controller.id === controllerId) || null; }; const isInvalidMinorPurchaseYn = (options) => { const hasMinorPurchaseYnProduct = options.some((option) => option.minorPurchaseYn === 'N'); return hasMinorPurchaseYnProduct && !utils.isAgeVerified(); }; let shopbyCommonData = {}; EventManager.on('PAGE_LOAD_COMPLETED', (commonData) => { shopbyCommonData = commonData; // 외부스크립트 등록 기능. 삭제금지 ShopbyExternalScript?.setPageScriptType('PRODUCT'); //카드사별 무이자 혜택 const clientId = shopbyCommonData?.clientId; if ( clientId ) { const myHeaders = new Headers(); myHeaders.append("accept", "application/json"); myHeaders.append("version", "1.0"); myHeaders.append("clientid", "csG2RJQcc5UDBprxun6j5w=="); myHeaders.append("platform", "PC"); const requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; fetch(`https://shop-api.e-ncp.com/products/extraInfo?productNos=${productNo}`, requestOptions) .then(res => res.json()) // JSON 파싱을 자동으로 수행 .then(data => { const elBenefitInfo = document.querySelector('.product-benefit__info'); let extraInfo = data?.[0]?.extraInfo; if ( extraInfo ) { extraInfo.replace(/\\n|\\r|\\t/g, ''); elBenefitInfo.innerHTML = extraInfo; const cardBtn = document.querySelector('.btn_card_benefit' ); const cardList = document.querySelector('.card_benefit_list' ); if (!cardBtn || !cardList) return; cardBtn.addEventListener('click', function () { cardList.classList.toggle('is-open'); }); } else { elBenefitInfo.remove(); } }) .catch(error => { console.log('error', error); }) .finally(()=>{ }); } //바텀 구매하기 버튼 const option = document.querySelector('.purchase__option'); const dim = document.querySelector('.back_dim'); const optionWrap = document.querySelector('.purchase.product-detail.full-width'); const opener = document.querySelector('.purchase__opener'); if (!option || !dim || !optionWrap) return; function syncState() { const isOpen = !option.classList.contains('hidden'); dim.classList.toggle('is-active', isOpen); optionWrap.classList.toggle('is-active', isOpen); opener.classList.toggle('is-show', isOpen); } syncState(); const observer = new MutationObserver(syncState); observer.observe(option, { attributes: true, attributeFilter: ['class'] }); dim.addEventListener('click', function () { const toggleBtn = document.querySelector('[shopby-on\\:click="TOGGLE_PURCHASE"]'); toggleBtn?.click(); }); }); const ACTION_HANDLER_MAP = { DISCOUNT_DETAIL: () => { EventManager.fire('OPEN_LAYER_MODAL', { title: '할인내역', name: 'discount-guide', data: { DISCOUNT_LABEL_MAP: { additionDiscountAmt: '추가할인', immediateDiscountAmt: '즉시할인', }, }, modalAddClass: 'no-full', classModifier: 'discount-price-information', onClose: () => null, }); }, COUPON_DOWNLOAD: () => { if (!utils.isSignIn()) { ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); return; } const { extraProducts } = document.querySelector('extra-products').store.state; const extraProductNos = extraProducts.map((product) => product.productNo); ShopbySkin.EventManager.fire('OPEN_LAYER_MODAL', { title: '쿠폰받기', name: 'coupon-download', data: { productNo, channelType, extraProductNos, }, isFull: true, onClose: () => null, }); }, PRODUCT_INQUIRY_WRITE: (target) => { const guestWriteable = target.getAttribute('shopby-guest-writeable') === 'true'; if (!utils.isSignIn() && !guestWriteable) { ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); return; } const productName = target.closest('[shopby-product-name]')?.getAttribute('shopby-product-name'); const imageUrl = target.closest('[shopby-image-url]')?.getAttribute('shopby-image-url'); const imageType = target.closest('[shopby-image-type]')?.getAttribute('shopby-image-type'); const { inquiryTags } = document.querySelector('product-detail-inquiry-list').store.state; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-inquiry-form', title: '상품 문의', data: { productNo, productName, unescapedProductName: unescapeHTML(productName), imageUrl, imageType, isModify: false, commonData: shopbyCommonData, useSelectProduct: false, inquiryTags, }, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '상품문의가 등록됐습니다.', onClose: () => { location.reload(); }, }); } }, }); }, INQUIRY_DETAIL: (target) => { const readable = target.closest('[shopby-readable]')?.getAttribute('shopby-readable') === 'true'; if (!readable) { EventManager.fire('MODAL_ALERT_OPEN', { message: '비밀글 조회 권한이 없습니다.', }); } }, INQUIRY_DELETE: (target) => { const inquiryNo = target.getAttribute('shopby-inquiry-no'); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'warning', message: '
삭제 시 복구가 불가능합니다.
정말 삭제하시겠습니까?
삭제 시 복구가 불가하며,
지급된 적립금이 차감됩니다.
정말 삭제하시겠습니까?
삭제 시 복구가 불가능합니다.
정말 삭제하시겠습니까?
상품이 장바구니에 담겼습니다. 바로 확인하시겠습니까?
', cancelLabel: '쇼핑계속하기', confirmLabel: '장바구니 가기', onConfirm: () => { utils.moveTo({ url: constants.PAGE.CART, }); }, }); }, PRODUCT_ORDER: async () => { if ( false === utils.isSignIn() ) { if ( true === productDetailData?.limitations?.memberOnly ) { ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); return; } } const { isSignedIn } = utils; const { data } = productOptionAction.fetchUserOptionSelections(); const { data: extraProductData } = extraProductOptionAction.fetchExtraProductUserOptionSelections(); const { requestOrderSheet } = pageHelper.productDetailHelper(); const baseProductNo = productNo; const baseProductOptions = data.map((item) => ({ ...item, productNo, orderCnt: item.count, additionalProductNo: 0, channelType, })); const extraProductOptions = extraProductData.map((item) => ({ ...item, baseProductNo, orderCnt: item.count, additionalProductNo: 0, channelType, })); const products = [...baseProductOptions, ...extraProductOptions]; if (isInvalidMinorPurchaseYn(products)) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '성인인증이 필요한 상품입니다.', noticeType: NOTICE_MODAL_TYPE.CAUTION, onConfirm: () => { utils.moveTo({ url: `${location.origin}${PAGE.ADULT_CERTIFICATION}?go-back=true`, }); }, }); return; } const { orderSheetNo } = await requestOrderSheet({ cartNos: null, channelType, productCoupons: null, trackingKey, products: products.map((item) => ({ ...item, orderCnt: item.count, additionalProductNo: 0, channelType, })), }); const orderSheetNoURL = `${location.origin}${constants.PAGE.ORDER_SHEET_FORM}?ordersheetNo=${orderSheetNo}`; const nextUrl = isSignedIn() ? orderSheetNoURL : `${location.origin}${constants.PAGE.SIGN_IN}?from=${orderSheetNoURL}`; utils.moveTo({ url: nextUrl }); }, PAY_APP_CARD: async () => { // 앱카드 결제 if (!utils.isSignIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인하셔야 본 서비스를 이용하실 수 있습니다', onConfirm: redirectLoginPage, }); return; } const { data } = productOptionAction.fetchUserOptionSelections(); const { requestOrderSheet } = pageHelper.productDetailHelper(); const { orderSheetNo } = await requestOrderSheet({ cartNos: null, channelType, productCoupons: null, trackingKey, products: data.map((item) => ({ ...item, productNo, orderCnt: item.count, additionalProductNo: 0, channelType, })), }); const orderSheetFormHelper = pageHelper.orderSheetFormHelper(); orderSheetFormHelper.orderSheetNo = orderSheetNo; await orderSheetFormHelper.actions.fetchOrderSheet({ orderSheetNo, includesMemberAddress: false, }); await orderSheetFormHelper.actions.fetchMyShippingAddress(); await orderSheetFormHelper.fetchPaymentInfo(); const amount = data?.reduce((acc, cur) => acc + cur.calcPrice, 0); await orderSheetFormHelper.actions.fetchAppCardCards({ amount, }); }, PRODUCT_LIKE: (target) => { const productNo = target.closest('[shopby-product-no]').getAttribute('shopby-product-no'); if (!productNo) { return; } ShopbySkin.actions.toggleLikeStatus({ productNo, onSuccess: (isLiked) => { const el = target.closest('[type=button]'); if (isLiked) { el.classList.add('is-active'); return; } el.classList.remove('is-active'); }, }); }, TOGGLE_SHOW_MORE: (target) => { const toggleTarget = document.querySelector('[shopby-element="product-content"]'); const status = toggleTarget.classList.toggle('hidden'); target.innerText = status ? '상세정보 펼쳐보기' : '상세정보 접기'; }, WRITE_REVIEW_REPORT: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('OPEN_LAYER_MODAL', { name: 'report-form', title: '신고하기', isFull: false, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { location.reload(); } }, onConfirm: async ({ reportReasonType, content }) => { const { status } = await actions.postProductReviewReport({ productNo, reviewNo, reportReasonCd: reportReasonType, content, }); if (status === 204) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, CANCEL_REVIEW_REPORT: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '신고를 취소 하시겠습니까?', confirmLabel: '확인', onConfirm: async () => { const { status } = await actions.deleteProductReviewReport({ productNo, reviewNo, }); if (status === 204) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고가 취소 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, // 상품문의 신고 WRITE_INQUIRY_REPORT: (target) => { const inquiryNo = target.closest('[shopby-inquiry-no]')?.getAttribute('shopby-inquiry-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('OPEN_LAYER_MODAL', { name: 'report-form', title: '신고하기', isFull: false, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { location.reload(); } }, onConfirm: async ({ reportReasonType, content }) => { const { status } = await actions.postProductInquiryReport({ productNo, inquiryNo, reportType: reportReasonType, reason: content, }); if (status === 204) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, // 상품 문의 신고 취소 CANCEL_INQUIRY_REPORT: (target) => { const inquiryNo = target.closest('[shopby-inquiry-no]')?.getAttribute('shopby-inquiry-no'); if (!utils.isSignedIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '로그인 후 이용할 수 있습니다.', onConfirm: () => { utils.moveTo({ url: `/pages/sign-in/sign-in.html?from=${encodeURIComponent(location.href)}` }); }, }); return; } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '신고를 취소 하시겠습니까?', confirmLabel: '확인', onConfirm: async () => { const { status } = await actions.deleteProductInquiryReport({ productNo, inquiryNo, }); if (status === 204) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '신고가 취소 되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, NOTIFY_RESTOCK: () => { EventManager.fire('OPEN_LAYER_MODAL', { title: '상품 재입고 알림 신청', name: 'restock-notification-form', data: { productNo, }, isFull: true, onClose: () => null, }); }, }; const ACTION_CHANGE_HANDLER_MAP = { SORT_REVIEWS: (target) => { const { value } = target; EventManager.fire('CHANGE_SORT_REVIEWS', { value }); }, }; const CLICK_ACTION_HANDLER_MAP = { HANDLE_COUNT_BTN_CLICK: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(controllerEl.getAttribute('shopby-count')); const incremental = target.getAttribute('shopby-variation') === 'INCREASE'; controller.changeCount({ optionId, count: incremental ? count + 1 : count - 1, }); productOptionAction.fetchOptionSelector(); }, HANDLE_EXTRA_PRODUCT_COUNT_BTN_CLICK: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(controllerEl.getAttribute('shopby-count')); const incremental = target.getAttribute('shopby-variation') === 'INCREASE'; controller.changeCount({ optionId, count: incremental ? count + 1 : count - 1, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, REMOVE_OPTION: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); controller.removeOption({ optionId }); productOptionAction.fetchOptionSelector(); }, REMOVE_EXTRA_PRODUCT_OPTION: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); controller.removeOption({ optionId }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, TOGGLE_TEXT_OPTIONS_BY_QUANTITY: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const type = controllerEl.getAttribute('shopby-text-option-type'); const count = Number(controllerEl.getAttribute('shopby-count')); controller.toggleTextOptionType({ optionId, inputNo, type, count, }); productOptionAction.fetchOptionSelector(); }, TOGGLE_EXTRA_PRODUCT_TEXT_OPTIONS_BY_QUANTITY: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const type = controllerEl.getAttribute('shopby-text-option-type'); const count = Number(controllerEl.getAttribute('shopby-count')); controller.toggleTextOptionType({ optionId, inputNo, type, count, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, // eslint-disable-next-line complexity CLICK_PAY_BTN: async () => { // 결제하기 const orderSheetFormHelper = pageHelper.orderSheetFormHelper(); const formData = orderSheetFormHelper.getFormData(); const { appCardInfo, shippingInfo, orderSheetTerms, hasDeliverableProduct, payMethods } = formData; const isValidShippingInfo = checkValidation({ data: shippingInfo, fields: ['receiverName', 'receiverAddress', 'receiverDetailAddress', 'receiverContact1'], }); if (hasDeliverableProduct && !isValidShippingInfo) { return; } const isNotValidCheckedTerms = orderSheetTerms.filter(({ required }) => required).some(({ checked }) => !checked); if (isNotValidCheckedTerms) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: '필수 약관을 확인해 주세요.', onClose: () => { const termCheckBox = document.querySelector('input[shopby-term-id]'); termCheckBox?.focus(); }, }); return; } const { pgType: selectedPgType } = payMethods.selectedPayMethod; if (selectedPgType === 'APP_CARD' && !appCardInfo.cardCode) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: '카드를 선택해 주세요.', }); return; } await orderSheetFormHelper.pay({ platform: ShopbySkin.platform, confirmUrl: `${location.origin}/pages/order/order-confirm.html?deliverable=${ hasDeliverableProduct ? 'Y' : 'N' }`, successCallback: (result) => { const { pgType, extraData } = result; const isOneClickPayAppCard = extraData?.authYn === 'Y'; if (pgType === 'APP_CARD' && !isOneClickPayAppCard) { EventManager.fire('OPEN_LAYER_MODAL', { name: 'app-card-authenticate', modalAddClass: 'app-card-authenticate-modal', isFull: true, data: { orderResponse: { ...result }, onRetry: CLICK_ACTION_HANDLER_MAP.CLICK_PAY_BTN, }, }); } }, }); }, SHOW_TERM_DETAIL: (target) => { const orderSheetFormHelper = pageHelper.orderSheetFormHelper(); const { orderSheetTerms } = orderSheetFormHelper.getFormData(); const termId = Number(target.getAttribute('shopby-term-id')); const foundTerm = orderSheetTerms.find(({ termsNo, customTermsNo }) => { const termNo = termsNo ?? customTermsNo; return termNo === termId; }); if (foundTerm) { EventManager.fire('OPEN_LAYER_MODAL', { name: 'term-detail', data: { ...foundTerm, title: foundTerm.termsName }, }); } }, CLICK_DELETE_CARD_ON_APP_CARD: (target) => { const acntId = target.closest('[shopby-acnt-id]')?.getAttribute('shopby-acnt-id'); if (!acntId) { return; } const orderSheetFormHelper = pageHelper.orderSheetFormHelper(); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: '카드를 삭제하시겠습니까?', confirmLabel: '확인', onConfirm: async () => { const { isSuccess } = await orderSheetFormHelper.actions.deleteAppCardPayCardsAcntId({ acntId }); if (isSuccess) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '카드가 삭제되었습니다.', }); const { data } = productOptionAction.fetchUserOptionSelections(); const amount = data?.reduce((acc, cur) => acc + cur.calcPrice, 0); orderSheetFormHelper.actions.fetchAppCardCards({ amount, }); } }, }); }, }; const CHANGE_ACTION_HANDLER_MAP = { SELECT_OPTION: (target) => { const controller = getController(target); if (!controller) { return; } const labelId = target.getAttribute('shopby-label-id'); const index = Number(target.getAttribute('shopby-index')); const optionId = target.value; controller.selectOption({ labelId, optionId, index, }); productOptionAction.fetchOptionSelector(); }, SELECT_EXTRA_PRODUCT_OPTION: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const labelId = target.getAttribute('shopby-label-id'); const index = Number(target.getAttribute('shopby-index')); const optionId = target.value; controller.selectOption({ labelId, optionId, index, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, CHANGE_COUNT: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(target.value); controller.changeCount({ optionId, count, }); productOptionAction.fetchOptionSelector(); }, CHANGE_EXTRA_PRODUCT_COUNT: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const count = Number(target.value); controller.changeCount({ optionId, count, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, INPUT_TEXT_OPTION: (target) => { const controller = getController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const textOptionId = target.getAttribute('shopby-text-option-id'); controller.inputTextOption({ value: target.value, optionId, inputNo, textOptionId, }); productOptionAction.fetchOptionSelector(); }, EXTRA_PRODUCT_INPUT_TEXT_OPTION: (target) => { const controller = getExtraProductController(target); if (!controller) { return; } const controllerEl = target.closest('[shopby-controller-id]'); const optionId = controllerEl.getAttribute('shopby-option-id'); const inputNo = Number(controllerEl.getAttribute('shopby-input-no')); const textOptionId = target.getAttribute('shopby-text-option-id'); const maxLength = target.getAttribute('shopby-max-length'); controller.inputTextOption({ value: target.value, optionId, inputNo, textOptionId, maxLength, }); extraProductOptionAction.fetchExtraProductOptionSelector(); }, }; const INPUT_ACTION_HANDLER_MAP = { INPUT_TEXT_OPTION: (target) => { const counterEl = target.closest('[shopby-counter]'); const countEl = counterEl.querySelector('[shopby-count]'); const errorMessageEl = counterEl.querySelector('[shopby-error-message]'); countEl.textContent = target.value.length; if (target.value.length > 100) { errorMessageEl.textContent = '텍스트옵션 입력글자수를 초과하였습니다.'; } else { errorMessageEl.textContent = ''; } }, }; // CLICK document.querySelector('product-summary')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(); }); document.querySelector('product-detail')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('product-detail-review-summary')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('product-detail-review-list')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('product-detail-board-button')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('[shopby-tab-element="PRODUCT_INQUIRY"]')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); productOptionEls?.forEach((el) => { el.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); document.querySelector('related-product')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); document.querySelector('product-detail-review-photo-collect')?.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); productOptionEls?.forEach((el) => { el.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); }); orderSheetAppCardEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); // CHANGE document.querySelector('product-detail-review-list')?.addEventListener('change', ({ target }) => { ACTION_CHANGE_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); productOptionEls?.forEach((el) => { el.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); }); productOptionEls?.forEach((el) => { el.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); }); selectedOptionsEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectedOptionsEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectedOptionsEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductOptionEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductOptionEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductOptionEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductSelectedOptionsEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductSelectedOptionsEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); extraProductSelectedOptionsEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectProductOptionEl?.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectProductOptionEl?.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); selectProductOptionEl?.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); })(); (()=>{ const { EventManager } = ShopbySkin; let hasIcon = false; const redirectLoginPage = () => { const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`; }; EventManager.on('PAGE_LOAD_COMPLETED', (commonData) => { EventManager.on('QUERY_PRODUCT_DETAIL', async (product) => { if ( true === Array.isArray( product?.baseInfo?.stickerInfos ) ) { for( const sticker of product?.baseInfo?.stickerInfos ) { if ( '점주전용' == sticker?.name ) { hasIcon = true } } } if ( !ShopbySkin.utils.isSignIn() || '93747' == commonData?.profile?.memberGradeNo ) { if ( hasIcon ) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType : 'CAUTION' , message : '점주전용 상품입니다.', onClose : ()=> { location.href = '/'; }, }); return; } } }); }); })();