(() => { const initialize = async (params, containerEl) => { if (params.usesProductSearch) { containerEl.setDisplayProductConfig(); return; } const { actions } = ShopbySkin; try { await actions?.getDisplayProductSectionById?.({ sectionsId: params?.sectionId, by: 'ADMIN_SETTING', direction: 'DESC', // ...params?.apiOption?.displayProductSectionByIdQueryParams, }); } catch (e) { console.error(e); containerEl.setIsLoaded(true); } }; const { EventManager, utils, constants } = ShopbySkin; const sectionId = document.currentScript.getAttribute('shopby-section-id'); const containerEl = document.querySelector(`[shopby-section-id="${sectionId}"]`); const displayProductActionMap = { // NOTE: 좋아요버튼 클릭. PRODUCT_LIKE_BTN: ({ sectionId, event }) => { event?.preventDefault?.(); const btn = event.target.closest('[shopby-product-no]'); const productNo = Number(btn.getAttribute('shopby-product-no') ?? 0); utils.isSignIn() ? EventManager.fire('MUTATE_LIKE_PRODUCT', { productNo, sectionId, onSuccess: (like) => { const likeBtns = document.querySelectorAll(`[shopby-product-no="${productNo}"]`); likeBtns?.forEach((btn) => { like ? btn.classList.add('is-active') : btn.classList.remove('is-active'); }); }, }) : EventManager.fire('MODAL_CONFIRM_OPEN', { message: `로그인하셔야 본 서비스를 이용하실 수 있습니다.`, noticeType: constants.NOTICE_MODAL_TYPE.WARNING, onConfirm: () => { const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`; }, }); }, OPEN_PRODUCT_OPTION_MODAL: ({ event }) => { event?.preventDefault?.(); const btn = event.target.closest('[shopby-product-no]'); const productNo = Number(btn.getAttribute('shopby-product-no') ?? 0); const isSoldOut = utils.convertStringBooleanToBoolean(btn.getAttribute('shopby-is-sold-out')); if (isSoldOut) { return; } if (!utils.isAdultVerified(event)) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '성인인증이 필요한 상품입니다.', noticeType: constants.NOTICE_MODAL_TYPE.CAUTION, onConfirm: () => { const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`; }, }); return; } EventManager.fire('OPEN_LAYER_MODAL', { name: 'select-product-option', title: '옵션 선택', isFull: false, modalAddClass: 'select-product-option-modal', data: { productNo, }, }); }, MOVE_PRODUCT_DETAIL: ({ event }) => { if (!utils.isAdultVerified(event)) { EventManager.fire('MODAL_CONFIRM_OPEN', { message: '성인인증이 필요한 상품입니다.', noticeType: 'CAUTION', onConfirm: () => { location.href = '/pages/intro/adult-certification.html?go-back=true'; }, }); } }, }; const clickEventListener = (e) => { const btn = e.target.closest('[shopby-action]') || e.target.parentElement.closest('[shopby-action]'); const action = btn?.getAttribute('shopby-action'); displayProductActionMap[action]?.({ sectionId, event: e, }); }; initialize( { sectionId, usesProductSearch: containerEl.hasAttribute('shopby-uses-product-search'), }, containerEl ); containerEl.addEventListener('click', clickEventListener); containerEl.removeEventListener('unload', clickEventListener); // ============================================================================ // 오늘출발 + 무료배송 뱃지 시스템 (display-product-mall 전용) // ============================================================================ // 공휴일 데이터 저장 변수 let holidayData = null; // 공휴일 API 호출 (페이지당 1회!) const initShippingBadgeSystem = async () => { if (window.ShippingBadgeUtils) { holidayData = await window.ShippingBadgeUtils.getHolidayData(); } }; // 무료배송 뱃지 적용 함수 function applyFreeShippingBadges() { // containerEl 내부에서만 상품 찾기 const productItems = containerEl.querySelectorAll('.thumb-item'); if (!containerEl.store?.state?.section?.products) return; const productData = containerEl.store.state.section.products; productItems.forEach((item, index) => { const product = productData[index]; const badgeContainer = item.querySelector('.product-badges-container'); if (!badgeContainer || !product) return; // 기존 뱃지 제거 badgeContainer.innerHTML = ''; const salePrice = product.salePrice; const deliveryType = product.deliveryConditionType; const discountAmt = product.immediateDiscountAmt; const minFreeShippingAmt = product.deliveryConditionInfo?.criteria || 50000; // ============================================ // 오늘출발 뱃지 체크 (재고 + 평일 + 17시 이전) // ============================================ let todayShippingBadgeHTML = ''; if (window.ShippingBadgeUtils && holidayData) { const canShip = window.ShippingBadgeUtils.canShipToday(holidayData.rawData, product); if (canShip) { todayShippingBadgeHTML = window.ShippingBadgeUtils.createTodayShippingBadge(); } else { // 오늘출발 불가능 시 예상 배송일 표시 (재고가 있을 때만) if (window.ShippingBadgeUtils.hasStock(product)) { const nextShippingDate = window.ShippingBadgeUtils.getNextShippingDate( holidayData.rawData, holidayData.continuousHoliday ); if (nextShippingDate) { todayShippingBadgeHTML = window.ShippingBadgeUtils.createNextShippingBadge( nextShippingDate.formatted ); } } } } const isFreeShipping = () => { if (deliveryType === 'FREE') { return true; } if (salePrice - discountAmt >= minFreeShippingAmt) { return true; } return false; }; // 무료배송 뱃지 let freeShippingBadgeHTML = ''; if (isFreeShipping()) { freeShippingBadgeHTML = '무료배송'; } // 뱃지 합치기 badgeContainer.innerHTML = todayShippingBadgeHTML + freeShippingBadgeHTML; // 무료배송 조건: deliveryConditionType이 "FREE"이거나 criteria 기준 (null이면 50000) // if ( // product.deliveryConditionType === 'FREE' || // (product.immediateDiscountAmt !== null && // product.immediateDiscountAmt >= (product.deliveryConditionInfo?.criteria || 50000)) || // (product.immediateDiscountAmt === null && // product.salePrice >= (product.deliveryConditionInfo?.criteria || 50000)) // ) { // badgeContainer.innerHTML = // '무료배송'; // } }); } // PAGE_LOAD_COMPLETED 이벤트로 뱃지 적용 EventManager.on('PAGE_LOAD_COMPLETED', async () => { // 공휴일 데이터 먼저 로드 await initShippingBadgeSystem(); // 뱃지 적용 setTimeout(() => { applyFreeShippingBadges(); }, 100); }); })(); $(document).ready(() => { setTimeout(() => { const mallSwiper = new Swiper('.mcon10 .swiper', { slidesPerView: 4, spaceBetween: 20, loop: true, speed: 800, observer: true, observeParents: true, navigation: { nextEl: '.mcon10 .swiper-button-next', prevEl: '.mcon10 .swiper-button-prev', }, autoplay: { delay: 3000, disableOnInteraction: false, }, }); }, 1000); });