(() => {
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: 'cart-products-v2',
CHECKBOX_PER_DELIVERY_GROUP_SLOT: '[slot="checkboxPerDeliveryGroup"]',
CHECKBOX_PER_CART_NO_SLOT: '[slot="checkboxPerCartNo"]',
};
const { pageHelper, EventManager, actions, utils } = ShopbySkin;
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',
});
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 handleGiftOrder = async ({ helper, cartNos, products }) => {
const {
data: { orderSheetNo },
} = await helper.orderSheetAction.makeOrderSheet({
cartNos,
products,
});
const ordersheetUri = `/pages/order/gift-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_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,
});
},
DELETE_SELECTED_ITEMS: async ({ 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;
}
const { data } = await helper.cartAction.deletableRequiredOption();
if (!data) {
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();
},
});
},
ORDER: ({ helper }) => {
const { data: checkedCartNos } = helper.cartAction.fetchCheckedCartNos();
const { data: checkedProducts } =
helper.cartAction.fetchCheckedProducts();
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,
});
},
GIFT_ORDER: ({ helper }) => {
const { data: checkedCartNos } = helper.cartAction.fetchCheckedCartNos();
const { data: checkedProducts } =
helper.cartAction.fetchCheckedProducts();
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;
}
handleGiftOrder({
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;
}
const { data } = await helper.cartAction.fetchAllValidProducts();
const cartNos = data.map(({ cartNo }) => cartNo);
handleOrder({
cartNos,
products: data,
helper,
});
},
};
const clickEventListener = ({ target }) => {
const actionEl = target?.closest?.(`[${ELEMENT_SELECTOR.ACTION}]`);
const actionType = actionEl?.getAttribute?.(ELEMENT_SELECTOR.ACTION);
if (!actionType) {
return;
}
CLICK_EVENT_HANDLER_MAP[actionType]?.({
target: actionEl,
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);
EventManager.on(
'ON_UPDATED_CART_PRODUCT',
cartProductsEl?.hideLoadingSpinner,
);
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);
// 외부스크립트 등록 기능. 삭제금지
ShopbyExternalScript?.setPageScriptType('CART');
});
EventManager.on('QUERY_CART_DETAIL', (cart) => {
// 외부스크립트 등록 기능. 삭제금지
ShopbyExternalScript?.setGlobalObjectSb({ cart });
});
})();