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