class CustomCartProducts extends ShopbySkin.modules.CartProducts { constructor() { super(); this.eventManager.on('QUERY_CART_CHECKED_CART_NOS', async (data) => { const state = this.store.getState(); const cartProducts = state.products; // 일반배송 상품 if (cartProducts.length > 0) { let deliveryProducts = []; let pickupProducts = []; let invalidProducts = []; let orderProducts = []; cartProducts.forEach((products) => { // 상품 데이터에 배송비 관련 값 추가 products.orderProducts.forEach((product) => { if (typeof products.isInvalidProduct === 'undefined') { products.deliveryCondition.deliveryPayType = products?.deliveryPayType; product.deliveryCondition = products?.deliveryCondition; orderProducts.push({ ...product }); } else { product.isInvalidProduct = products.isInvalidProduct; orderProducts.push({ ...product }); } }); }); cartProducts[0].orderProducts = orderProducts; cartProducts[0]?.orderProducts.forEach((products) => { // 텍스트 옵션에 입력된 배송타입 let deliveryType; if (!products.optionInputs) products.optionInputs = []; deliveryType = products.optionInputs[0]?.inputValues[0]; // 일반배송인 경우 if (!deliveryType) { if (products.isInvalidProduct) { invalidProducts.push(products); } else { deliveryProducts.push(products); } } else { // 매장픽업인 경우 if (products.isInvalidProduct) { invalidProducts.push(products); } else { pickupProducts.push(products); } } }); this.store.setState((prev) => ({ ...prev, isAllChecked: true, deliveryProducts: deliveryProducts, pickupProducts: pickupProducts, invalidProducts: invalidProducts, })); } }); } } customElements.define('custom-cart-products', CustomCartProducts); (async () => { const ELEMENT_SELECTOR = { HELPER_KEY: '[shopby-helper-key="cart-helper-key"]', ACTION: 'shopby-action', SELECTED_COUNT: 'shopby-selected-count', CHECKED_CART_NOS_AS_STRING: 'shopby-checked-cart-nos-as-string', DELIVERY_GROUP_IDX: 'shopby-delivery-group-idx', IS_INVALID_PRODUCT: 'shopby-is-invalid-product', CART_NO: 'shopby-cart-no', CART_PRODUCTS: 'custom-cart-products', CHECKBOX_PER_DELIVERY_GROUP_SLOT: '[slot="checkboxPerDeliveryGroup"]', CHECKBOX_PER_CART_NO_SLOT: '[slot="checkboxPerCartNo"]', }; const { pageHelper, EventManager, actions, utils, Handlebars } = ShopbySkin; const url = new URL(window.location.href); const containerEl = document.querySelector(ELEMENT_SELECTOR.HELPER_KEY); const cartProductsEl = containerEl.querySelector( ELEMENT_SELECTOR.CART_PRODUCTS, ); const cartHelper = pageHelper.cartHelper(); cartHelper.initialize({ helperKey: 'cart-helper-key', }); // [Aaron] 구매제한 상품 구분 헬퍼 Handlebars.registerHelper({ InvalidProductFl(products, options) { let invalidProductArr = []; for (let idx in products) { if (products[idx].isInvalidProduct) invalidProductArr.push(products[idx]); } return invalidProductArr.length > 0 ? options.fn(this) : options.inverse(this); }, }); if (utils.isSignIn()) { // [Aaron] 결제정보 slot 에 보유 마일리지, 보유쿠폰, 관심상품 개수 데이터 추가 EventManager.on('QUERY_CART_PAYMENT_INFO', async (data) => { // 보유 마일리지 조회 const { result: accumulationData } = await callShopApi( '/profile/accumulations/summary', 'GET', { accessTokenType: 'member' }, ); // END // 보유 쿠폰 조회 const { result: couponData } = await callShopApi( '/coupons/summary', 'GET', { accessTokenType: 'member' }, ); // END // 관심 상품 조회 const recentProductParams = { queryString: { soldout: false, hasMaxCouponAmt: false, hasOptionValues: false, }, accessTokenType: 'member', }; const { result: recentProductData } = await callShopApi( '/profile/recent-products?', 'GET', recentProductParams, ); // END await recalculateByType(true); const type = url.searchParams.get('type'); // 회원 추가정보 업데이트 const cartOrderModule = document.querySelector('cart-order'); if (type === 'pickup') { const totalAmt = cartOrderModule.store.getState().price.totalAmt; const totalDeliveryAmt = cartOrderModule.store.getState().price.totalDeliveryAmt; cartOrderModule.store.setState((prev) => ({ ...prev, memberAdditionalData: { myAccumulationAmt: accumulationData.totalAvailableAmt, // 사용가능한 적립금 myCouponCnt: couponData.usableCouponCnt, // 보유 쿠폰 개수 (만료된 쿠폰 제외) recentProductCnt: recentProductData.length, // 최근 본 상품 개수 }, price: { ...prev.price, totalPrePaidDeliveryAmt: 0, // [Jay] 매장픽업의 경우 배송비 0원처리 totalAmt: totalAmt - totalDeliveryAmt, // [Jay] 매장픽업의 경우 배송비 제외 }, })); } else { cartOrderModule.store.setState((prev) => ({ ...prev, memberAdditionalData: { myAccumulationAmt: accumulationData.totalAvailableAmt, // 사용가능한 적립금 myCouponCnt: couponData.usableCouponCnt, // 보유 쿠폰 개수 (만료된 쿠폰 제외) recentProductCnt: recentProductData.length, // 최근 본 상품 개수 }, })); } // END }); } const handleOrder = async ({ helper, cartNos, products }) => { const { data: { orderSheetNo }, } = await helper.orderSheetAction.makeOrderSheet({ cartNos, products, }); const ordersheetUri = `/pages/order/order-sheet-form.html?ordersheetNo=${orderSheetNo}`; if (utils.isSignedIn()) { location.href = ordersheetUri; } else { const url = new URL(location.href); url.pathname = '/pages/sign-in/sign-in.html'; url.searchParams.set('from', encodeURIComponent(ordersheetUri)); location.href = url.toString(); } }; const CLICK_EVENT_HANDLER_MAP = { TOGGLE_DELIVERY_TYPE: async ({ helper, target }) => { // [Jay] 배송타입 const type = $(target).data('delivery-type'); if (type === 'delivery') { $('.tab li').removeClass('is-active'); $('#deliveryType').addClass('is-active'); url.searchParams.set('type', 'delivery'); $('#delivery').show(); $('#pickup').hide(); const deliveryItemsTg = $('#delivery') .find('.cart-list__item') .find('input[name="checked-item"]'); deliveryItemsTg.prop('checked', true); const pickupItemsTg = $('#pickup') .find('.cart-list__item') .find('input[name="checked-item"]'); pickupItemsTg.prop('checked', false); pickupItemsTg.attr('checked', false); } else { $('.tab li').removeClass('is-active'); $('#pickupType').addClass('is-active'); url.searchParams.set('type', 'pickup'); $('#delivery').hide(); $('#pickup').show(); const deliveryItemsTg = $('#delivery') .find('.cart-list__item') .find('input[name="checked-item"]'); deliveryItemsTg.prop('checked', false); const pickupItemsTg = $('#pickup') .find('.cart-list__item') .find('input[name="checked-item"]'); pickupItemsTg.prop('checked', true); } window.history.pushState({}, '', url); if (utils.isSignIn()) { EventManager.fire('QUERY_CART_PAYMENT_INFO'); } else { const itemsEl = $(`#${type}`); const guestItemsEl = itemsEl.find('input[name="checked-item"]'); let cartDataArr = []; for (const value of guestItemsEl) { const params = { channelType: null, orderCnt: value.getAttribute('shopby-order-count'), optionInputs: [ { inputValue: value.getAttribute('shopby-input-value'), inputLabel: value.getAttribute('shopby-input-label'), inputNo: value.getAttribute('shopby-input-no'), }, ], optionNo: value.getAttribute('shopby-option-no'), cartNo: value.getAttribute('shopby-cart-no'), productNo: value.getAttribute('shopby-product-no'), }; // 장바구니 번호 배열에 추가 cartDataArr.push(params); $(value).prop('checked', true); } // [Jay] 재계산 const calculateParams = { queryString: { divideInvalidProducts: true, }, data: JSON.stringify(cartDataArr), }; // [Jay] 재계산 const { result: calculationData } = await callShopApi( '/guest/cart?', 'POST', calculateParams, ); document.querySelector('cart-order').store.setState({ price: calculationData.price, selectedCount: guestItemsEl.length, totalCount: guestItemsEl.length, }); } }, TOGGLE_DELIVERY_ALL: async ({ helper, target }) => { const isChecked = $(target).is(':checked'); const itemsEl = $(target) .closest('.cart-list__control') .parent() .find('.cart-list__item'); const guestItemsEl = itemsEl.find('input[name="checked-item"]'); let cartDataArr = []; if (isChecked) { if (utils.isSignIn()) { for (const value of itemsEl) { cartDataArr.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--md').children().prop('checked', true); } } else { for (const value of guestItemsEl) { const params = { channelType: null, orderCnt: value.getAttribute('shopby-order-count'), optionInputs: [ { inputValue: value.getAttribute('shopby-input-value'), inputLabel: value.getAttribute('shopby-input-label'), inputNo: value.getAttribute('shopby-input-no'), }, ], optionNo: value.getAttribute('shopby-option-no'), cartNo: value.getAttribute('shopby-cart-no'), productNo: value.getAttribute('shopby-product-no'), }; // 장바구니 번호 배열에 추가 cartDataArr.push(params); $(value).prop('checked', true); } } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('cart-order').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, }); } else { for (const value of itemsEl) { $(value).find('.form-check--md').children().prop('checked', false); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('cart-order').store.setState({ selectedCount: 0, totalCount: 0, }); } // [Jay] 재계산 let cartApiUrl; let method; let calculateParams; if (utils.isSignIn()) { cartApiUrl = '/cart/subset?'; method = 'GET'; calculateParams = { queryString: { cartNo: cartDataArr.join(','), }, accessTokenType: 'member', }; } else { cartApiUrl = '/guest/cart?'; method = 'POST'; calculateParams = { queryString: { divideInvalidProducts: true, }, data: JSON.stringify(cartDataArr), }; } // [Jay] 재계산 const { result: calculationData } = await callShopApi( cartApiUrl, method, calculateParams, ); // END if (utils.isSignIn()) { // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); } else { document.querySelector('cart-order').store.setState({ price: calculationData.price, selectedCount: cartDataArr.length, totalCount: cartDataArr.length, }); } if (!isChecked) { // 선택된 상품만큼 선택개수 텍스트 변경 $('label[for="isAllChecked"]').find('#selectedCnt').text(0); } else { $('label[for="isAllChecked"]') .find('#selectedCnt') .text(itemsEl.length); } }, TOGGLE_PICKUP_ALL: async ({ helper, target }) => { const isChecked = $(target).is(':checked'); const itemsEl = $(target) .closest('.cart-list__control') .parent() .find('.cart-list__item'); const guestItemsEl = itemsEl.find('input[name="checked-item"]'); let cartDataArr = []; if (isChecked) { if (utils.isSignIn()) { for (const value of itemsEl) { cartDataArr.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--md').children().prop('checked', true); } } else { for (const value of guestItemsEl) { const params = { channelType: null, orderCnt: value.getAttribute('shopby-order-count'), optionInputs: [ { inputValue: value.getAttribute('shopby-input-value'), inputLabel: value.getAttribute('shopby-input-label'), inputNo: value.getAttribute('shopby-input-no'), }, ], optionNo: value.getAttribute('shopby-option-no'), cartNo: value.getAttribute('shopby-cart-no'), productNo: value.getAttribute('shopby-product-no'), }; // 장바구니 번호 배열에 추가 cartDataArr.push(params); $(value).prop('checked', true); } } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('cart-order').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, }); } else { for (const value of itemsEl) { $(value).find('.form-check--md').children().prop('checked', false); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('cart-order').store.setState({ selectedCount: 0, totalCount: 0, }); } // [Jay] 재계산 let cartApiUrl; let method; let calculateParams; if (utils.isSignIn()) { cartApiUrl = '/cart/subset?'; method = 'GET'; calculateParams = { queryString: { cartNo: cartDataArr.join(','), }, accessTokenType: 'member', }; } else { cartApiUrl = '/guest/cart?'; method = 'POST'; calculateParams = { queryString: { divideInvalidProducts: true, }, data: JSON.stringify(cartDataArr), }; } // [Jay] 재계산 const { result: calculationData } = await callShopApi( cartApiUrl, method, calculateParams, ); // END if (utils.isSignIn()) { // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); } else { document.querySelector('cart-order').store.setState({ price: calculationData.price, selectedCount: cartDataArr.length, totalCount: cartDataArr.length, }); } if (!isChecked) { // 선택된 상품만큼 선택개수 텍스트 변경 $(target) .closest('.cart-list__control') .find('label[for="isPickupAllChecked"]') .find('#selectedCnt') .text(0); } else { $(target) .closest('.cart-list__control') .find('label[for="isPickupAllChecked"]') .find('#selectedCnt') .text(itemsEl.length); } }, TOGGLE_INVALID_ALL: async ({ helper, target }) => { const isChecked = $(target).is(':checked'); const itemsEl = $(target) .closest('.cart-list__control') .parent() .find('.cart-list__item'); const guestItemsEl = itemsEl.find('input[name="checked-item"]'); let cartDataArr = []; if (isChecked) { if (utils.isSignIn()) { for (const value of itemsEl) { cartDataArr.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--md').children().prop('checked', true); } } else { for (const value of guestItemsEl) { const params = { channelType: null, orderCnt: value.getAttribute('shopby-order-count'), optionInputs: [ { inputValue: value.getAttribute('shopby-input-value'), inputLabel: value.getAttribute('shopby-input-label'), inputNo: value.getAttribute('shopby-input-no'), }, ], optionNo: value.getAttribute('shopby-option-no'), cartNo: value.getAttribute('shopby-cart-no'), productNo: value.getAttribute('shopby-product-no'), }; // 장바구니 번호 배열에 추가 cartDataArr.push(params); $(value).prop('checked', true); } } $(target) .closest('.cart-list__control') .find('#selectedCnt') .text(itemsEl.length); } else { for (const value of itemsEl) { $(value).find('.form-check--md').children().prop('checked', false); } // 선택된 상품만큼 선택개수 텍스트 변경 $(target).closest('.cart-list__control').find('#selectedCnt').text(0); } }, TOGGLE_ALL: ({ helper, target }) => { helper.cartAction.updateIsAllChecked(target.checked); }, TOGGLE_CHECKBOX_PER_DELIVERY_GROUP: ({ helper, target }) => { const labelEl = target.closest( ELEMENT_SELECTOR.CHECKBOX_PER_DELIVERY_GROUP_SLOT, ); const deliveryGroupIdx = Number( labelEl.getAttribute(ELEMENT_SELECTOR.DELIVERY_GROUP_IDX) ?? -1, ); const isInvalidProduct = labelEl.getAttribute(ELEMENT_SELECTOR.IS_INVALID_PRODUCT) === 'true'; helper.cartAction.updateIsDeliveryGroupChecked({ deliveryGroupIdx: isInvalidProduct ? -1 : deliveryGroupIdx, isChecked: target.checked, }); }, TOGGLE_CHECKBOX_PER_CART_NO: ({ helper, target }) => { const labelEl = target.closest( ELEMENT_SELECTOR.CHECKBOX_PER_CART_NO_SLOT, ); helper.cartAction.updateIsCartNoChecked({ cartNo: Number(labelEl.getAttribute(ELEMENT_SELECTOR.CART_NO) ?? 0), isChecked: target.checked, }); }, CUSTOM_TOGGLE_CHECKBOX_PER_CART_NO: async ({ helper, target }) => { const checkboxElCnt = $(target) .parents('section') .find('input[name="checked-item"]'); const checkedItems = $('input[name="checked-item"]:checked'); // checked 된 요소 const type = getUrlParam('type'); if (checkboxElCnt.length === checkedItems.length) { if (type === 'pickup') { $(target) .parents('section') .find('#isPickupAllChecked') .prop('checked', true); $(target) .parents('section') .find('#isPickupAllChecked') .attr('checked', true); } else { $(target) .parents('section') .find('#isAllChecked') .prop('checked', true); $(target) .parents('section') .find('#isAllChecked') .attr('checked', true); } } else { if (type === 'pickup') { $(target) .parents('section') .find('#isPickupAllChecked') .prop('checked', false); $(target) .parents('section') .find('#isPickupAllChecked') .attr('checked', false); } else { $(target) .parents('section') .find('#isAllChecked') .prop('checked', false); $(target) .parents('section') .find('#isAllChecked') .attr('checked', false); } } // [Jay] 재계산 await reCalculate(checkedItems); // END // [Jay] 가격 업데이트 if (utils.isSignIn()) ShopbySkin.EventManager.fire('QUERY_CART_PAYMENT_INFO'); else ShopbySkin.EventManager.fire('FETCH_CART'); // 선택된 상품만큼 선택개수 텍스트 변경 $(target) .parents('section') .find('#selectedCnt') .text(checkedItems.length); }, INVALID_TOGGLE_CHECKBOX_PER_CART_NO: async ({ helper, target }) => { const checkboxElCnt = $(target) .parents('section') .find('input[name="checked-item"]'); const checkedItems = $(target) .parents('section') .find('input[name="checked-item"]:checked'); // checked 된 요소 if (checkboxElCnt.length === checkedItems.length) { $(target) .parents('section') .find('#isInvalidAllChecked') .prop('checked', true); $(target) .parents('section') .find('#isInvalidAllChecked') .attr('checked', true); } else { $(target) .parents('section') .find('#isInvalidAllChecked') .prop('checked', false); $(target) .parents('section') .find('#isInvalidAllChecked') .attr('checked', false); } // [Jay] 재계산 await reCalculate(checkedItems); // END // [Jay] 가격 업데이트 if (utils.isSignIn()) ShopbySkin.EventManager.fire('QUERY_CART_PAYMENT_INFO'); else ShopbySkin.EventManager.fire('FETCH_CART'); // 선택된 상품만큼 선택개수 텍스트 변경 $(target) .parents('section') .find('#selectedCnt') .text(checkedItems.length); }, DELETE_SELECTED_ITEMS: ({ helper, target }) => { let selectedCount = Number( target.getAttribute(ELEMENT_SELECTOR.SELECTED_COUNT), ); const checkedCartNos = target .getAttribute(ELEMENT_SELECTOR.CHECKED_CART_NOS_AS_STRING) ?.split?.(',') ?.map(Number) ?? []; // [Aaron] 상품 직접 삭제버튼 if (target.getAttribute('delete-type') === 'DIRECT') { const selectedTopParentEl = $(target).parents('.cart-list__item'); const quantityControllerEl = selectedTopParentEl.find( '[slot="quantityController"]', )[0]; const cartNo = Number( quantityControllerEl.getAttribute('shopby-cart-no'), ); selectedCount = 1; checkedCartNos.push(cartNo); } // END if (!selectedCount) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `선택하신 상품이 없습니다.`, }); return; } if (target.getAttribute('product-type') === 'invalid') { const customCartProducts = $('#invalidProducts').find( 'custom-cart-products', ); const updatingProduct = customCartProducts[0]; updatingProduct.style.position = 'relative'; const loadingBackdrop = document.createElement('div'); loadingBackdrop.classList.add('cart__option-loading-backdrop'); const loadingSpinner = document.createElement('div'); loadingSpinner.classList.add( 'cart__option-loading-spinner', 'loader', 'loader--lg', 'loader--full', ); loadingSpinner.insertAdjacentHTML( 'beforeend', '', ); updatingProduct.appendChild(loadingBackdrop); updatingProduct.appendChild(loadingSpinner); } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: `선택하신 ${selectedCount}개의 상품을 삭제하시겠습니까?`, confirmLabel: '삭제', onConfirm: async () => { EventManager.fire('UPDATE_CART_PRODUCT'); await helper.cartAction.deleteCartNos(checkedCartNos); helper.cartAction.fetchCartDetail(); const type = url.searchParams.get('type'); // [Jay] 매장픽업 상품 삭제시 상품이 그대로 남아있어서 필터링된 상품 리스트 상태값 업데이트 처리 if (type === 'pickup') { let pickupProducts = document .querySelector('custom-cart-products') .store.getState().pickupProducts; pickupProducts = pickupProducts.filter( (product) => !checkedCartNos.includes(product.cartNo), ); document .querySelector('custom-cart-products') .store.setState((prev) => ({ ...prev, pickupProducts, })); } // END }, }); }, CUSTOM_DELETE_SELECTED_ITEMS: ({ helper, target }) => { const selectedProducts = $(target) .closest('.cart-list__control') .parent() .find('.cart-list__item') .find('input[name="checked-item"]:checked'); let checkedCartNos = []; for (const product of selectedProducts) { checkedCartNos.push(Number(product.getAttribute('shopby-cart-no'))); } // [Aaron] 상품 직접 삭제버튼 if (target.getAttribute('delete-type') === 'DIRECT') { const selectedTopParentEl = $(target).parents('.cart-list__item'); const quantityControllerEl = selectedTopParentEl.find( '[slot="quantityController"]', )[0]; const cartNo = Number( quantityControllerEl.getAttribute('shopby-cart-no'), ); selectedCount = 1; checkedCartNos.push(cartNo); } // END if (checkedCartNos.length === 0) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `선택하신 상품이 없습니다.`, }); return; } if (target.getAttribute('product-type') === 'invalid') { const customCartProducts = $('#invalidProducts').find( 'custom-cart-products', ); const updatingProduct = customCartProducts[0]; updatingProduct.style.position = 'relative'; const loadingBackdrop = document.createElement('div'); loadingBackdrop.classList.add('cart__option-loading-backdrop'); const loadingSpinner = document.createElement('div'); loadingSpinner.classList.add( 'cart__option-loading-spinner', 'loader', 'loader--lg', 'loader--full', ); loadingSpinner.insertAdjacentHTML( 'beforeend', '', ); updatingProduct.appendChild(loadingBackdrop); updatingProduct.appendChild(loadingSpinner); } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: `선택하신 ${checkedCartNos.length}개의 상품을 삭제하시겠습니까?`, confirmLabel: '삭제', onConfirm: async () => { EventManager.fire('UPDATE_CART_PRODUCT'); await helper.cartAction.deleteCartNos(checkedCartNos); helper.cartAction.fetchCartDetail(); const type = url.searchParams.get('type'); // [Jay] 매장픽업 상품 삭제시 상품이 그대로 남아있어서 필터링된 상품 리스트 상태값 업데이트 처리 if (type === 'pickup') { let pickupProducts = document .querySelector('custom-cart-products') .store.getState().pickupProducts; pickupProducts = pickupProducts.filter( (product) => !checkedCartNos.includes(product.cartNo), ); document .querySelector('#pickup custom-cart-products') .store.setState((prev) => ({ ...prev, pickupProducts, })); } else { // [Jay] 일반배송 상품 삭제시 상품이 그대로 남아있어서 필터링된 상품 리스트 상태값 업데이트 처리 let deliveryProducts = document .querySelector('custom-cart-products') .store.getState().deliveryProducts; deliveryProducts = deliveryProducts.filter( (product) => !checkedCartNos.includes(product.cartNo), ); document .querySelector('#delivery custom-cart-products') .store.setState((prev) => ({ ...prev, deliveryProducts, })); } // END }, }); }, ORDER: ({ helper, target }) => { // let { data: checkedCartNos } = helper.cartAction.fetchCheckedCartNos(); const type = url.searchParams.get('type'); let checkedCartNos = []; // 기본값 초기화 const checkedItems = $('input[name="checked-item"]:checked'); // checked 된 요소 for (const checkedItem of checkedItems) { // 장바구니 번호 배열에 추가 checkedCartNos.push(Number(checkedItem.getAttribute('shopby-cart-no'))); } let { data: checkedProducts } = helper.cartAction.fetchCheckedProducts(); checkedProducts = checkedProducts.filter((item) => { if (checkedCartNos.includes(item.cartNo)) { return item.cartNo; } }); let optionInputs = []; // [Aaron] 바로구매 버튼의 경우 데이터 초기화 후 해당 상품 데이터 재할당 if (target.getAttribute('order-type') === 'DIRECT') { const selectedTopParentEl = $(target).parents('.cart-list__item'); const quantityControllerEl = selectedTopParentEl.find( '[slot="quantityController"]', )[0]; const inputsControllerEl = selectedTopParentEl.find( '[slot="inputsController"]', ); // 텍스트 옵션 데이터 추출 const textInputValueEl = inputsControllerEl.find('[slot="inputValue"]'); // [Jay] 매장픽업일 경우에만 텍스트 옵션 데이터 추가 if (textInputValueEl.length > 0 && type === 'pickup') { $.each(textInputValueEl, function (idx, el) { const data = { inputNo: Number(el.getAttribute('shopby-input-no')), inputLabel: el.getAttribute('shopby-input-label'), required: el.getAttribute('shopby-required') === 'true' ? true : false, inputValue: el.value, }; optionInputs.push(data); }); } // END const cartNo = Number( quantityControllerEl.getAttribute('shopby-cart-no'), ); const productNo = Number( quantityControllerEl.getAttribute('shopby-product-no'), ); const optionNo = Number( quantityControllerEl.getAttribute('shopby-option-no'), ); const orderCnt = Number( $(target) .closest('.cart-list__item_btn') .siblings() .find('.counter__input input') .val(), ); const productData = { optionInputs, optionNo, orderCnt, productNo, recurringPaymentDelivery: null, }; checkedCartNos = []; checkedProducts = []; checkedCartNos.push(cartNo); checkedProducts.push(productData); } // END const invalidCartNos = Array.from( containerEl.querySelectorAll( '[slot="deliveryGroup"][shopby-delivery-group-idx="-1"]', ), ).flatMap((el) => { const cartNoEls = el.querySelectorAll('[shopby-cart-no]'); return Array.from(cartNoEls).flatMap((el) => Number(el.getAttribute('shopby-cart-no')), ); }); const hasInvalidCartNo = invalidCartNos.some((no) => checkedCartNos.includes(no), ); const editingEl = containerEl.querySelector('[shopby-status="EDITING"]'); if (editingEl) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `변경중인 옵션이 있습니다.`, onClose: () => { editingEl?.focus?.(); }, }); return; } if (!checkedCartNos.length) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `선택된 상품이 없습니다.`, }); return; } if (hasInvalidCartNo) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `선택하신 상품에 구매불가한 상품이 있습니다.`, }); return; } handleOrder({ cartNos: checkedCartNos, products: checkedProducts, helper, }); }, ORDER_ALL: async ({ helper }) => { const editingEl = containerEl.querySelector('[shopby-status="EDITING"]'); if (editingEl) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `변경중인 옵션이 있습니다.`, onClose: () => { editingEl?.focus?.(); }, }); return; } let { data } = await helper.cartAction.fetchAllValidProducts(); // const cartNos = data.map(({ cartNo }) => cartNo); const cartNos = []; // 기본값 초기화 const checkedItems = $('input[name="checked-item"]:checked'); // checked 된 요소 for (const checkedItem of checkedItems) { // 장바구니 번호 배열에 추가 cartNos.push(Number(checkedItem.getAttribute('shopby-cart-no'))); } data = data.filter((item) => { if (cartNos.includes(item.cartNo)) { return item.cartNo; } }); await handleOrder({ cartNos, products: data, helper, }); }, CARD_EVENT: () => { EventManager.fire('OPEN_LAYER_MODAL', { name: 'card-event-detail-modal', title: '카드 이벤트', isFull: false, }); }, }; async function reCalculate(target) { let cartDataArr = []; let cartApiUrl; // 장바구니 계산 api url let method; // api method let calculateParams; // api params if (utils.isSignIn()) { for (const checkedItem of target) { // 장바구니 번호 배열에 추가 cartDataArr.push(checkedItem.getAttribute('shopby-cart-no')); } } else { for (const checkedItem of target) { const params = { channelType: null, orderCnt: checkedItem.getAttribute('shopby-order-count'), optionInputs: [ { inputValue: checkedItem.getAttribute('shopby-input-value'), inputLabel: checkedItem.getAttribute('shopby-input-label'), inputNo: checkedItem.getAttribute('shopby-input-no'), }, ], optionNo: checkedItem.getAttribute('shopby-option-no'), cartNo: checkedItem.getAttribute('shopby-cart-no'), productNo: checkedItem.getAttribute('shopby-product-no'), }; // 장바구니 번호 배열에 추가 cartDataArr.push(params); } } if (utils.isSignIn()) { cartApiUrl = '/cart/subset?'; method = 'GET'; calculateParams = { queryString: { cartNo: cartDataArr.join(','), }, accessTokenType: 'member', }; } else { cartApiUrl = '/guest/cart?'; method = 'POST'; calculateParams = { queryString: { divideInvalidProducts: true, }, data: JSON.stringify(cartDataArr), }; } // [Jay] 재계산 const { result: calculationData } = await callShopApi( cartApiUrl, method, calculateParams, ); // END // [Jay] 매장픽업 선택인 경우 배송비 빠진 금액으로 노출 if (getUrlParam('type') === 'pickup') { calculationData.price.totalAmt = calculationData.price.buyAmt; calculationData.price.totalPrePaidDeliveryAmt = 0; } // [Jay] 가격 업데이트 // [Jay] 배송타입에 따른 상태값 업데이트 document.querySelector('cart-order').store.setState({ price: calculationData.price, selectedCount: cartDataArr.length, totalCount: cartDataArr.length, }); // END } const clickEventListener = ({ target }) => { const actionType = target.getAttribute(ELEMENT_SELECTOR.ACTION); CLICK_EVENT_HANDLER_MAP[actionType]?.({ target, helper: cartHelper, }); }; containerEl.addEventListener('click', clickEventListener); // 네이버 주문 const naverPay = { action: null, usable: false, el: document.querySelector('#naver-pay'), getVisibility: (visible) => (visible ? 'visible' : 'hidden'), getTotalCount: (data) => Object.keys(data)?.length || 0, handleReceiverCheckingStatus: (data) => { const { el, action, getTotalCount, getVisibility, usable } = naverPay; const totalCount = getTotalCount(data); const showsNaverPayButton = usable && totalCount > 0; const visibility = getVisibility(showsNaverPayButton); if (el) { el.style.visibility = visibility; return; } if (!showsNaverPayButton) { return; } action.showNaverPayButton({ containerElementId: 'naver-pay', isCartPage: true, }); }, handleReceiverCheckedProducts: (data) => { const items = data.map( ({ productNo, optionNo, orderCnt, optionInputs, channelType }) => ({ productNo, optionNo, orderCnt, optionInputs, channelType: channelType || utils.getQueryParams()?.channelType, }), ); naverPay.action.prepareNaverPay({ items }); }, setNaverPayAction: async ({ env, clientId }) => { naverPay.action = await actions.getNaverPayAction({ mallProfile: env, clientId, platform: utils.isMobileDevice ? 'MOBILE_WEB' : 'PC', }); // eslint-disable-next-line require-atomic-updates naverPay.usable = await naverPay.action.checkUsesNaverPayOrder(); }, }; EventManager.on('UPDATE_CART_PRODUCT', cartProductsEl?.showLoadingSpinner); // [Jay] 매장픽업 옵션 변경시 스피너 추가 EventManager.on('UPDATE_CART_PRODUCT', () => { const customCartProducts = $('#pickup').find('custom-cart-products'); const updatingProduct = customCartProducts[0]; updatingProduct.style.position = 'relative'; const loadingBackdrop = document.createElement('div'); loadingBackdrop.classList.add('cart__option-loading-backdrop'); const loadingSpinner = document.createElement('div'); loadingSpinner.classList.add( 'cart__option-loading-spinner', 'loader', 'loader--lg', 'loader--full', ); loadingSpinner.insertAdjacentHTML( 'beforeend', '', ); updatingProduct.appendChild(loadingBackdrop); updatingProduct.appendChild(loadingSpinner); }); EventManager.on( 'ON_UPDATED_CART_PRODUCT', cartProductsEl?.hideLoadingSpinner, ); EventManager.on( 'QUERY_CART_CHECKED_PRODUCTS', naverPay.handleReceiverCheckedProducts, ); // 비회원일 경우 장바구니 분리 관련 코드 EventManager.on('QUERY_CART_CHECKED_PRODUCTS', async () => { let type; if (getUrlParam('type')) type = '#' + getUrlParam('type'); else type = '#delivery'; const itemTarget = $(`${type}`).find('input[name="checked-item"]'); const checkedTarget = itemTarget.is(':checked'); // 회원 추가정보 업데이트 document.querySelector('cart-order').store.setState((prev) => ({ ...prev, totalCount: itemTarget.length, selectedCount: checkedTarget.length, })); await recalculateByType(true); }); EventManager.on( 'QUERY_CART_CHECKING_STATUS_PER_CART_NO', naverPay.handleReceiverCheckingStatus, ); EventManager.on('PAGE_LOAD_COMPLETED', (commonData) => { cartHelper.cartAction.fetchCartDetail(); naverPay.setNaverPayAction(commonData); }); // [Aaron] 비회원용 배송 타입 별 state 세팅 이벤트 async function recalculateByType(pageLoad = false) { // url 에 있는 배송타입값 let type = getUrlParam('type'); if (!type) type = 'delivery'; if (pageLoad) pushState({ type }); let cartDataParams = []; // 체크된 상품 장바구니 번호 배열 let target = $('input[name="checked-item"]:checked'); // checked 된 요소 $('.spinner-contents').hide(); if (type === 'delivery') { $('.tab li').removeClass('is-active'); $('#deliveryType').addClass('is-active'); // 매장픽업 상품들 체크 해제 $('#pickup') .find('.cart-list__item') .find('input[name="checked-item"]') .prop('checked', false); $('#delivery').show(); $('#pickup').hide(); target = $('#delivery') .find('.cart-list__item') .find('input[name="checked-item"]:checked'); } else if (type === 'pickup') { $('.tab li').removeClass('is-active'); $('#pickupType').addClass('is-active'); // 일반배송 상품들 체크 해제 $('#delivery') .find('.cart-list__item') .find('input[name="checked-item"]') .prop('checked', false); $('#delivery').hide(); $('#pickup').show(); target = $('#pickup') .find('.cart-list__item') .find('input[name="checked-item"]:checked'); } else if (type === null) { // 매장픽업 상품들 체크 해제 $('#pickup') .find('.cart-list__item') .find('input[name="checked-item"]') .prop('checked', false); $('#delivery').show(); $('#pickup').hide(); target = $('#delivery') .find('.cart-list__item') .find('input[name="checked-item"]:checked'); } // [Jay] 재계산 await reCalculate(target); // END } })();