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