🕐 커밋 시간: 2025. 11. 24. 09:24:08 📊 변경 통계: • 총 파일: 5개 • 추가: +156줄 • 삭제: -111줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/actions/empActions.js ~ com.twin.app.shoptime/src/hooks/useFocusHistory/useFocusHistory.js ~ com.twin.app.shoptime/src/lunaSend/common.js ~ com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/hooks/useFocusHistory/useFocusHistory.js (javascript): ✅ Added: dwarn(), derror() 🔄 Modified: getOrCreateGlobalBuffer() 📄 com.twin.app.shoptime/src/lunaSend/common.js (javascript): ✅ Added: dwarn(), derror() 📄 com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx (javascript): ✅ Added: dwarn(), derror() 🔧 주요 변경 내용: • 핵심 비즈니스 로직 개선
870 lines
29 KiB
JavaScript
870 lines
29 KiB
JavaScript
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
|
|
import { Job } from '@enact/core/util';
|
|
import Spotlight from '@enact/spotlight';
|
|
|
|
import { getCheckoutTotalAmt, resetCheckoutData } from '../../actions/checkoutActions';
|
|
import { setHidePopup, setShowPopup } from '../../actions/commonActions';
|
|
import { getShoptimeTerms } from '../../actions/empActions';
|
|
import {
|
|
sendLogCheckOutBtnClick,
|
|
sendLogGNB,
|
|
sendLogMyInfoEdit,
|
|
sendLogPaymentEntry,
|
|
sendLogTotalRecommend,
|
|
} from '../../actions/logActions';
|
|
import { popPanel, updatePanel } from '../../actions/panelActions';
|
|
import TBody from '../../components/TBody/TBody';
|
|
import TButton from '../../components/TButton/TButton';
|
|
import TButtonScroller from '../../components/TButtonScroller/TButtonScroller';
|
|
import TButtonTab from '../../components/TButtonTab/TButtonTab';
|
|
import TFullPopup from '../../components/TFullPopup/TFullPopup';
|
|
import THeader from '../../components/THeader/THeader';
|
|
import TPanel from '../../components/TPanel/TPanel';
|
|
import TPopUp from '../../components/TPopUp/TPopUp';
|
|
import TQRCode from '../../components/TQRCode/TQRCode';
|
|
import useScrollTo from '../../hooks/useScrollTo';
|
|
import { BUYNOW_CONFIG } from '../../utils/BuyNowConfig';
|
|
import * as Config from '../../utils/Config';
|
|
import { $L, scaleH, scaleW } from '../../utils/helperMethods';
|
|
import {
|
|
getSafeCurrencyInfo,
|
|
getSafeFirstProduct,
|
|
normalizeProductDataForDisplay,
|
|
} from '../../utils/mockDataSafetyUtils';
|
|
import { SpotlightIds } from '../../utils/SpotlightIds';
|
|
import css from './CheckOutPanel.module.less';
|
|
import PinCodeInput from './components/PinCodeInput';
|
|
import FixedSideBar from './container/FixedSideBar';
|
|
import InformationContainer from './container/InformationContainer';
|
|
import InformationContainerMock from './container/InformationContainerMock';
|
|
import OrderItemsSideBar from './container/OrderItemsSideBar';
|
|
import SummaryContainerMock from './container/SummaryContainerMock';
|
|
import SummaryContainer from './container/SummaryCotainer';
|
|
|
|
export default function CheckOutPanel({ panelInfo }) {
|
|
// DEBUG_LOG 설정 - 이 값이 true일 때만 console.log가 실행됨
|
|
const DEBUG_LOG = false; // 계속 활성화하여 디버깅
|
|
|
|
// console.log 오버라이드를 위한 ref
|
|
const originalConsoleLog = useRef();
|
|
|
|
// 컴포넌트 마운트 시 console.log 오버라이드 및 PlayerPanel 충돌 방지
|
|
useEffect(() => {
|
|
// 원래 함수 저장
|
|
originalConsoleLog.current = console.log;
|
|
|
|
// console.log 오버라이드 - 이 컴포넌트에서만 DEBUG_LOG 조건을 체크하도록 설정
|
|
console.log = (...args) => {
|
|
if (DEBUG_LOG) {
|
|
originalConsoleLog.current.apply(console, args);
|
|
}
|
|
};
|
|
|
|
console.log(
|
|
'%c[BuyOption][CheckOutPanel] ▶️ Component mounted START',
|
|
'background: blue; color: white; font-weight: bold; padding: 5px;'
|
|
);
|
|
console.log(
|
|
'%c🚨🚨🚨 CHECKOUT PANEL PANELINFO ANALYSIS 🚨🚨🚨',
|
|
'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;'
|
|
);
|
|
console.log('%cpanelInfo:', 'background: yellow; color: black; padding: 3px;', panelInfo);
|
|
console.log(
|
|
'%cpanelInfo.isFromCart:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.isFromCart
|
|
);
|
|
console.log(
|
|
'%cpanelInfo.fromCartPanel:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.fromCartPanel
|
|
);
|
|
console.log(
|
|
'%cpanelInfo.cartItems:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.cartItems
|
|
);
|
|
console.log(
|
|
'%cpanelInfo.cartItems type:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
typeof panelInfo?.cartItems
|
|
);
|
|
console.log(
|
|
'%cpanelInfo.cartItems length:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.cartItems?.length
|
|
);
|
|
console.log(
|
|
'%cpanelInfo.productInfo:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.productInfo
|
|
);
|
|
console.log(
|
|
'%cpanelInfo.logInfo:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.logInfo
|
|
);
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] Current panels:',
|
|
panels?.map((p) => ({ name: p.name, hasModal: !!p.panelInfo?.modal }))
|
|
);
|
|
|
|
// PlayerPanel 충돌 방지: PlayerPanel이 있고 modal 상태면 비활성화
|
|
const playerPanelIndex = panels?.findIndex(
|
|
(p) =>
|
|
p.name === Config.panel_names.PLAYER_PANEL ||
|
|
p.name === Config.panel_names.PLAYER_PANEL_NEW ||
|
|
p.name === Config.panel_names.MEDIA_PANEL
|
|
);
|
|
|
|
if (playerPanelIndex >= 0) {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] 🚨 PlayerPanel/MediaPanel detected at index:',
|
|
playerPanelIndex
|
|
);
|
|
console.log('[BuyOption][CheckOutPanel] PlayerPanel info:', panels[playerPanelIndex]);
|
|
|
|
// PlayerPanel/MediaPanel 상태를 비활성화하여 CheckOutPanel과의 충돌 방지
|
|
if (panels[playerPanelIndex].panelInfo?.modal) {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] 🔄 Disabling modal PlayerPanel to prevent conflicts'
|
|
);
|
|
// 필요하다면 여기서 PlayerPanel 상태를 비활성화하는 액션을 디스패치할 수 있음
|
|
// dispatch(updatePanel({
|
|
// name: panels[playerPanelIndex].name,
|
|
// panelInfo: { ...panels[playerPanelIndex].panelInfo, isActive: false }
|
|
// }));
|
|
}
|
|
}
|
|
|
|
return () => {
|
|
// console.log 원래 함수로 복원
|
|
console.log = originalConsoleLog.current;
|
|
console.log('[BuyOption][CheckOutPanel] 🔄 Component unmounting - cleaning up');
|
|
};
|
|
}, [panels, panelInfo]); // panels와 panelInfo를 의존성에 추가
|
|
const dispatch = useDispatch();
|
|
const panels = useSelector((state) => state.panels.panels);
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] panels:',
|
|
panels?.map((p) => p.name)
|
|
);
|
|
const { userNumber } = useSelector((state) => state.common.appStatus.loginUserData);
|
|
const reduxProductData = useSelector((state) => state.checkout?.checkoutData.productList);
|
|
const infoForCheckoutData = useSelector((state) => state.checkout?.infoForCheckoutData);
|
|
const selectedCoupons = useSelector((state) => state.checkout.selectedCoupons);
|
|
const empTermsData = useSelector((state) => state.emp.empTermsData.terms);
|
|
const { popupVisible, activePopup } = useSelector((state) => state.common.popup);
|
|
const popup = useSelector((state) => state.common.popup);
|
|
const cartSelectInfo = useSelector((state) => state.cart.selectCart.checkedItems);
|
|
|
|
// Mock Mode: panelInfo.productInfo 또는 Redux에서 상품 데이터 사용
|
|
const productData = BUYNOW_CONFIG.isMockMode()
|
|
? (() => {
|
|
console.log(
|
|
'%c🚨🚨🚨 MOCK MODE DATA SELECTION START 🚨🚨🚨',
|
|
'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;'
|
|
);
|
|
console.log(
|
|
'%cisFromCart condition check:',
|
|
'background: yellow; color: black; padding: 3px;'
|
|
);
|
|
console.log(
|
|
'%c - panelInfo?.isFromCart:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.isFromCart
|
|
);
|
|
console.log(
|
|
'%c - panelInfo?.cartItems exists:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
!!panelInfo?.cartItems
|
|
);
|
|
console.log(
|
|
'%c - Array.isArray(panelInfo?.cartItems):',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
Array.isArray(panelInfo?.cartItems)
|
|
);
|
|
console.log(
|
|
'%c - panelInfo?.cartItems.length > 0:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
panelInfo?.cartItems?.length > 0
|
|
);
|
|
|
|
// ✅ 1순위: CartPanel에서 전달된 cartItems (전체 카트 데이터)
|
|
if (
|
|
panelInfo?.isFromCart &&
|
|
panelInfo?.cartItems &&
|
|
Array.isArray(panelInfo.cartItems) &&
|
|
panelInfo.cartItems.length > 0
|
|
) {
|
|
console.log(
|
|
'%c✅ SUCCESS! Using cartItems from CartPanel (multi-product) ✅',
|
|
'background: green; color: white; font-weight: bold; font-size: 14px; padding: 5px;'
|
|
);
|
|
console.log(
|
|
'%ccartItems:',
|
|
'background: green; color: white; padding: 3px;',
|
|
panelInfo.cartItems
|
|
);
|
|
console.log(
|
|
'%ccartItems count:',
|
|
'background: green; color: white; padding: 3px;',
|
|
panelInfo.cartItems.length
|
|
);
|
|
return panelInfo.cartItems;
|
|
}
|
|
|
|
console.log(
|
|
'%c❌ FAILED! isFromCart condition FAILED ❌',
|
|
'background: red; color: white; font-weight: bold; font-size: 14px; padding: 5px;'
|
|
);
|
|
console.log(
|
|
'%cTrying next condition - productInfo check...',
|
|
'background: red; color: white; padding: 3px;'
|
|
);
|
|
|
|
// 2순위: BuyOption에서 전달된 productInfo (단일 상품)
|
|
if (panelInfo?.productInfo) {
|
|
console.log(
|
|
'%c[BuyOption][CheckOutPanel] ✅ Mock Mode - Using panelInfo.productInfo (single product):',
|
|
'background: green; color: white; font-weight: bold; padding: 5px;',
|
|
panelInfo.productInfo
|
|
);
|
|
return [panelInfo.productInfo];
|
|
}
|
|
|
|
// 3순위: Redux에서 가져온 상품 데이터
|
|
if (reduxProductData && Array.isArray(reduxProductData) && reduxProductData.length > 0) {
|
|
console.log(
|
|
'%c[BuyOption][CheckOutPanel] ✅ Mock Mode - Using reduxProductData:',
|
|
'background: green; color: white; font-weight: bold; padding: 5px;',
|
|
'count=' + reduxProductData.length
|
|
);
|
|
return reduxProductData;
|
|
}
|
|
|
|
// 4순위: 기본 Hardcoded Mock 데이터 (최후의 fallback)
|
|
console.error(
|
|
'%c[BuyOption][CheckOutPanel] ⚠️ Mock Mode - Using fallback mock data:',
|
|
'background: orange; color: white; font-weight: bold; padding: 5px;',
|
|
'panelInfo=',
|
|
panelInfo,
|
|
'reduxProductData=',
|
|
reduxProductData
|
|
);
|
|
return [
|
|
{
|
|
prdtId: 'MOCK_PRODUCT_1',
|
|
prdtNm: 'Mock Product',
|
|
patnrId: '1',
|
|
patncNm: 'Partner',
|
|
prodQty: 1,
|
|
finalPrice: 99999,
|
|
origPrice: 99999,
|
|
discountPrice: 99999,
|
|
currSign: '$',
|
|
currSignLoc: 'left',
|
|
},
|
|
];
|
|
})()
|
|
: reduxProductData;
|
|
|
|
console.log(
|
|
'%c🚨🚨🚨 FINAL PRODUCT DATA RESULT 🚨🚨🚨',
|
|
'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;'
|
|
);
|
|
console.log(
|
|
'%cisMockMode:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
BUYNOW_CONFIG.isMockMode()
|
|
);
|
|
console.log(
|
|
'%cproductData loaded:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
productData && productData.length,
|
|
'items'
|
|
);
|
|
console.log(
|
|
'%cproductData[0].prdtId:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
productData?.[0]?.prdtId
|
|
);
|
|
console.log(
|
|
'%cproductData length:',
|
|
'background: yellow; color: black; padding: 3px;',
|
|
productData?.length || 0
|
|
);
|
|
console.log('%cproductData:', 'background: yellow; color: black; padding: 3px;', productData);
|
|
|
|
// 표시용으로 모든 상품 데이터 정규화 (없는 필드는 안전한 기본값으로)
|
|
// Mock 모드에서는 항상 정규화, API 모드에서는 그대로 사용
|
|
const normalizedProductData =
|
|
productData?.map((prod) => normalizeProductDataForDisplay(prod)) || [];
|
|
const safeProductData = BUYNOW_CONFIG.isMockMode() ? normalizedProductData : productData;
|
|
|
|
console.log('[BuyOption][CheckOutPanel] productData (normalized):', normalizedProductData);
|
|
console.log('[BuyOption][CheckOutPanel] safeProductData (final):', safeProductData);
|
|
|
|
// 첫 번째 상품 정보로 통화 정보 추출
|
|
const firstProduct = getSafeFirstProduct(safeProductData);
|
|
const { currSign, currSignLoc } = firstProduct
|
|
? getSafeCurrencyInfo(firstProduct)
|
|
: { currSign: '$', currSignLoc: 'left' };
|
|
console.log('[BuyOption][CheckOutPanel] firstProduct:', firstProduct);
|
|
console.log('[BuyOption][CheckOutPanel] currSign:', currSign, 'currSignLoc:', currSignLoc);
|
|
|
|
const orderItemsCount = useMemo(() => {
|
|
const normalizeQty = (value) => {
|
|
const numeric = Number(value);
|
|
if (Number.isFinite(numeric) && numeric > 0) {
|
|
return numeric;
|
|
}
|
|
return 1;
|
|
};
|
|
|
|
if (Array.isArray(productData) && productData.length > 0) {
|
|
return productData.reduce((sum, item) => {
|
|
if (!item) {
|
|
return sum + 1;
|
|
}
|
|
const qty = item.prodQty ?? item.qty ?? 1;
|
|
return sum + normalizeQty(qty);
|
|
}, 0);
|
|
}
|
|
|
|
if (panelInfo?.productInfo) {
|
|
const qty = panelInfo.productInfo?.prodQty ?? panelInfo.productInfo?.qty ?? 1;
|
|
return normalizeQty(qty);
|
|
}
|
|
|
|
return 0;
|
|
}, [productData, panelInfo]);
|
|
|
|
const [orderSideBarOpen, setOrderSideBarOpen] = useState(false);
|
|
const [offerSideBarOpen, setOfferSideBarOpen] = useState(false);
|
|
const [placeOrderPopup, setPlaceOrderPopup] = useState(false);
|
|
const [currentTerms, setCurrentTerms] = useState(null);
|
|
const [tabList, setTabList] = useState([]);
|
|
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
|
|
const [resetScroll, setResetScroll] = useState(false);
|
|
const [spotlightDisalbed, setSpotlightDisabled] = useState(false);
|
|
const [isOrderSuccessful, setIsOrderSuccessful] = useState(false);
|
|
|
|
const isMounted = useRef(true);
|
|
|
|
const { getScrollTo: getScrollToBody, scrollTop: scrollTopBody } = useScrollTo();
|
|
|
|
const spotJob = useRef(new Job((func) => func(), 0));
|
|
|
|
useEffect(() => {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] sendLogGNB useEffect - isOrderSuccessful:',
|
|
isOrderSuccessful
|
|
);
|
|
let nowMenu;
|
|
|
|
if (isOrderSuccessful) {
|
|
console.log('[BuyOption][CheckOutPanel] Order successful, returning early');
|
|
return;
|
|
}
|
|
//
|
|
else if (!placeOrderPopup || popupVisible) {
|
|
nowMenu = Config.LOG_MENU.CHECKOUT;
|
|
}
|
|
//
|
|
else if (placeOrderPopup) {
|
|
nowMenu = Config.LOG_MENU.CHECKOUT_PIN_CODE;
|
|
}
|
|
|
|
console.log('[BuyOption][CheckOutPanel] Dispatching sendLogGNB with menu:', nowMenu);
|
|
dispatch(sendLogGNB(nowMenu));
|
|
}, [isOrderSuccessful, placeOrderPopup, popupVisible]);
|
|
|
|
useEffect(() => {
|
|
console.log('[BuyOption][CheckOutPanel] isMounted useEffect');
|
|
isMounted.current = true;
|
|
|
|
return () => {
|
|
console.log('[BuyOption][CheckOutPanel] isMounted cleanup - component unmounting');
|
|
isMounted.current = false;
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
console.log('[BuyOption][CheckOutPanel] getShoptimeTerms useEffect');
|
|
|
|
// Mock Mode: API 호출 스킵
|
|
if (!BUYNOW_CONFIG.isMockMode()) {
|
|
dispatch(getShoptimeTerms());
|
|
} else {
|
|
console.log('[BuyOption][CheckOutPanel] Mock Mode - Skipping getShoptimeTerms');
|
|
}
|
|
}, [dispatch]);
|
|
|
|
function totalAmtValidate(response) {
|
|
if (response) {
|
|
if (response.retCode !== 0) {
|
|
if (response.retMsg) {
|
|
dispatch(
|
|
setShowPopup(Config.ACTIVE_POPUP.errorPopup, {
|
|
text: response.retMsg,
|
|
})
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
console.log('[BuyOption][CheckOutPanel] checkout total amount useEffect triggered');
|
|
console.log('[BuyOption][CheckOutPanel] infoForCheckoutData:', infoForCheckoutData);
|
|
console.log('[BuyOption][CheckOutPanel] productData length:', productData?.length);
|
|
|
|
// Mock Mode: API 호출 스킵
|
|
if (BUYNOW_CONFIG.isMockMode()) {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] Mock Mode - Skipping checkout total amount calculation'
|
|
);
|
|
return;
|
|
}
|
|
|
|
console.log('[BuyOption][CheckOutPanel] API Mode - calling getCheckoutTotalAmt');
|
|
// API Mode: 기존 로직 유지
|
|
|
|
// 🔍 조건 디버깅
|
|
console.log('[BuyOption][CheckOutPanel] 🔍 getCheckoutTotalAmt conditions:', {
|
|
hasInfoForCheckoutData: !!infoForCheckoutData,
|
|
hasProductData: !!productData,
|
|
dlvrAddrSno: infoForCheckoutData?.dlvrAddrSno,
|
|
bilAddrSno: infoForCheckoutData?.bilAddrSno,
|
|
fullInfoForCheckoutData: infoForCheckoutData,
|
|
});
|
|
|
|
if (infoForCheckoutData && productData) {
|
|
const orderProductCoupontUse = Object.keys(selectedCoupons).map((productId) => {
|
|
const { cpnCdSeq, cpnSno, prdtId } = selectedCoupons[productId];
|
|
const product = productData.find((prod) => prod.prdtId === prdtId);
|
|
|
|
return {
|
|
cpnCdSeq,
|
|
cpnSno,
|
|
prdtId,
|
|
prodSno: product?.prodSno,
|
|
patnrId: product?.patnrId,
|
|
};
|
|
});
|
|
|
|
if (
|
|
infoForCheckoutData &&
|
|
infoForCheckoutData.dlvrAddrSno &&
|
|
infoForCheckoutData.bilAddrSno
|
|
) {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] ✅ All conditions met - Calling getCheckoutTotalAmt'
|
|
);
|
|
dispatch(
|
|
getCheckoutTotalAmt(
|
|
{
|
|
mbrNo: userNumber,
|
|
dirPurcSelYn: cartSelectInfo.length > 0 ? 'N' : 'Y',
|
|
bilAddrSno: infoForCheckoutData.bilAddrSno,
|
|
dlvrAddrSno: infoForCheckoutData.dlvrAddrSno,
|
|
isPageLoading: 'Y',
|
|
orderProductCoupontUse,
|
|
},
|
|
totalAmtValidate
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}, [dispatch, infoForCheckoutData, productData, userNumber, selectedCoupons]);
|
|
|
|
useEffect(() => {
|
|
console.log(
|
|
'[CheckOutPanel] empTermsData useEffect - empTermsData length:',
|
|
empTermsData?.length
|
|
);
|
|
const newTabList = [];
|
|
|
|
if (empTermsData) {
|
|
empTermsData.forEach((term) => {
|
|
newTabList.push(term.termsTypeName);
|
|
});
|
|
|
|
console.log('[BuyOption][CheckOutPanel] Setting tabList:', newTabList);
|
|
setTabList(newTabList);
|
|
}
|
|
}, [empTermsData]);
|
|
|
|
useEffect(() => {
|
|
console.log('[BuyOption][CheckOutPanel] cleanup useEffect - setting up cleanup');
|
|
return () => {
|
|
console.log('[BuyOption][CheckOutPanel] cleanup useEffect - calling resetCheckoutData');
|
|
|
|
// API Mode에서만 checkout data 초기화 필요
|
|
// Mock Mode에서는 popup 상태만 정리 (Redux checkout state 유지)
|
|
if (!BUYNOW_CONFIG.isMockMode()) {
|
|
dispatch(resetCheckoutData());
|
|
} else {
|
|
console.log('[BuyOption][CheckOutPanel] Mock Mode - Cleaning up popup state only');
|
|
}
|
|
|
|
dispatch(setHidePopup());
|
|
};
|
|
}, [dispatch]);
|
|
|
|
useEffect(() => {
|
|
const spotJobValue = spotJob.current;
|
|
|
|
spotJobValue.start(() => {
|
|
if (!activePopup) {
|
|
Spotlight.focus('spotlightId_placeOrderBtn');
|
|
} else if (activePopup === Config.ACTIVE_POPUP.errorPopup) {
|
|
Spotlight.focus(SpotlightIds.TPOPUP);
|
|
}
|
|
});
|
|
|
|
return () => {
|
|
spotJobValue.stop();
|
|
};
|
|
}, [activePopup]);
|
|
|
|
const onBackClick = useCallback(() => {
|
|
console.log('[CheckOutPanel] onBackClick - Sending reload signal to DetailPanel');
|
|
|
|
// DetailPanel에 재시작 신호 전달
|
|
dispatch(
|
|
updatePanel({
|
|
name: Config.panel_names.DETAIL_PANEL,
|
|
panelInfo: {
|
|
shouldReload: true,
|
|
},
|
|
})
|
|
);
|
|
|
|
// CheckOutPanel 제거
|
|
dispatch(popPanel(Config.panel_names.CHECKOUT_PANEL));
|
|
|
|
console.log('[CheckOutPanel] popPanel dispatched for CHECKOUT_PANEL');
|
|
}, [dispatch, panels]);
|
|
|
|
const toggleOrderSideBar = useCallback(() => {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] toggleOrderSideBar called - current state:',
|
|
orderSideBarOpen
|
|
);
|
|
if (!orderSideBarOpen) {
|
|
dispatch(sendLogCheckOutBtnClick({ btnNm: 'ORDER ITEMS' }));
|
|
dispatch(
|
|
sendLogTotalRecommend({
|
|
buttonTitle: 'ORDER ITEMS',
|
|
buttonId: 'checkout_order_items_view',
|
|
contextName: Config.LOG_CONTEXT_NAME.CHECKOUT,
|
|
messageId: Config.LOG_MESSAGE_ID.BUTTONCLICK,
|
|
})
|
|
);
|
|
}
|
|
|
|
setOrderSideBarOpen((prev) => !prev);
|
|
setTimeout(() => Spotlight.focus(), 0);
|
|
}, [orderSideBarOpen, dispatch]);
|
|
|
|
const toggleOfferSideBar = useCallback(() => {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] toggleOfferSideBar called - current state:',
|
|
offerSideBarOpen
|
|
);
|
|
if (!offerSideBarOpen) {
|
|
dispatch(sendLogCheckOutBtnClick({ btnNm: 'OFFERS & PROMOTION' }));
|
|
dispatch(
|
|
sendLogTotalRecommend({
|
|
buttonTitle: 'OFFERS & PROMOTION',
|
|
buttonId: 'checkout_offers_promotion_view',
|
|
contextName: Config.LOG_CONTEXT_NAME.CHECKOUT,
|
|
messageId: Config.LOG_MESSAGE_ID.BUTTONCLICK,
|
|
})
|
|
);
|
|
}
|
|
|
|
setOfferSideBarOpen((prev) => !prev);
|
|
setTimeout(() => Spotlight.focus(), 0);
|
|
}, [offerSideBarOpen, dispatch]);
|
|
|
|
const onClosePopup = useCallback(() => {
|
|
console.log('[BuyOption][CheckOutPanel] onClosePopup called');
|
|
setPlaceOrderPopup(false);
|
|
setTimeout(() => Spotlight.focus(), 0);
|
|
}, []);
|
|
|
|
const onCloseTermsPopup = useCallback(() => {
|
|
console.log('[BuyOption][CheckOutPanel] onCloseTermsPopup called');
|
|
dispatch(setHidePopup());
|
|
}, [dispatch]);
|
|
|
|
const handlePopPanel = useCallback(() => {
|
|
console.log(
|
|
'[BuyOption][CheckOutPanel] handlePopPanel called - dispatching setHidePopup and popPanel'
|
|
);
|
|
dispatch(setHidePopup());
|
|
dispatch(popPanel());
|
|
}, [dispatch]);
|
|
|
|
const handleTermsClick = useCallback(
|
|
(termsID) => {
|
|
console.log('[BuyOption][CheckOutPanel] handleTermsClick called with termsID:', termsID);
|
|
if (empTermsData) {
|
|
const selectedTerms = empTermsData.find((term) => term.termsID === termsID);
|
|
|
|
console.log('[BuyOption][CheckOutPanel] Selected terms:', selectedTerms?.termsTypeName);
|
|
dispatch(
|
|
sendLogTotalRecommend({
|
|
buttonTitle: selectedTerms.termsTypeName,
|
|
buttonId: `checkout_terms_${selectedTerms.termsTypeName
|
|
.toLowerCase()
|
|
.replace(/\s+/g, '_')}`,
|
|
contextName: Config.LOG_CONTEXT_NAME.CHECKOUT,
|
|
messageId: Config.LOG_MESSAGE_ID.BUTTONCLICK,
|
|
})
|
|
);
|
|
setCurrentTerms(selectedTerms);
|
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.termsPopup));
|
|
Spotlight.focus('spotlightId_TbuttonScrollerDown');
|
|
const selectedIndex = empTermsData.findIndex((term) => term.termsID === termsID);
|
|
|
|
setSelectedTabIndex(selectedIndex);
|
|
setResetScroll(true);
|
|
}
|
|
},
|
|
[empTermsData, dispatch]
|
|
);
|
|
|
|
const handleTabClick = useCallback(({ index }) => {
|
|
setSelectedTabIndex(index);
|
|
setResetScroll(true);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (empTermsData && empTermsData[selectedTabIndex]) {
|
|
setCurrentTerms(empTermsData[selectedTabIndex]);
|
|
setResetScroll(true);
|
|
}
|
|
}, [selectedTabIndex, empTermsData]);
|
|
|
|
useEffect(() => {
|
|
if (resetScroll) {
|
|
setResetScroll(false);
|
|
}
|
|
}, [resetScroll]);
|
|
|
|
const onCancelCheckoutPanel = useCallback(
|
|
(e) => {
|
|
console.log('[BuyOption][CheckOutPanel] onCancelCheckoutPanel called');
|
|
if (orderSideBarOpen) {
|
|
console.log('[BuyOption][CheckOutPanel] Closing order sidebar');
|
|
setOrderSideBarOpen(false);
|
|
setTimeout(() => Spotlight.focus(), 0);
|
|
|
|
return;
|
|
}
|
|
|
|
if (offerSideBarOpen) {
|
|
console.log('[BuyOption][CheckOutPanel] Closing offer sidebar');
|
|
setOfferSideBarOpen(false);
|
|
setTimeout(() => Spotlight.focus(), 0);
|
|
|
|
return;
|
|
}
|
|
|
|
if (!orderSideBarOpen && !offerSideBarOpen) {
|
|
console.log('[CheckOutPanel] onCancelCheckoutPanel - Sending reload signal to DetailPanel');
|
|
|
|
// DetailPanel에 재시작 신호 전달
|
|
dispatch(
|
|
updatePanel({
|
|
name: Config.panel_names.DETAIL_PANEL,
|
|
panelInfo: {
|
|
shouldReload: true,
|
|
},
|
|
})
|
|
);
|
|
|
|
// CheckOutPanel 제거
|
|
dispatch(popPanel(Config.panel_names.CHECKOUT_PANEL));
|
|
e.stopPropagation();
|
|
|
|
console.log('[CheckOutPanel] popPanel dispatched for CHECKOUT_PANEL from cancel');
|
|
}
|
|
},
|
|
[orderSideBarOpen, offerSideBarOpen, dispatch, panels]
|
|
);
|
|
|
|
const doSendLogPaymentEntry = useCallback(() => {
|
|
if (panelInfo?.logInfo) {
|
|
dispatch(sendLogPaymentEntry(panelInfo.logInfo));
|
|
}
|
|
}, [panelInfo?.logInfo]);
|
|
|
|
const doSendLogMyInfoEdit = useCallback((btnNm) => {
|
|
dispatch(sendLogMyInfoEdit({ btnNm }));
|
|
}, []);
|
|
|
|
const checkOutPanelInfo = panels.find((panel) => panel.name === 'checkoutpanel')?.panelInfo;
|
|
|
|
console.log(
|
|
'[CheckOutPanel] Rendering - orderSideBarOpen:',
|
|
orderSideBarOpen,
|
|
'offerSideBarOpen:',
|
|
offerSideBarOpen,
|
|
'placeOrderPopup:',
|
|
placeOrderPopup
|
|
);
|
|
console.log(
|
|
'[CheckOutPanel] Rendering - productData exists:',
|
|
!!productData,
|
|
'length:',
|
|
productData?.length
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<TPanel
|
|
isTabActivated={false}
|
|
spotlightDisabled={orderSideBarOpen || offerSideBarOpen || placeOrderPopup}
|
|
handleCancel={onCancelCheckoutPanel}
|
|
>
|
|
<TBody className={css.tbody} cbScrollTo={getScrollToBody}>
|
|
<THeader className={css.theader} title="CHECKOUT" onBackButton onClick={onBackClick} />
|
|
<div className={css.Wrap}>
|
|
{/* {BUYNOW_CONFIG.isMockMode() ? (
|
|
<SummaryContainerMock
|
|
setPlaceOrderPopup={setPlaceOrderPopup}
|
|
empTermsData={empTermsData}
|
|
handleTermsClick={handleTermsClick}
|
|
currSign={currSign}
|
|
currSignLoc={currSignLoc}
|
|
doSendLogPaymentEntry={doSendLogPaymentEntry}
|
|
productData={safeProductData}
|
|
rawProductData={productData}
|
|
productInfo={panelInfo?.productInfo}
|
|
defaultPrice={panelInfo?.defaultPrice}
|
|
fromCartPanel={panelInfo?.fromCartPanel}
|
|
/>
|
|
) : ( */}
|
|
<SummaryContainer
|
|
setPlaceOrderPopup={setPlaceOrderPopup}
|
|
empTermsData={empTermsData}
|
|
handleTermsClick={handleTermsClick}
|
|
currSign={currSign}
|
|
currSignLoc={currSignLoc}
|
|
doSendLogPaymentEntry={doSendLogPaymentEntry}
|
|
/>
|
|
{/* )} */}
|
|
{/* {BUYNOW_CONFIG.isMockMode() ? (
|
|
<InformationContainerMock
|
|
toggleOrderSideBar={toggleOrderSideBar}
|
|
toggleOfferSideBar={toggleOfferSideBar}
|
|
scrollTopBody={scrollTopBody}
|
|
doSendLogMyInfoEdit={doSendLogMyInfoEdit}
|
|
orderItemsCount={orderItemsCount}
|
|
/>
|
|
) : ( */}
|
|
<InformationContainer
|
|
toggleOrderSideBar={toggleOrderSideBar}
|
|
toggleOfferSideBar={toggleOfferSideBar}
|
|
scrollTopBody={scrollTopBody}
|
|
doSendLogMyInfoEdit={doSendLogMyInfoEdit}
|
|
/>
|
|
{/* )} */}
|
|
</div>
|
|
</TBody>
|
|
</TPanel>
|
|
|
|
{orderSideBarOpen && (
|
|
<OrderItemsSideBar
|
|
closeSideBar={toggleOrderSideBar}
|
|
productData={safeProductData}
|
|
rawProductData={productData}
|
|
productInfo={reduxProductData}
|
|
fromCartPanel={panelInfo?.fromCartPanel}
|
|
/>
|
|
)}
|
|
{offerSideBarOpen && (
|
|
<FixedSideBar closeSideBar={toggleOfferSideBar} offerSideBarOpen={offerSideBarOpen} />
|
|
)}
|
|
|
|
{activePopup === Config.ACTIVE_POPUP.termsPopup && (
|
|
<TPopUp
|
|
kind="introTermsPopup"
|
|
open={popupVisible}
|
|
onClose={onCloseTermsPopup}
|
|
hasButton
|
|
button1Text={$L('OK')}
|
|
>
|
|
{currentTerms && (
|
|
<div className={css.termsConts}>
|
|
<TButtonTab
|
|
className={css.tab}
|
|
selectedIndex={selectedTabIndex}
|
|
onItemClick={handleTabClick}
|
|
contents={tabList}
|
|
spotlightDisabled={true}
|
|
role="button"
|
|
/>
|
|
<TButtonScroller
|
|
boxHeight={scaleH(300)}
|
|
width={scaleW(980)}
|
|
className={css.termsDescription}
|
|
resetScrollPosition={resetScroll}
|
|
forcedFocus={false}
|
|
>
|
|
<div
|
|
className={css.termsDesc}
|
|
dangerouslySetInnerHTML={{
|
|
__html: currentTerms && currentTerms.termContent,
|
|
}}
|
|
></div>
|
|
</TButtonScroller>
|
|
</div>
|
|
)}
|
|
</TPopUp>
|
|
)}
|
|
|
|
{/*
|
|
{activePopup === Config.ACTIVE_POPUP.errorPopup && (
|
|
<TPopUp
|
|
kind="errorPopup"
|
|
hasText
|
|
open={popupVisible}
|
|
text={popup.text ? popup.text : "unknown error"}
|
|
hasButton
|
|
button1Text={$L("CLOSE")}
|
|
onClick={handlePopPanel}
|
|
/>
|
|
)} */}
|
|
|
|
<TFullPopup
|
|
open={placeOrderPopup}
|
|
className={css.pinCodePopup}
|
|
onClose={onClosePopup}
|
|
noAnimation={true}
|
|
spotlightId="pinCodeFullPopup"
|
|
>
|
|
<PinCodeInput
|
|
setPlaceOrderPopup={setPlaceOrderPopup}
|
|
setIsOrderSuccessful={setIsOrderSuccessful}
|
|
lastTotalPrice={checkOutPanelInfo?.estimatedTotal}
|
|
/>
|
|
</TFullPopup>
|
|
<div style={{ display: 'none' }}>
|
|
{console.log(
|
|
'%c[BuyOption][CheckOutPanel] ✅ Component rendering COMPLETE',
|
|
'background: lightgreen; color: black; font-weight: bold; padding: 5px;'
|
|
)}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|