(() => { const { pageHelper, EventManager, utils, actions, constants } = ShopbySkin; const { unescapeHTML } = utils; const { NOTICE_MODAL_TYPE, PAGE } = constants; const searchParams = new URLSearchParams(location.search); const productNo = Number(searchParams.get('productNo')); const channelType = searchParams.get('channelType'); const trackingKey = searchParams.get('trackingKey'); const sortType = searchParams.get('sortType'); const cartAction = actions.getCartAction(); const productOptionAction = actions.getProductOptionAction(); const extraProductOptionAction = actions.getExtraProductOptionAction(); const productOptionEls = document.querySelectorAll('product-purchase-v2'); const selectProductOptionEls = document.querySelectorAll('select-product-option'); const selectedOptionsEls = document.querySelectorAll('selected-options'); const extraProductOptionEls = document.querySelectorAll('extra-products'); const extraProductSelectedOptionsEls = document.querySelectorAll('extra-product-selected-options'); const { productDetailHelper } = pageHelper; const { initialize, deleteProductInquiryBy, searchReviewsV2 } = productDetailHelper(); let productDetailData = {} EventManager.on('QUERY_PRODUCT_DETAIL', async (product) => { productDetailData = product; await productOptionAction.fetchOptions(productNo, { productInfo: product, }); const productOptionData = productOptionAction.fetchOptionSelector(); initMiniPurchase(productOptionData?.data?.[product.productNo]); // 외부스크립트 등록 기능. 삭제금지 ShopbyExternalScript?.setGlobalObjectSb({ product }); 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('QUERY_EXTRA_PRODUCTS_BY_PRODUCT_NO', (product) => { extraProductOptionAction.fetchExtraProductOptions(productNo, product); extraProductOptionAction.fetchExtraProductOptionSelector(); }); EventManager.on('PRODUCT_DETAIL_CONTENT_LOADED', () => { const imgs = document.querySelector('product-detail').querySelectorAll('img'); utils.lazyLoad({ imgEls: imgs }); }); EventManager.on('PRODUCT_DETAIL_OPTION_IMAGES_LOADED', () => { const imgs = document.querySelector('[slot="optionImages"]')?.querySelectorAll('img'); if (!imgs) { return; } utils.lazyLoad({ imgEls: imgs }); }); initialize({ productNo, channelType, sortType, cartAction, productOptionAction, extraProductOptionAction, disableInitFetchProductOptions: true, }); const redirectLoginPage = () => { const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`; }; const productLike = (productNo, { onSuccess }) => { if (!utils.isSignIn()) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); return; } ShopbySkin.actions.toggleLikeStatus({ productNo, onSuccess, }); }; 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 getExtraProductController = (target) => { const position = target.closest('extra-products' )?.getAttribute('data-position') || target.closest('extra-product-selected-options' )?.getAttribute('data-position') ; const extraProductSelectedOptionsEl = document.querySelector(`extra-product-selected-options[data-position=${position}]`); 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 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'); }); setTimeout(function () { var thumbnailSlider = new Swiper(".slider_goods_nav .swiper", { spaceBetween: 20, slidesPerView: 6.2, freeMode: true, watchSlidesProgress: true, }); var mainImageSlider = new Swiper(".item_photo_big .swiper", { loop: true, thumbs: { swiper: thumbnailSlider, }, speed: 600, }); const detailContent = document.querySelector(".detail_content"); const viewMoreBtn = document.querySelector(".btn_view_more"); const viewMoreText = viewMoreBtn?.querySelector("p"); if (!detailContent || !viewMoreBtn) return; function applyLogic(height) { if (height > 1000) { detailContent.classList.remove("is-expanded"); detailContent.classList.add("is-collapsed"); viewMoreBtn.style.display = "flex"; viewMoreText.textContent = "상세정보 더보기"; } else { detailContent.classList.remove("is-collapsed"); detailContent.classList.add("is-expanded"); viewMoreBtn.style.display = "none"; } } const observer = new ResizeObserver(entries => { for (let entry of entries) { const height = entry.target.scrollHeight; if (height > 50) { applyLogic(height); observer.disconnect(); // 한 번만 실행 } } }); observer.observe(detailContent); // 버튼 토글 viewMoreBtn.addEventListener("click", function () { const isCollapsed = detailContent.classList.contains("is-collapsed"); if (isCollapsed) { detailContent.classList.remove("is-collapsed"); detailContent.classList.add("is-expanded"); viewMoreText.textContent = "상세정보 접기"; } else { detailContent.classList.remove("is-expanded"); detailContent.classList.add("is-collapsed"); viewMoreText.textContent = "상세정보 더보기"; detailContent.scrollIntoView({ behavior: "smooth", block: "start" }); } }); const tabButtons = document.querySelectorAll('.tab__btn'); const sections = []; // 버튼과 연결된 section 매칭 tabButtons.forEach(btn => { const id = btn.getAttribute('shopby-tab-value'); const section = document.getElementById(id); if (section) { sections.push({ id, button: btn, section }); } }); // 클릭 시 부드럽게 이동 tabButtons.forEach(btn => { btn.addEventListener('click', function (e) { e.preventDefault(); const id = this.getAttribute('shopby-tab-value'); const target = document.getElementById(id); if (!target) return; window.scrollTo({ top: target.offsetTop - 100, // 상단 고정탭 높이만큼 보정 behavior: 'smooth' }); }); }); window.addEventListener('scroll', function () { const scrollPos = window.scrollY + 150; sections.forEach(item => { const top = item.section.offsetTop; const height = item.section.offsetHeight; if (scrollPos >= top && scrollPos < top + height) { tabButtons.forEach(btn => btn.classList.remove('is-active')); item.button.classList.add('is-active'); } }); }); }, 500); }); const ACTION_HANDLER_MAP = { 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: utils.getChannelType(), extraProductNos, }, isFull: false, onClose: () => null, }); }, INQUIRY_DETAIL: (target) => { const readable = target.getAttribute('shopby-readable') === 'true'; if (!readable) { EventManager.fire('MODAL_ALERT_OPEN', { message: '비밀글 조회 권한이 없습니다.', }); return; } target.closest('[shopby-active]').classList.toggle('active'); }, PRODUCT_INQUIRY_WRITE: (target) => { if (!utils.isSignIn()) { 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: '상품문의', modalAddClass: 'product-inquiry-form-modal', isFull: false, 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_DELETE: (target) => { const inquiryNo = target.getAttribute('shopby-inquiry-no'); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'warning', message: '

삭제 시 복구가 불가능합니다.
정말 삭제하시겠습니까?

', onConfirm: async () => { await deleteProductInquiryBy({ inquiryNo }); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '삭제되었습니다.', onClose: () => { location.reload(); }, }); }, }); }, INQUIRY_MODIFY: (target) => { const inquiryNo = target.getAttribute('shopby-inquiry-no'); const { inquiryTags } = document.querySelector('product-detail-inquiry-list').store.state; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-inquiry-form', title: '상품문의', modalAddClass: 'product-inquiry-form-modal', isFull: false, data: { productNo, inquiryNo, isModify: true, commonData: shopbyCommonData, inquiryTags, }, onClose: ({ reason }) => { if (reason === 'DID_MODIFY') { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '수정이 완료되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, WRITE_REVIEW: (target) => { const reviewableCount = Number(target.getAttribute('shopby-reviewable-count')); const usesAttachment = target.getAttribute('shopby-uses-attachment') === 'true'; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-review-form', title: '상품후기', modalAddClass: 'product-review-form-modal', isFull: false, data: { productNo, isModify: false, useSelectOrderProduct: reviewableCount > 1, usesAttachment, }, onClose: ({ reason }) => { if (reason === 'DID_SUBMIT') { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '상품후기가 작성되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, REVIEW_DETAIL: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); const targetEl = document.querySelector(`[shopby-target="REVIEW-OPEN-${reviewNo}"]`); targetEl.classList.toggle('is-open'); }, REVIEW_DETAIL_POPUP: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); const reviewListEl = document.querySelector('product-detail-review-list'); const { boardConfig = {}, photoCollections = [] } = reviewListEl?.store.state ?? {}; const { expandedReviewConfig = {} } = boardConfig ?? {}; const { photoReviewDisplayType = '' } = expandedReviewConfig ?? {}; const modalAddClass = photoReviewDisplayType === 'FIRST_TYPE' ? 'first-type-modal' : 'second-type-modal'; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-review-detail', title: '상품후기 상세', modalAddClass: `board-reviews-detail-${modalAddClass}`, isFull: false, data: { productNo, reviewNo, pageReviewNo: reviewNo, reviewConfig: boardConfig, reviews: photoCollections, queryParams: { boardType: 'ALL', }, }, }); }, PHOTO_REVIEW_MORE: async () => { const { data } = await searchReviewsV2({ productNo, channelType, sortType: 'RECOMMEND', hasAttachmentFile: true, pageSize: 20, }); const photoCollections = data.reviews.map(({ images, reviewNo }) => ({ urls: images, attachedFileCount: images.length, productNo, reviewNo, })); const reviewListEl = document.querySelector('product-detail-review-list'); const { boardConfig = {} } = reviewListEl?.store.state ?? {}; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-review-photos', title: `포토(${photoCollections.length})`, isFull: true, data: { images: photoCollections, reviewConfig: boardConfig, }, }); }, REVIEW_MODIFY: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); const boardName = target.closest('[shopby-board-name]')?.getAttribute('shopby-board-name'); const usesAttachment = target.closest('[shopby-uses-attachment]')?.getAttribute('shopby-uses-attachment') === 'true'; EventManager.fire('OPEN_LAYER_MODAL', { name: 'product-review-form', title: boardName, modalAddClass: 'product-review-form-modal', isFull: false, data: { productNo, reviewNo, isModify: true, usesAttachment }, onClose: ({ reason }) => { if (reason === 'DID_MODIFY') { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '수정이 완료되었습니다.', onClose: () => { location.reload(); }, }); } }, }); }, REVIEW_DELETE: (target) => { const reviewNo = target.closest('[shopby-review-no]')?.getAttribute('shopby-review-no'); const givenAccumulation = target.getAttribute('shopby-given-accumulation'); const confirmMessage = givenAccumulation.toUpperCase() === 'Y' ? '

삭제 시 복구가 불가하며,
지급된 적립금이 차감됩니다.
정말 삭제하시겠습니까?

' : '

삭제 시 복구가 불가능합니다.
정말 삭제하시겠습니까?

'; const myProductReviewListHelper = pageHelper.myProductReviewListHelper(); myProductReviewListHelper.initialize(); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'warning', message: confirmMessage, onConfirm: async () => { await myProductReviewListHelper.deleteReview({ productNo, reviewNo }); EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'success', message: '삭제되었습니다.', onClose: () => { location.reload(); }, }); }, }); }, ADD_CART: async () => { if ( false === utils.isSignIn() ) { if ( true === productDetailData?.limitations?.memberOnly ) { ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); return; } } const { data } = productOptionAction.fetchUserOptionSelections(); const { data: extraProductData } = extraProductOptionAction.fetchExtraProductUserOptionSelections(); const { addCart } = pageHelper.productDetailHelper(); const baseProductNo = productNo; const baseProductOptions = data.map((item) => ({ ...item, channelType, productNo, orderCnt: item.count, })); const extraProductOptions = extraProductData.map((item) => ({ ...item, baseProductNo, channelType, productNo: Number(item.productNo), orderCnt: item.count, })); const products = [...baseProductOptions, ...extraProductOptions]; if (isInvalidMinorPurchaseYn(products)) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '성인인증이 필요한 상품입니다.', noticeType: NOTICE_MODAL_TYPE.CAUTION, onConfirm: () => { const nextUrl = encodeURIComponent( `${location.origin}${constants.PAGE.PRODUCT_DETAIL}?productNo=${productNo}` ); utils.moveTo({ url: `${location.origin}${PAGE.ADULT_CERTIFICATION}?go-back=true&from=${nextUrl}`, }); }, }); return; } await addCart(products); EventManager.fire('MODAL_CONFIRM_OPEN', { message: '

상품이 장바구니에 담겼습니다. 바로 확인하시겠습니까?

', cancelLabel: '쇼핑계속하기', confirmLabel: '장바구니 가기', onConfirm: () => { location.href = '/pages/order/cart.html'; }, }); }, 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: () => { const nextUrl = encodeURIComponent( `${location.origin}${constants.PAGE.PRODUCT_DETAIL}?productNo=${productNo}` ); utils.moveTo({ url: `${location.origin}${PAGE.ADULT_CERTIFICATION}?go-back=true&from=${nextUrl}`, }); }, }); return; } const { orderSheetNo } = await requestOrderSheet({ cartNos: null, channelType, productCoupons: null, trackingKey, products, }); const orderSheetNoURL = `${location.origin}/pages/order/order-sheet-form.html?ordersheetNo=${orderSheetNo}`; const nextUrl = isSignedIn() ? orderSheetNoURL : `${location.origin}/pages/sign-in/sign-in.html?from=${orderSheetNoURL}`; window.location.href = nextUrl; }, SORT_TAB: (target) => { const sortType = target.getAttribute('shopby-sort-type'); const params = new URLSearchParams({ productNo, sortType, }); EventManager.fire('CHANGE_SORT_REVIEWS', { value: sortType }); history.pushState(null, null, `?${params.toString()}#PRODUCT_REVIEW`); }, REVIEW_CONTENT_TEXT: (target) => { target.closest('[shopby-element]').classList.toggle('open'); }, TOGGLE_DISCOUNT_DETAIL: () => { document.querySelector("[shopby-element='discount-tooltip']").classList.toggle('active'); }, RECOMMEND: () => { if (!utils.isSignIn()) { ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', { message: '로그인 후 이용할 수 있습니다.', onConfirm: redirectLoginPage, }); } }, PRODUCT_LIKE: (event) => { event.preventDefault(); const { target } = event; productLike(productNo, { onSuccess: (isLiked) => { //const el = target.closest('[type=button]'); const els = document.querySelectorAll('[shopby-action="PRODUCT_LIKE"]'); const messageEls = document.querySelectorAll('[shopby-element="like-action-message"]'); messageEls.forEach((v)=>{ v.classList.remove('like-message'); }); // 페이드 아웃 메시지 setTimeout(() => { const actionMessage = isLiked ? '상품이 좋아요 리스트에 추가되었습니다.' : '상품이 좋아요 리스트에 제거되었습니다.'; messageEls.forEach((v)=>{ v.innerText = actionMessage; v.classList.add('like-message'); }); }, 20); if (isLiked) { els.forEach((v)=>{ v.classList.add('is-active'); }); return; } els.forEach((v)=>{ v.classList.remove('is-active'); }); }, }); }, RELATED_PRODUCT_LIKE: (event) => { event.preventDefault(); const { target } = event; const productNo = target.closest('[shopby-product-no]')?.getAttribute('shopby-product-no'); if (!productNo) { return; } productLike(productNo, { onSuccess: (isLiked) => { const el = target.closest('[type=button]'); if (isLiked) { el.classList.add('is-active'); return; } el.classList.remove('is-active'); }, }); }, 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: false, onClose: () => null, }); }, }; 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(); }, }; 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'); const maxLength = target.getAttribute('shopby-max-length'); controller.inputTextOption({ value: target.value, optionId, inputNo, textOptionId, maxLength, }); 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 = ''; } }, }; document.querySelectorAll('product-summary')?.forEach((v) => { v.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(); }); }); document.querySelectorAll('product-purchase-v2')?.forEach((v) => { v.addEventListener('click', (event) => { ACTION_HANDLER_MAP[event.target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(event); }); }); document.querySelectorAll('product-detail-review-list')?.forEach((v) => { v.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); document.querySelectorAll('product-detail-board-button')?.forEach((v) => { v.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); document.querySelectorAll('product-detail-inquiry-list')?.forEach((v) => { v.addEventListener('click', ({ target }) => { ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); document.querySelectorAll('related-product')?.forEach((v) => { v.addEventListener('click', (event) => { ACTION_HANDLER_MAP[event.target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(event); }); }); productOptionEls?.forEach((v) => { v.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); }); productOptionEls?.forEach((v) => { v.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); }); productOptionEls?.forEach((v) => { v.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.getAttribute('shopby-action')]?.(target); }); }); selectedOptionsEls?.forEach((v) => { v.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); selectedOptionsEls?.forEach((v) => { v.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); selectedOptionsEls?.forEach((v) => { v.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); extraProductOptionEls?.forEach((v) => { v.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); extraProductOptionEls?.forEach((v) => { v.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); extraProductOptionEls?.forEach((v) => { v.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); extraProductSelectedOptionsEls?.forEach((v) => { v.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); extraProductSelectedOptionsEls?.forEach((v) => { v.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); extraProductSelectedOptionsEls?.forEach((v) => { v.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); selectProductOptionEls?.forEach((v) => { v.addEventListener('click', ({ target }) => { CLICK_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); selectProductOptionEls?.forEach((v) => { v.addEventListener('change', ({ target }) => { CHANGE_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); selectProductOptionEls?.forEach((v) => { v.addEventListener('input', ({ target }) => { INPUT_ACTION_HANDLER_MAP[target.closest('[shopby-action]')?.getAttribute('shopby-action')]?.(target); }); }); function initMiniPurchase(productOptionData) { const hasOption = productOptionData?.multiLevelOptions?.length > 1 ? 'Y' : 'N' ; setTimeout(() => { if ('Y' == hasOption) { $('.floating_box .for-option').show(); } else { $('.floating_box .for-no-option').show(); } }, 500); $('.product-summary').attr('data-has-option', hasOption); } })(); (()=>{ 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; } } }); }); })();