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