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; // 일반배송 상품 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 }); } }); }); // 상품이 있을때만 아래 로직 실행 if (cartProducts.length > 0) { cartProducts[0].orderProducts = orderProducts; cartProducts[0]?.orderProducts.forEach((products) => { if (!products.optionInputs) products.optionInputs = []; // 텍스트 옵션에 입력된 배송타입 const 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); class CustomCartOrder extends ShopbySkin.modules.CartOrder { setup() { super.setup(); this.eventManager.on('QUERY_CART_CHECKED_CART_NOS', (data) => { let target; // checked 된 요소 const url = new URL(window.location.href); // url 에 있는 배송타입값 const deliveryType = url.searchParams.get('type'); if (deliveryType === 'delivery') { target = $('#delivery').find('input[name="checked-item"]:checked'); } else if (deliveryType === 'pickup') { target = $('#pickup').find('input[name="checked-item"]:checked'); } else if (deliveryType === null) { target = $('#delivery').find('input[name="checked-item"]:checked'); } // 타입별 상품 갯수 업데이트 this.store.setState({ selectedCount: target.length, }); this.store.attach('selectedCount', (prev) => { this.updateSlot(prev, 'selectedCount'); }); }); } } customElements.define('custom-cart-order', CustomCartOrder); (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 } = 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', }); EventManager.on('QUERY_CART_CHECKED_CART_NOS', async () => { // url 에 있는 배송타입값 const deliveryType = url.searchParams.get('type'); // [Jay] url 에 값이 없는 경우/type 이 delivery 인 경우 url 에 'delivery' 셋팅 if (deliveryType === 'delivery') { url.searchParams.set('type', 'delivery'); } else if (deliveryType === 'pickup') { url.searchParams.set('type', 'pickup'); } else if (deliveryType === null) { url.searchParams.set('type', 'delivery'); } // url 업데이트 window.history.pushState({}, '', url); let cartNoArr = []; // 체크된 상품 장바구니 번호 배열 let productCount = 0; // 배송타입별 상품 갯수 let target = $('input[name="checked-item"]:checked'); // checked 된 요소 $('.spinner-contents').hide(); if (deliveryType === 'delivery') { // 매장픽업 상품들 체크 해제 $('#pickup') .find('.cart__product') .find('input[name="checked-item"]') .prop('checked', false); $('#deliveryType').addClass('active'); $('#delivery').show(); $('#pickup').hide(); target = $('#delivery') .find('.cart__product') .find('input[name="checked-item"]:checked'); productCount = $('#delivery').find('.cart__product').length; } else if (deliveryType === 'pickup') { // 일반배송 상품들 체크 해제 $('#delivery') .find('.cart__product') .find('input[name="checked-item"]') .prop('checked', false); $('#pickupType').addClass('active'); $('#delivery').hide(); $('#pickup').show(); target = $('#pickup') .find('.cart__product') .find('input[name="checked-item"]:checked'); productCount = $('#pickup').find('.cart__product').length; } else if (deliveryType === null) { // 매장픽업 상품들 체크 해제 $('#pickup') .find('.cart__product') .find('input[name="checked-item"]') .prop('checked', false); $('#delivery').show(); $('#pickup').hide(); target = $('#delivery') .find('.cart__product') .find('input[name="checked-item"]:checked'); productCount = $('#delivery').find('.cart__product').length; } for (const checkedItem of target) { // 장바구니 번호 배열에 추가 cartNoArr.push(checkedItem.getAttribute('shopby-cart-no')); } // [Jay] 재계산 if (utils.isSignedIn()) { const calculateParams = { queryString: { cartNo: cartNoArr.join(','), }, accessTokenType: 'member', }; const { result: calculationData } = await callShopApi( '/cart/subset?', 'GET', calculateParams, ); // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); // END } else { const productArr = []; for (const checkedItem of target) { // 상품 수량 const productOrderCnt = $(checkedItem) .closest('.cart-product__top') .find('.cart-product__top-content') .find('.counter__input input') .val(); const productData = { cartNo: Number(checkedItem.getAttribute('shopby-cart-no')), productNo: Number(checkedItem.getAttribute('shopby-product-no')), optionNo: Number(checkedItem.getAttribute('shopby-option-no')), orderCnt: Number(productOrderCnt), optionInputs: [], // 텍스트 옵션에 따로 추가금 안붙을 예정이라 빈배열 넣어줌 channelType: '', }; // 장바구니 번호 배열에 추가 productArr.push(productData); } const calculateParams = { queryString: { divideInvalidProducts: false, }, data: JSON.stringify(productArr), }; const { result: price } = await callShopApi( '/guest/cart?', 'POST', calculateParams, ); // [Jay] 매장픽업인 경우에는 배송비 제거 if (getUrlParam('type') === 'pickup') { price.price.totalAmt = price.price.totalAmt - price.price.totalDeliveryAmt; price.price.totalPrePaidDeliveryAmt = 0; } // [Jay] 가격 업데이트 document.querySelector('cart-order').store.setState({ price: price.price, }); document.querySelector('custom-cart-order').store.setState({ price: price.price, }); // END } // END // [Jay] 상품 갯수 상태 업데이트 document.querySelector('custom-cart-products').store.setState({ selectedCount: cartNoArr.length, totalCount: productCount, }); // END // [Jay] 최초 접속시 전체선택 풀려있어서 checked const deliveryAllCheckTg = $('#delivery').find('#deliveryAllCheck'); deliveryAllCheckTg.prop('checked', true); deliveryAllCheckTg.attr('checked', true); // END // [Jay] 구매불가 상품 전체선택 카운트 set const invalidComponent = document.getElementById('invalidProducts'); const invalidProductCount = $('#invalidProducts').find('.cart__product').length; invalidComponent.querySelector('custom-cart-products').store.setState({ selectedCount: 0, totalCount: invalidProductCount, }); // END // [Jay] 구매불가 상품이 있는 경우 show if (invalidProductCount !== 0) { $('#invalidProducts').show(); } else { $('#invalidProducts').hide(); } // END $('.product-multiOption-price').each(function () { var productWidth = $(this).width(); var tooltip = $(this).closest('li').find('.tool-tip-info-icon'); var tooltipIcon = $(this).closest('li').find('.tooltip-icon'); if (tooltip.length) { // 요소가 있는지 확인 tooltip.css('--discount-width', `${productWidth}px`); // tooltip 아이콘 클릭 이벤트 추가 tooltipIcon.on('click', function () { $(this) .closest('.product-multiOption-cont') .find('.tool-tip-wrap') .toggleClass('active'); }); } }); }); EventManager.on('QUERY_CART_PAYMENT_INFO', async (data) => { const type = url.searchParams.get('type'); const cartOrderModule = document.querySelector('cart-order'); const customCartOrderModule = document.querySelector('custom-cart-order'); // [Jay] 가격 업데이트 if (type === 'pickup') { const totalAmt = cartOrderModule.store.getState().price.totalAmt; const totalDeliveryAmt = cartOrderModule.store.getState().price.totalDeliveryAmt; cartOrderModule.store.setState((prev) => ({ ...prev, price: { ...prev.price, totalPrePaidDeliveryAmt: 0, // [Jay] 매장픽업의 경우 배송비 0원처리 totalAmt: totalAmt - totalDeliveryAmt, // [Jay] 매장픽업의 경우 배송비 제외 }, })); customCartOrderModule.store.setState((prev) => ({ ...prev, price: { ...prev.price, totalPrePaidDeliveryAmt: 0, // [Jay] 매장픽업의 경우 배송비 0원처리 totalAmt: totalAmt - totalDeliveryAmt, // [Jay] 매장픽업의 경우 배송비 제외 }, })); } }); const CLICK_EVENT_HANDLER_MAP = { TOGGLE_DELIVERY_TYPE: async ({ helper, target }) => { // [Jay] 배송타입 const type = $(target).data('delivery-type'); let itemsEl; if (type === 'delivery') { url.searchParams.set('type', 'delivery'); $('#delivery').show(); $('#pickup').hide(); $('#deliveryType').addClass('active'); // [Jay] 매장픽업 상품 unchecked, 일반배송 상품 checked 처리 const deliveryItemsTg = $('#delivery') .find('.cart__product') .find('input[name="checked-item"]'); deliveryItemsTg.prop('checked', true); const pickupItemsTg = $('#pickup') .find('.cart__product') .find('input[name="checked-item"]'); pickupItemsTg.prop('checked', false); pickupItemsTg.attr('checked', false); // END // [Jay] 선택한 배송타입에 따른 상품 checked elements itemsEl = $(target) .parent() .siblings() .parent() .find('#delivery') .find('.cart__product') .find('input[name="checked-item"]'); } else { url.searchParams.set('type', 'pickup'); $('#delivery').hide(); $('#pickup').show(); $('#pickupType').addClass('active'); // [Jay] 매장픽업 상품 checked, 일반배송 상품 unchecked 처리 const deliveryItemsTg = $('#delivery') .find('.cart__product') .find('input[name="checked-item"]'); deliveryItemsTg.prop('checked', false); deliveryItemsTg.attr('checked', false); const pickupItemsTg = $('#pickup') .find('.cart__product') .find('input[name="checked-item"]'); pickupItemsTg.prop('checked', true); pickupItemsTg.attr('checked', true); // END // [Jay] 선택한 배송타입에 따른 상품 checked elements itemsEl = $(target) .parent() .siblings() .parent() .find('#pickup') .find('.cart__product') .find('input[name="checked-item"]'); } window.history.pushState({}, '', url); // [Jay] 선택된 장바구니 번호 추출 const cartNo = []; for (const value of itemsEl) { cartNo.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--sm').children().prop('checked', true); } // END // [Jay] 배송타입별 상품 개수 상태값 변경 및 전체선택 checked 처리 if (type === 'delivery') { const deliveryElement = document.getElementById('delivery'); deliveryElement.querySelector('custom-cart-products').store.setState({ selectedCount: cartNo.length, totalCount: cartNo.length, }); const deliveryAllCheckTg = $('#delivery').find('#deliveryAllCheck'); deliveryAllCheckTg.prop('checked', true); deliveryAllCheckTg.attr('checked', true); } else { const pickupElement = document.getElementById('pickup'); pickupElement.querySelector('custom-cart-products').store.setState({ selectedCount: cartNo.length, totalCount: cartNo.length, }); const pickupAllCheckTg = $('#pickup').find('#pickupAllCheck'); pickupAllCheckTg.prop('checked', true); pickupAllCheckTg.attr('checked', true); } // END document.querySelector('custom-cart-order').store.setState({ selectedCount: cartNo.length, totalCount: cartNo.length, }); // [Jay] 재계산 if (utils.isSignedIn()) { const calculateParams = { queryString: { cartNo: cartNo.join(','), }, accessTokenType: 'member', }; const { result: calculationData } = await callShopApi( '/cart/subset?', 'GET', calculateParams, ); // END // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); } else { const productArr = []; for (const checkedItem of itemsEl) { // 상품 수량 const productOrderCnt = $(checkedItem) .closest('.cart-product__top') .find('.cart-product__top-content') .find('.counter__input input') .val(); const productData = { cartNo: Number(checkedItem.getAttribute('shopby-cart-no')), productNo: Number(checkedItem.getAttribute('shopby-product-no')), optionNo: Number(checkedItem.getAttribute('shopby-option-no')), orderCnt: Number(productOrderCnt), optionInputs: [], // 텍스트 옵션에 따로 추가금 안붙을 예정이라 빈배열 넣어줌 channelType: '', }; // 장바구니 번호 배열에 추가 productArr.push(productData); } const calculateParams = { queryString: { divideInvalidProducts: false, }, data: JSON.stringify(productArr), }; const { result: price } = await callShopApi( '/guest/cart?', 'POST', calculateParams, ); // [Jay] 매장픽업인 경우에는 배송비 제거 if (getUrlParam('type') === 'pickup') { price.price.totalAmt = price.price.totalAmt - price.price.totalDeliveryAmt; price.price.totalPrePaidDeliveryAmt = 0; } // [Jay] 가격 업데이트 document.querySelector('cart-order').store.setState({ price: price.price, }); document.querySelector('custom-cart-order').store.setState({ price: price.price, }); // END } }, TOGGLE_INVALID_ALL: ({ helper, target }) => { const isChecked = $(target).is(':checked'); const itemsEl = $(target) .closest('section') .parent() .find('.cart__product'); let cartNo = []; const component = document.getElementById('invalidProducts'); if (isChecked) { for (const value of itemsEl) { cartNo.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--sm').children().prop('checked', true); $(value).find('.form-check--sm').children().attr('checked', true); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 component.querySelector('custom-cart-products').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, }); $('#invalidProducts') .find('#isInvalidAllChecked') .prop('checked', true); $('#invalidProducts') .find('#isInvalidAllChecked') .attr('checked', true); } else { $(target).prop('checked', false); $(target).attr('checked', false); for (const value of itemsEl) { $(value).find('.form-check--sm').children().prop('checked', false); $(value).find('.form-check--sm').children().attr('checked', false); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 component.querySelector('custom-cart-products').store.setState({ selectedCount: 0, totalCount: itemsEl.length, }); $('#invalidProducts') .find('#isInvalidAllChecked') .prop('checked', false); $('#invalidProducts') .find('#isInvalidAllChecked') .attr('checked', false); } }, INVALID_TOGGLE_CHECKBOX_PER_CART_NO: async ({ helper, target }) => { const checkboxEl = $(target) .parents('section') .find('input[name="checked-item"]'); const checkedItems = $(target) .parents('section') .find('input[name="checked-item"]:checked'); // checked 된 요소 // 상품 선택시 선택 개수 업데이트 const invalidProductsEl = document.getElementById('invalidProducts'); invalidProductsEl.querySelector('custom-cart-products').store.setState({ selectedCount: checkedItems.length, totalCount: checkboxEl.length, }); if (checkboxEl.length === checkedItems.length) { $(target) .parents('section') .siblings() .find('#isInvalidAllChecked') .prop('checked', true); $(target) .parents('section') .siblings() .find('#isInvalidAllChecked') .attr('checked', true); } else { $(target) .parents('section') .siblings() .find('#isInvalidAllChecked') .prop('checked', false); $(target) .parents('section') .siblings() .find('#isInvalidAllChecked') .attr('checked', false); } }, TOGGLE_DELIVERY_ALL: async ({ helper, target }) => { const isChecked = $(target).is(':checked'); const itemsEl = $(target) .closest('section') .parent() .find('.cart__product'); const deliveryTg = document.getElementById('delivery'); const deliveryAllCheckTg = $('#delivery').find('#deliveryAllCheck'); let cartNo = []; if (isChecked) { for (const value of itemsEl) { cartNo.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--sm').children().prop('checked', true); $(value).find('.form-check--sm').children().attr('checked', true); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('custom-cart-order').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, }); // END // [Jay] 전체선택 카운트 변경 deliveryTg.querySelector('custom-cart-products').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, isAllChecked: true, }); // END } else { for (const value of itemsEl) { $(value).find('.form-check--sm').children().prop('checked', false); $(value).find('.form-check--sm').children().attr('checked', false); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('custom-cart-order').store.setState({ selectedCount: 0, totalCount: 0, }); // END // [Jay] 전체선택 카운트 변경 deliveryTg.querySelector('custom-cart-products').store.setState({ selectedCount: 0, totalCount: itemsEl.length, }); // END // [Jay] unchecked deliveryAllCheckTg.prop('checked', false); deliveryAllCheckTg.attr('checked', false); // END } // [Jay] 재계산 if (utils.isSignedIn()) { const calculateParams = { queryString: { cartNo: cartNo.join(','), }, accessTokenType: 'member', }; const { result: calculationData } = await callShopApi( '/cart/subset?', 'GET', calculateParams, ); // END // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); } else { const productArr = []; for (const checkedItem of itemsEl) { // 상품 수량 const productOrderCnt = $(checkedItem) .find('.cart-product__top') .find('.cart-product__top-content') .find('.counter__input input') .val(); // checked 된 상품만 가져온다. const checkboxTg = $(checkedItem).find( '.cart-product__top-checkbox input:checked', ); if (checkboxTg.length > 0) { const productData = { cartNo: Number(checkboxTg.attr('shopby-cart-no')), productNo: Number(checkboxTg.attr('shopby-product-no')), optionNo: Number(checkboxTg.attr('shopby-option-no')), orderCnt: Number(productOrderCnt), optionInputs: [], // 텍스트 옵션에 따로 추가금 안붙을 예정이라 빈배열 넣어줌 channelType: '', }; // 장바구니 번호 배열에 추가 productArr.push(productData); } } const calculateParams = { queryString: { divideInvalidProducts: false, }, data: JSON.stringify(productArr), }; const { result: price } = await callShopApi( '/guest/cart?', 'POST', calculateParams, ); // [Jay] 가격 업데이트 document.querySelector('cart-order').store.setState({ price: price.price, }); document.querySelector('custom-cart-order').store.setState({ price: price.price, }); // END } }, TOGGLE_PICKUP_ALL: async ({ helper, target }) => { const isChecked = $(target).is(':checked'); const itemsEl = $(target) .closest('section') .parent() .find('.cart__product'); const pickupTg = document.getElementById('pickup'); const pickupAllCheckTg = $('#pickup').find('#pickupAllCheck'); let cartNo = []; if (isChecked) { for (const value of itemsEl) { cartNo.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--sm').children().prop('checked', true); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('custom-cart-order').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, }); // [Jay] 전체선택 카운트 변경 pickupTg.querySelector('custom-cart-products').store.setState({ selectedCount: itemsEl.length, totalCount: itemsEl.length, isAllChecked: true, }); // END } else { for (const value of itemsEl) { $(value).find('.form-check--sm').children().prop('checked', false); } // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('custom-cart-order').store.setState({ selectedCount: 0, totalCount: 0, }); // [Jay] 전체선택 카운트 변경 pickupTg.querySelector('custom-cart-products').store.setState({ selectedCount: 0, totalCount: itemsEl.length, }); // END // [Jay] unchecked pickupAllCheckTg.prop('checked', false); pickupAllCheckTg.attr('checked', false); // END } // [Jay] 재계산 if (utils.isSignedIn()) { const calculateParams = { queryString: { cartNo: cartNo.join(','), }, accessTokenType: 'member', }; const { result: calculationData } = await callShopApi( '/cart/subset?', 'GET', calculateParams, ); // END // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); } else { const productArr = []; for (const checkedItem of itemsEl) { // 상품 수량 const productOrderCnt = $(checkedItem) .find('.cart-product__top') .find('.cart-product__top-content') .find('.counter__input input') .val(); // checked 된 상품만 가져온다. const checkboxTg = $(checkedItem).find( '.cart-product__top-checkbox input:checked', ); if (checkboxTg.length > 0) { const productData = { cartNo: Number(checkboxTg.attr('shopby-cart-no')), productNo: Number(checkboxTg.attr('shopby-product-no')), optionNo: Number(checkboxTg.attr('shopby-option-no')), orderCnt: Number(productOrderCnt), optionInputs: [], // 텍스트 옵션에 따로 추가금 안붙을 예정이라 빈배열 넣어줌 channelType: '', }; // 장바구니 번호 배열에 추가 productArr.push(productData); } } const calculateParams = { queryString: { divideInvalidProducts: false, }, data: JSON.stringify(productArr), }; const { result: price } = await callShopApi( '/guest/cart?', 'POST', calculateParams, ); // [Jay] 매장픽업인 경우에는 배송비 제거 if (getUrlParam('type') === 'pickup') { price.price.totalAmt = price.price.totalAmt - price.price.totalDeliveryAmt; price.price.totalPrePaidDeliveryAmt = 0; } // [Jay] 가격 업데이트 document.querySelector('cart-order').store.setState({ price: price.price, }); document.querySelector('custom-cart-order').store.setState({ price: price.price, }); // END } }, 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"]'); let cartNoArr = []; const checkedItems = $(target) .parents('section') .find('input[name="checked-item"]:checked'); // checked 된 요소 const type = getUrlParam('type'); for (const checkedItem of checkedItems) { // 장바구니 번호 배열에 추가 cartNoArr.push(checkedItem.getAttribute('shopby-cart-no')); } // [Jay] 재계산 if (utils.isSignedIn()) { const calculateParams = { queryString: { cartNo: cartNoArr.join(','), }, accessTokenType: 'member', }; const { result: calculationData } = await callShopApi( '/cart/subset?', 'GET', calculateParams, ); // END // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); // END } else { const productArr = []; for (const checkedItem of checkedItems) { // 상품 수량 const productOrderCnt = $(checkedItem) .closest('.cart-product__top') .find('.cart-product__top-content') .find('.counter__input input') .val(); const productData = { cartNo: Number(checkedItem.getAttribute('shopby-cart-no')), productNo: Number(checkedItem.getAttribute('shopby-product-no')), optionNo: Number(checkedItem.getAttribute('shopby-option-no')), orderCnt: Number(productOrderCnt), optionInputs: [], // 텍스트 옵션에 따로 추가금 안붙을 예정이라 빈배열 넣어줌 channelType: '', }; // 장바구니 번호 배열에 추가 productArr.push(productData); } const calculateParams = { queryString: { divideInvalidProducts: false, }, data: JSON.stringify(productArr), }; const { result: price } = await callShopApi( '/guest/cart?', 'POST', calculateParams, ); // [Jay] 매장픽업인 경우에는 배송비 제거 if (getUrlParam('type') === 'pickup') { price.price.totalAmt = price.price.totalAmt - price.price.totalDeliveryAmt; price.price.totalPrePaidDeliveryAmt = 0; } // [Jay] 가격 업데이트 document.querySelector('cart-order').store.setState({ price: price.price, }); document.querySelector('custom-cart-order').store.setState({ price: price.price, }); // END } let productCount = $('#delivery').find('.cart__product').length; // 상품 선택시 선택 개수 업데이트 document.querySelector('custom-cart-products').store.setState({ selectedCount: cartNoArr.length, totalCount: productCount, }); document.querySelector('custom-cart-order').store.setState({ selectedCount: cartNoArr.length, totalCount: productCount, }); if (checkboxElCnt.length === checkedItems.length) { if (type === 'pickup') { $(target) .parents('section') .siblings() .find('#pickupAllCheck') .prop('checked', true); $(target) .parents('section') .siblings() .find('#pickupAllCheck') .attr('checked', true); } else { $(target) .parents('section') .siblings() .find('#deliveryAllCheck') .prop('checked', true); $(target) .parents('section') .siblings() .find('#deliveryAllCheck') .attr('checked', true); } } else { if (type === 'pickup') { $(target) .parents('section') .siblings() .find('#pickupAllCheck') .prop('checked', false); $(target) .parents('section') .siblings() .find('#pickupAllCheck') .attr('checked', false); } else { $(target) .parents('section') .siblings() .find('#deliveryAllCheck') .prop('checked', false); $(target) .parents('section') .siblings() .find('#deliveryAllCheck') .attr('checked', false); } } // END }, DELETE_SELECTED_ITEMS: ({ helper, target }) => { const selectedCount = Number( target.getAttribute(ELEMENT_SELECTOR.SELECTED_COUNT), ); const checkedCartNos = target .getAttribute(ELEMENT_SELECTOR.CHECKED_CART_NOS_AS_STRING) ?.split?.(',') ?.map(Number) ?? []; if (!selectedCount) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'CAUTION', message: `선택하신 상품이 없습니다.`, }); return; } 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(); }, }); }, CUSTOM_DELETE_SELECTED_ITEMS: ({ helper, target }) => { const selectedProducts = $(target) .closest('section') .parent() .find('.cart__products') .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__product'); 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; } EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: `선택하신 ${checkedCartNos.length}개의 상품을 삭제하시겠습니까?`, confirmLabel: '삭제', onConfirm: async () => { const type = url.searchParams.get('type'); // [Jay] 매장픽업 상품 삭제시에만 스피너 추가 if (type === 'pickup') { const customCartProducts = $(target) .closest('section') .parent() .parent(); 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); } // END EventManager.fire('UPDATE_CART_PRODUCT'); await helper.cartAction.deleteCartNos(checkedCartNos); helper.cartAction.fetchCartDetail(); }, }); }, ORDER: async ({ 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__product'); 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-product__top-content') .find('.cart-product__count-wrap') .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; } const { data: { orderSheetNo }, } = await helper.orderSheetAction.makeOrderSheet({ cartNos: checkedCartNos, products: checkedProducts, }); 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(); } }, }; async function reCalculate(cartNoArr) { // [Jay] 재계산 const calculateParams = { queryString: { cartNo: cartNoArr.join(','), }, accessTokenType: 'member', }; const { result: calculationData } = await callShopApi( '/cart/subset?', 'GET', calculateParams, ); // END // [Jay] 가격 업데이트 // [Jay] 전체선택한 배송타입에 따른 상품수량 상태값 업데이트 document.querySelector('cart-order').store.setState({ price: calculationData.price, selectedCount: cartNoArr.length, totalCount: cartNoArr.length, }); // END // [Jay] 가격 업데이트 ShopbySkin.EventManager.fire( 'QUERY_CART_PAYMENT_INFO', calculationData.price, ); } const clickEventListener = ({ target }) => { const actionType = target.getAttribute(ELEMENT_SELECTOR.ACTION); $(target).addClass('active').siblings().removeClass('active'); 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: getPlatform(), }); // 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); }); // END EventManager.on( 'ON_UPDATED_CART_PRODUCT', cartProductsEl?.hideLoadingSpinner, ); EventManager.on('QUERY_CART_CHECKED_PRODUCTS', () => { const type = url.searchParams.get('type'); let itemsEl; // [Jay] 배송타입별 상품 개수 상태값 변경 및 전체선택 checked 처리 if (type === 'delivery') { itemsEl = $('#delivery') .find('.cart__product') .find('input[name="checked-item"]'); $('#deliveryType').addClass('active').siblings().removeClass('active'); // [Jay] 선택된 장바구니 번호 추출 const cartNo = []; for (const value of itemsEl) { cartNo.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--sm').children().prop('checked', true); } // END const deliveryElement = document.getElementById('delivery'); deliveryElement.querySelector('custom-cart-products').store.setState({ selectedCount: cartNo.length, totalCount: cartNo.length, }); const deliveryAllCheckTg = $('#delivery').find('#deliveryAllCheck'); deliveryAllCheckTg.prop('checked', true); deliveryAllCheckTg.attr('checked', true); } else { itemsEl = $('#pickup') .find('.cart__product') .find('input[name="checked-item"]'); $('#pickupType').addClass('active').siblings().removeClass('active'); // [Jay] 선택된 장바구니 번호 추출 const cartNo = []; for (const value of itemsEl) { cartNo.push(value.getAttribute('shopby-cart-no')); $(value).find('.form-check--sm').children().prop('checked', true); } // END const pickupElement = document.getElementById('pickup'); pickupElement.querySelector('custom-cart-products').store.setState({ selectedCount: cartNo.length, totalCount: cartNo.length, }); const pickupAllCheckTg = $('#pickup').find('#pickupAllCheck'); pickupAllCheckTg.prop('checked', true); pickupAllCheckTg.attr('checked', true); } }); EventManager.on( 'QUERY_CART_CHECKED_PRODUCTS', naverPay.handleReceiverCheckedProducts, ); EventManager.on( 'QUERY_CART_CHECKING_STATUS_PER_CART_NO', naverPay.handleReceiverCheckingStatus, ); EventManager.on('PAGE_LOAD_COMPLETED', (commonData) => { cartHelper.cartAction.fetchCartDetail(); naverPay.setNaverPayAction(commonData); }); })();