(() => {
const { pageHelper, EventManager, utils, actions } = ShopbySkin;
const eventDetailHelper = pageHelper.eventDetailHelper();
const { getQueryParams, replaceHistory, isSignIn } = utils;
const containerEl = document.querySelector('[shopby-helper-key="event-detail-helper-key"]');
const { event: eventNoOrId, pageSize, pageNumber, sectionNo } = getQueryParams(location);
const eventDetailRequest = {
eventKey: eventNoOrId,
};
const eventDetailProductRequest = {
sortType: 'ADMIN_SETTING',
soldOut: true,
includeStopProduct: true,
};
const searchParams = new URLSearchParams(location.search);
const eventDetailProductRequestParamType = [
'event',
'sectionNo',
'pageNumber',
'pageSize',
'sortType',
'direction',
'soldOut',
'includeStopProduct',
];
const redirectLoginPage = () => {
const nextUrl = '/pages/sign-in/sign-in.html';
location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`;
};
const convertEventDetailRequestParam = (params, filterTypes) =>
Object.fromEntries(params?.filter(([key]) => !filterTypes.includes(key)));
eventDetailHelper.initialize({
helperKey: 'event-detail-helper-key',
});
const likeHelper = {
toggleClassName: (likeEl) => {
likeEl.classList.toggle('is-active');
},
toggleLikeStatus: async (likeEl) => {
const productNo = likeEl.getAttribute('shopby-product-no') ?? 0;
await actions.toggleLikeStatus({
productNo: Number(productNo),
});
},
};
const CLICK_EVENT_HANDLER_MAP = {
HANDLE_COUPON_BTN_CLICK: () => {
if (!isSignIn()) {
ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', {
noticeType: 'CAUTION',
message: '로그인하셔야 본 서비스를 이용하실 수 있습니다.',
onConfirm: redirectLoginPage,
});
return;
}
const { coupon, eventNo } = document.querySelector('event-detail-product-list-v2').store.state ?? {};
ShopbySkin.EventManager.fire('OPEN_LAYER_MODAL', {
title: '쿠폰받기',
name: 'coupon-download',
data: {
coupons: coupon?.coupons?.filter(({ downloadable }) => downloadable) ?? [],
eventNo,
},
isFull: false,
onClose: () => null,
});
},
HANDLE_SECTION_ID_CLICK: ({ target, helper }) => {
const tabId = target.getAttribute('shopby-tab-id');
const currentSectionNo = target.getAttribute('shopby-section-no');
const { eventNo } = document.querySelector('event-detail-product-list-v2').store.state ?? {};
helper.eventAction.selectEventCategoryV2({ tabId, sectionNo: currentSectionNo });
searchParams.set('sectionNo', currentSectionNo);
searchParams.set('pageNumber', 1);
const param = Object.fromEntries(searchParams);
replaceHistory({ query: param });
const { event, ...rest } = param;
eventDetailHelper.eventAction.fetchEventDetailProducts({
...eventDetailProductRequest,
...rest,
eventNo,
sectionNo: currentSectionNo,
pageSize,
pageNumber: 1,
});
},
LIKE_PRODUCT: ({ target }) => {
if (!isSignIn()) {
ShopbySkin.EventManager.fire('MODAL_CONFIRM_OPEN', {
noticeType: 'CAUTION',
message: '로그인하셔야 본 서비스를 이용하실 수 있습니다.',
onConfirm: redirectLoginPage,
});
return;
}
const likeEl = target.closest('[shopby-product-no]');
likeHelper.toggleClassName(likeEl);
likeHelper.toggleLikeStatus(likeEl);
},
};
const CHANGE_EVENT_HANDLER_MAP = {
HANDLE_SORT_CHANGE: ({ target, helper }) => {
const paramArray = Array.from(searchParams.entries());
const eventDetailRequestParam = convertEventDetailRequestParam(paramArray, eventDetailProductRequestParamType);
helper.eventAction.fetchEventDetailV2({
...eventDetailRequestParam,
...eventDetailRequest,
sortType: target.value,
});
},
};
EventManager.fire('INIT_EVENT_PRODUCT_SECTION_SLIDER', {
spaceBetween: 32,
direction: 'horizontal',
effect: 'slide',
slidesPerView: 'auto',
});
EventManager.on('PAGE_LOAD_COMPLETED', () => {
const paramArray = Array.from(searchParams.entries());
const eventDetailRequestParam = convertEventDetailRequestParam(paramArray, eventDetailProductRequestParamType);
eventDetailHelper.eventAction.fetchEventDetailV2({ ...eventDetailRequestParam, ...eventDetailRequest });
EventManager.on('QUERY_DISPLAY_EVENTS_EVENT_NO', (data) => {
const currentSectionNo = sectionNo ?? data.listOfExhibition[0]?.sectionNo;
if (!currentSectionNo) return;
searchParams.set('sectionNo', currentSectionNo);
const param = Object.fromEntries(searchParams);
replaceHistory({ query: param });
const { event, ...rest } = param;
eventDetailHelper.eventAction.fetchEventDetailProducts({
...eventDetailProductRequest,
...rest,
eventNo: data.eventNo,
sectionNo: currentSectionNo,
pageSize,
pageNumber,
});
});
});
const clickEventListener = ({ target }) => {
const actionType = target.getAttribute('shopby-action') ?? target.closest('button')?.getAttribute('shopby-action');
CLICK_EVENT_HANDLER_MAP[actionType]?.({ helper: eventDetailHelper, target });
};
const changeEventListener = ({ target }) => {
const actionType = target.getAttribute('shopby-action');
CHANGE_EVENT_HANDLER_MAP[actionType]?.({ helper: eventDetailHelper, target });
};
containerEl.addEventListener('click', clickEventListener);
containerEl.addEventListener('change', changeEventListener);
// ✅ 탭 클릭 이벤트 — btn 변수를 forEach 블록 안에서만 사용하도록 수정
const tabs = document.querySelectorAll('.tabs');
tabs.forEach(tab => {
const btns = tab.querySelectorAll('.event-detail .tab-btn');
const contents = tab.querySelectorAll('.event-detail .tab-content');
btns.forEach((btn, index) => {
btn.addEventListener('click', () => {
btns.forEach(b => b.classList.remove('active'));
contents.forEach(c => c.classList.remove('active'));
btn.classList.add('active');
contents[index].classList.add('active');
// 슬라이더 재초기화를 forEach 블록 안으로 이동
setTimeout(() => {
EventManager.fire('INIT_EVENT_PRODUCT_SECTION_SLIDER');
}, 0);
});
});
});
// URL 파라미터 기반 탭 초기화
(function () {
const urlParams = new URLSearchParams(window.location.search);
const eventNo = urlParams.get('event');
const currentEvent = eventNo || '79204';
const allTabs = document.querySelectorAll('.tab-btn');
allTabs.forEach(tab => tab.classList.remove('active'));
if (currentEvent === '79204') {
allTabs[0]?.classList.add('active');
} else if (currentEvent === '73820') {
allTabs[1]?.classList.add('active');
}
})();
// 할인율 반올림 처리 — discountObserver 선언 후 내부 참조하도록 순서 수정
const removeDecimalDiscount = () => {
document.querySelectorAll('.rate em').forEach((el) => {
if (el.dataset.rounded) return;
const numericVal = parseFloat(el.textContent.replace(/[^0-9.]/g, ''));
if (!isNaN(numericVal)) {
el.textContent = Math.round(numericVal) + '%';
el.dataset.rounded = 'true';
}
});
};
const targetNode = document.querySelector('.event-detail') || document.body;
const discountObserver = new MutationObserver(() => {
discountObserver.disconnect();
removeDecimalDiscount();
discountObserver.observe(targetNode, { childList: true, subtree: true }); // ✅ 이제 선언 후 참조
});
if (targetNode) {
discountObserver.observe(targetNode, { childList: true, subtree: true });
}
})();