(() => {
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);
});