[카트, 체크아웃 수정]#1
- 금액 노출 및 나오는 값 수정중. - 체크박스 선택해서 주문 처리 - 체크박스 선택시 금액 노출 처리.
This commit is contained in:
@@ -86,6 +86,8 @@ export const types = {
|
|||||||
DELETE_MY_INFO_CART : "DELETE_MY_INFO_CART",
|
DELETE_MY_INFO_CART : "DELETE_MY_INFO_CART",
|
||||||
DELETE_ALL_MY_INFO_CART : "DELETE_ALL_MY_INFO_CART",
|
DELETE_ALL_MY_INFO_CART : "DELETE_ALL_MY_INFO_CART",
|
||||||
UPDATE_MY_INFO_CART : "UPDATE_MY_INFO_CART",
|
UPDATE_MY_INFO_CART : "UPDATE_MY_INFO_CART",
|
||||||
|
//cart checkbox toggle action
|
||||||
|
TOGGLE_CHECK_CART : "TOGGLE_CHECK_CART",
|
||||||
|
|
||||||
// appData actions
|
// appData actions
|
||||||
ADD_MAIN_INDEX: 'ADD_MAIN_INDEX',
|
ADD_MAIN_INDEX: 'ADD_MAIN_INDEX',
|
||||||
|
|||||||
@@ -171,6 +171,22 @@ export const deleteAllMyinfoCart = (props) => (dispatch, getState) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 장바구니 상품 체크박스 토글
|
||||||
|
* @param {Object} item - 선택된 상품 정보
|
||||||
|
* @param {Boolean} isChecked - 선택 여부
|
||||||
|
*/
|
||||||
|
export const toggleCheckCart = (item, isChecked) => (dispatch) => {
|
||||||
|
dispatch({
|
||||||
|
type: types.TOGGLE_CHECK_CART,
|
||||||
|
payload: {
|
||||||
|
item: item,
|
||||||
|
isChecked: isChecked,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 장바구니 상품 수정
|
* 장바구니 상품 수정
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { URLS } from "../api/apiConfig";
|
import { URLS } from '../api/apiConfig';
|
||||||
import { TAxios } from "../api/TAxios";
|
import { TAxios } from '../api/TAxios';
|
||||||
import { types } from "./actionTypes";
|
import { types } from './actionTypes';
|
||||||
import { changeAppStatus, showError } from "./commonActions";
|
import {
|
||||||
|
changeAppStatus,
|
||||||
|
showError,
|
||||||
|
} from './commonActions';
|
||||||
|
|
||||||
// 회원 체크아웃 정보 조회 IF-LGSP-345
|
// 회원 체크아웃 정보 조회 IF-LGSP-345
|
||||||
export const getMyInfoCheckoutInfo =
|
export const getMyInfoCheckoutInfo =
|
||||||
@@ -150,6 +153,7 @@ export const getCheckoutTotalAmt =
|
|||||||
dirPurcSelYn,
|
dirPurcSelYn,
|
||||||
bilAddrSno,
|
bilAddrSno,
|
||||||
dlvrAddrSno,
|
dlvrAddrSno,
|
||||||
|
isPageLoading,
|
||||||
orderProductCoupontUse,
|
orderProductCoupontUse,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
@@ -195,7 +199,7 @@ export const getCheckoutTotalAmt =
|
|||||||
"post",
|
"post",
|
||||||
URLS.GET_CHECKOUT_TOTAL_AMT,
|
URLS.GET_CHECKOUT_TOTAL_AMT,
|
||||||
{},
|
{},
|
||||||
{ mbrNo, dirPurcSelYn, bilAddrSno, dlvrAddrSno, orderProductCoupontUse },
|
{ mbrNo, dirPurcSelYn, bilAddrSno, dlvrAddrSno, isPageLoading, orderProductCoupontUse },
|
||||||
onSuccess,
|
onSuccess,
|
||||||
onFail
|
onFail
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ const initialState = {
|
|||||||
cartList: [],
|
cartList: [],
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
},
|
},
|
||||||
|
selectCart : {
|
||||||
|
cartList: [],
|
||||||
|
checkedItems: [], // ✅ 체크된 상품 정보 저장
|
||||||
|
totalCount: 0,
|
||||||
|
},
|
||||||
// 추가/수정/삭제 결과
|
// 추가/수정/삭제 결과
|
||||||
lastAction: null,
|
lastAction: null,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -35,13 +40,43 @@ export const cartReducer = (state = initialState, action) => {
|
|||||||
case types.INSERT_MY_INFO_CART:
|
case types.INSERT_MY_INFO_CART:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
getMyinfoCartSearch: {
|
selectCart: {
|
||||||
...state.getMyinfoCartSearch,
|
...state.selectCart,
|
||||||
cartList: [...state.getMyinfoCartSearch.cartList, action.payload],
|
cartList: [...state.selectCart.cartList, action.payload],
|
||||||
totalCount: (state.getMyinfoCartSearch.totalCount || 0) + 1,
|
totalCount: (state.getMyinfoCartSearch.totalCount || 0) + 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//체크박스 토글시 상품 처리
|
||||||
|
case types.TOGGLE_CHECK_CART: {
|
||||||
|
const checkedItem = action.payload.item;
|
||||||
|
const isChecked = action.payload.isChecked;
|
||||||
|
|
||||||
|
let updatedCheckedList = state.selectCart?.checkedItems || [];
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
const itemExists = updatedCheckedList.some(
|
||||||
|
item => item.prodSno === checkedItem.prodSno
|
||||||
|
);
|
||||||
|
if (!itemExists) {
|
||||||
|
updatedCheckedList = [...updatedCheckedList, checkedItem];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatedCheckedList = updatedCheckedList.filter(
|
||||||
|
item => item.prodSno !== checkedItem.prodSno
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selectCart: {
|
||||||
|
...state.selectCart,
|
||||||
|
checkedItems: updatedCheckedList,
|
||||||
|
totalCount: updatedCheckedList.length,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 장바구니에서 상품 삭제
|
// 장바구니에서 상품 삭제
|
||||||
case types.DELETE_MY_INFO_CART:
|
case types.DELETE_MY_INFO_CART:
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -202,8 +202,7 @@ export const isAuctionProduct = (product) => {
|
|||||||
* @returns {Object} 정규화된 상품 객체
|
* @returns {Object} 정규화된 상품 객체
|
||||||
*/
|
*/
|
||||||
export const normalizeProductDataForDisplay = (product) => {
|
export const normalizeProductDataForDisplay = (product) => {
|
||||||
// Mock Mode: product가 없어도 기본값으로 진행
|
// Mock Mode: product가 없어도 기본값으로 진행
|
||||||
console.log("###product 확인용", product)
|
|
||||||
if (!product) {
|
if (!product) {
|
||||||
console.log('[mockDataSafetyUtils] normalizeProductDataForDisplay - product is null/undefined, using defaults');
|
console.log('[mockDataSafetyUtils] normalizeProductDataForDisplay - product is null/undefined, using defaults');
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ import {
|
|||||||
} from 'react-redux';
|
} from 'react-redux';
|
||||||
|
|
||||||
import { getMyInfoCartSearch } from '../../actions/cartActions';
|
import { getMyInfoCartSearch } from '../../actions/cartActions';
|
||||||
|
import {
|
||||||
|
setHidePopup,
|
||||||
|
setShowPopup,
|
||||||
|
} from '../../actions/commonActions';
|
||||||
import {
|
import {
|
||||||
initializeMockCart,
|
initializeMockCart,
|
||||||
resetMockCart,
|
resetMockCart,
|
||||||
@@ -21,10 +25,12 @@ import {
|
|||||||
import TBody from '../../components/TBody/TBody';
|
import TBody from '../../components/TBody/TBody';
|
||||||
import THeader from '../../components/THeader/THeader';
|
import THeader from '../../components/THeader/THeader';
|
||||||
import TPanel from '../../components/TPanel/TPanel';
|
import TPanel from '../../components/TPanel/TPanel';
|
||||||
|
import TPopUp from '../../components/TPopUp/TPopUp';
|
||||||
import TScroller from '../../components/TScroller/TScroller';
|
import TScroller from '../../components/TScroller/TScroller';
|
||||||
import useScrollTo from '../../hooks/useScrollTo';
|
import useScrollTo from '../../hooks/useScrollTo';
|
||||||
import { BUYNOW_CONFIG } from '../../utils/BuyNowConfig';
|
import { launchMembershipApp } from '../../lunaSend';
|
||||||
import * as Config from '../../utils/Config';
|
import * as Config from '../../utils/Config';
|
||||||
|
import { $L } from '../../utils/helperMethods';
|
||||||
import CartEmpty from './CartEmpty';
|
import CartEmpty from './CartEmpty';
|
||||||
import css from './CartPanel.module.less';
|
import css from './CartPanel.module.less';
|
||||||
import CartProductBar from './CartProductBar';
|
import CartProductBar from './CartProductBar';
|
||||||
@@ -44,13 +50,19 @@ export default function CartPanel({ spotlightId, scrollOptions = [], panelInfo }
|
|||||||
const { userNumber } = useSelector(
|
const { userNumber } = useSelector(
|
||||||
(state) => state.common.appStatus.loginUserData
|
(state) => state.common.appStatus.loginUserData
|
||||||
);
|
);
|
||||||
|
const { popupVisible, activePopup } = useSelector(
|
||||||
|
(state) => state.common.popup
|
||||||
|
);
|
||||||
|
const webOSVersion = useSelector(
|
||||||
|
(state) => state.common.appStatus.webOSVersion
|
||||||
|
);
|
||||||
|
|
||||||
// Mock Mode 여부 확인 및 적절한 데이터 선택
|
// Mock Mode 여부 확인 및 적절한 데이터 선택
|
||||||
// const isMockMode = BUYNOW_CONFIG.isMockMode();
|
// const isMockMode = BUYNOW_CONFIG.isMockMode();
|
||||||
const isMockMode = false;
|
const isMockMode = false;
|
||||||
const displayCartData = useMemo(() => {
|
const displayCartData = useMemo(() => {
|
||||||
return isMockMode ? mockCartData : cartData;
|
return isMockMode ? mockCartData : cartData;
|
||||||
}, [isMockMode, mockCartData, cartData]);
|
}, [isMockMode, mockCartData, cartData]);
|
||||||
|
|
||||||
// PlayerPanel/MediaPanel 충돌 방지 로직 (CheckOutPanel 전환 시에만 활성화)
|
// PlayerPanel/MediaPanel 충돌 방지 로직 (CheckOutPanel 전환 시에만 활성화)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -166,6 +178,35 @@ export default function CartPanel({ spotlightId, scrollOptions = [], panelInfo }
|
|||||||
|
|
||||||
const { getScrollTo, scrollTop } = useScrollTo();
|
const { getScrollTo, scrollTop } = useScrollTo();
|
||||||
|
|
||||||
|
// 로그인 팝업 텍스트 로직 (SingleOption과 동일)
|
||||||
|
const loginPopupText = useMemo(() => {
|
||||||
|
return $L('Would you like to sign in?');
|
||||||
|
}, [userNumber]);
|
||||||
|
|
||||||
|
// 로그인 팝업 열기 핸들러 (SingleOption과 동일)
|
||||||
|
const handleLoginPopUpOpen = useCallback(() => {
|
||||||
|
if (!userNumber) {
|
||||||
|
if (webOSVersion >= '6.0') {
|
||||||
|
dispatch(setHidePopup());
|
||||||
|
dispatch(launchMembershipApp()); // 필요시 추가
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [dispatch, webOSVersion, userNumber]);
|
||||||
|
|
||||||
|
// 팝업 닫기 핸들러 (SingleOption과 동일)
|
||||||
|
const onClose = useCallback(() => {
|
||||||
|
dispatch(setHidePopup());
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(!userNumber || userNumber === ''){
|
||||||
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.loginPopup));
|
||||||
|
}
|
||||||
|
},[userNumber, dispatch])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TPanel spotlightId={spotlightId} isTabActivated={true}>
|
<TPanel spotlightId={spotlightId} isTabActivated={true}>
|
||||||
<TBody className={css.tbody} cbScrollTo={getScrollTo}>
|
<TBody className={css.tbody} cbScrollTo={getScrollTo}>
|
||||||
@@ -182,7 +223,7 @@ export default function CartPanel({ spotlightId, scrollOptions = [], panelInfo }
|
|||||||
</div>
|
</div>
|
||||||
<div className={css.rightSection}>
|
<div className={css.rightSection}>
|
||||||
{/* 오른쪽 상품 영역 */}
|
{/* 오른쪽 상품 영역 */}
|
||||||
{displayCartData && displayCartData?.length > 0 ? (
|
{userNumber && displayCartData && displayCartData?.length > 0 ? (
|
||||||
<TScroller
|
<TScroller
|
||||||
className={css.tScroller}
|
className={css.tScroller}
|
||||||
{...scrollOptions}
|
{...scrollOptions}
|
||||||
@@ -191,6 +232,22 @@ export default function CartPanel({ spotlightId, scrollOptions = [], panelInfo }
|
|||||||
</TScroller>
|
</TScroller>
|
||||||
) : (
|
) : (
|
||||||
<CartEmpty />
|
<CartEmpty />
|
||||||
|
|
||||||
|
|
||||||
|
)}
|
||||||
|
{/* LOGIN POPUP */}
|
||||||
|
{(!userNumber || userNumber === '') && activePopup === Config.ACTIVE_POPUP.loginPopup && (
|
||||||
|
<TPopUp
|
||||||
|
kind="textPopup"
|
||||||
|
hasText
|
||||||
|
open={popupVisible}
|
||||||
|
text={loginPopupText}
|
||||||
|
hasButton
|
||||||
|
button1Text={$L('OK')}
|
||||||
|
button2Text={$L('CANCEL')}
|
||||||
|
onClick={handleLoginPopUpOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import defaultImage from '../../../assets/images/img-thumb-empty-144@3x.png';
|
|||||||
import {
|
import {
|
||||||
deleteMyinfoCart,
|
deleteMyinfoCart,
|
||||||
removeFromCart,
|
removeFromCart,
|
||||||
|
toggleCheckCart,
|
||||||
updateMyinfoCart,
|
updateMyinfoCart,
|
||||||
} from '../../actions/cartActions';
|
} from '../../actions/cartActions';
|
||||||
import {
|
import {
|
||||||
@@ -94,6 +95,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
|
|
||||||
// 항상 호출되어야 하는 Hook들
|
// 항상 호출되어야 하는 Hook들
|
||||||
const fallbackCartData = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo);
|
const fallbackCartData = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo);
|
||||||
|
const checkedItems = useSelector((state) => state.cart.selectCart.checkedItems || []); // ✅ Redux에서 체크된 아이템 가져오기
|
||||||
const selectedItems = useSelector((state) => state.mockCart.selectedItems || []);
|
const selectedItems = useSelector((state) => state.mockCart.selectedItems || []);
|
||||||
const userNumber = useSelector((state) => state.common.appStatus.loginUserData.userNumber);
|
const userNumber = useSelector((state) => state.common.appStatus.loginUserData.userNumber);
|
||||||
|
|
||||||
@@ -103,7 +105,6 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
// Mock Mode 확인
|
// Mock Mode 확인
|
||||||
const isMockMode = BUYNOW_CONFIG.isMockMode();
|
const isMockMode = BUYNOW_CONFIG.isMockMode();
|
||||||
|
|
||||||
//카트 데이타 그룹화 - 수정된 부분
|
|
||||||
const groupedCartData = useMemo(() => {
|
const groupedCartData = useMemo(() => {
|
||||||
if (!cartData || !Array.isArray(cartData)) return {};
|
if (!cartData || !Array.isArray(cartData)) return {};
|
||||||
|
|
||||||
@@ -111,7 +112,6 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
const groupKey = item.patncNm || item.patnrId || 'unknown';
|
const groupKey = item.patncNm || item.patnrId || 'unknown';
|
||||||
|
|
||||||
if (!acc[groupKey]) {
|
if (!acc[groupKey]) {
|
||||||
// 객체 구조로 초기화 (수정됨)
|
|
||||||
acc[groupKey] = {
|
acc[groupKey] = {
|
||||||
partnerInfo: {
|
partnerInfo: {
|
||||||
id: item.patnrId,
|
id: item.patnrId,
|
||||||
@@ -137,14 +137,15 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
// 파트너사별 총합 계산
|
// 파트너사별 총합 계산
|
||||||
const calculatePartnerTotal = (items) => {
|
const calculatePartnerTotal = (items) => {
|
||||||
const productTotal = items.reduce((sum, item) =>
|
const productTotal = items.reduce((sum, item) =>
|
||||||
sum + (parseFloat(Number(item.price3) !== 0 ? Number(item.price3) : Number(item.price2) !== 0 ? Number(item.price2) : 0) * item.prodQty), 0
|
sum + (Number(item.price3) !== 0 ? Number(item.price3) : Number(item.price2) !== 0 ? Number(item.price2) : 0) * item.prodQty, 0
|
||||||
);
|
);
|
||||||
const optionTotal = items.reduce((sum, item) =>
|
const optionTotal = items.reduce((sum, item) =>
|
||||||
sum + (parseFloat(Number(item.price5) !== 0 ? Number(item.price5) : Number(item.optPrc) !== 0 ? Number(item.optPrc) : 0) * item.prodQty), 0
|
//sum + (parseFloat(Number(item.price5) !== 0 ? Number(item.price5) : Number(item.optPrc) !== 0 ? Number(item.optPrc) : 0) * item.prodQty), 0
|
||||||
|
sum + (Number(item.optPrc) !== 0 && item.optPrc !== undefined) ? Number(item.optPrc) : 0 * item.prodQty, 0
|
||||||
);
|
);
|
||||||
|
|
||||||
const shippingTotal = items.reduce((sum, item) =>
|
const shippingTotal = items.reduce((sum, item) =>
|
||||||
sum + parseFloat((item.shippingCharge) * item.prodQty || 0), 0
|
sum + parseFloat(item.shippingCharge || 0), 0
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -176,7 +177,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [dispatch, isMockMode]);
|
}, [dispatch, isMockMode, userNumber]);
|
||||||
|
|
||||||
const handleIncreseClick = useCallback((prodSno, patnrId, prdtId, currentQty) => {
|
const handleIncreseClick = useCallback((prodSno, patnrId, prdtId, currentQty) => {
|
||||||
const newQty = currentQty + 1;
|
const newQty = currentQty + 1;
|
||||||
@@ -190,7 +191,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
dispatch(updateMyinfoCart({ mbrNo: userNumber, patnrId, prdtId, prodSno, prodQty: newQty }));
|
dispatch(updateMyinfoCart({ mbrNo: userNumber, patnrId, prdtId, prodSno, prodQty: newQty }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [dispatch, isMockMode]);
|
}, [dispatch, isMockMode, userNumber]);
|
||||||
|
|
||||||
// 상품 삭제 핸들러
|
// 상품 삭제 핸들러
|
||||||
const handleDeleteClick = useCallback((prodSno) => {
|
const handleDeleteClick = useCallback((prodSno) => {
|
||||||
@@ -205,46 +206,29 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
}
|
}
|
||||||
}, [dispatch, isMockMode]);
|
}, [dispatch, isMockMode]);
|
||||||
|
|
||||||
// 체크박스 선택 핸들러 (TCheckBoxSquare onToggle 형식에 맞춤) - debounce 적용
|
// 체크박스 선택 핸들러 - ✅ Redux 상태만 사용하도록 수정
|
||||||
const debouncedUpdateSelectedItems = useCallback(
|
const handleCheckboxToggle = useCallback((prodSno, fullItemData) => {
|
||||||
debounce((newSelectedItems) => {
|
|
||||||
dispatch(updateSelectedItems(newSelectedItems));
|
|
||||||
}, 100), // 100ms debounce
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleCheckboxToggle = useCallback((prodSno) => {
|
|
||||||
return ({ selected: isChecked }) => {
|
return ({ selected: isChecked }) => {
|
||||||
const DEBUG_LOG = false; // 수동 설정: false로 비활성화
|
// Redux 상태에만 저장
|
||||||
|
dispatch(toggleCheckCart(fullItemData, isChecked));
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartProduct] handleCheckboxToggle called - prodSno:', prodSno, 'selected:', isChecked);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMockMode) {
|
|
||||||
let newSelectedItems;
|
|
||||||
if (isChecked) {
|
|
||||||
// 상품 선택
|
|
||||||
newSelectedItems = [...selectedItems, prodSno];
|
|
||||||
} else {
|
|
||||||
// 상품 선택 해제
|
|
||||||
newSelectedItems = selectedItems.filter(id => id !== prodSno);
|
|
||||||
}
|
|
||||||
|
|
||||||
// debounced 호출 사용
|
|
||||||
debouncedUpdateSelectedItems(newSelectedItems);
|
|
||||||
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartProduct] Checkbox toggled - prodSno:', prodSno, 'isChecked:', isChecked, 'selectedItems:', newSelectedItems);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}, [dispatch, isMockMode, selectedItems, debouncedUpdateSelectedItems]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
// 장바구니 삭제
|
||||||
|
const deleteCart = useCallback((patnrId, prdtId, prodSno, item) => {
|
||||||
|
dispatch(toggleCheckCart(item, false));
|
||||||
|
dispatch(deleteMyinfoCart({
|
||||||
|
mbrNo : userNumber,
|
||||||
|
patnrId: String(patnrId),
|
||||||
|
prdtId : String(prdtId),
|
||||||
|
prodSno : String(prodSno)
|
||||||
|
}))
|
||||||
|
},[dispatch, userNumber])
|
||||||
|
|
||||||
// 상품이 선택되었는지 확인
|
// 상품이 선택되었는지 확인
|
||||||
const isItemSelected = useCallback((prodSno) => {
|
const isItemSelected = useCallback((prodSno) => {
|
||||||
return selectedItems.includes(prodSno);
|
return checkedItems.some(item => item.prodSno === prodSno);
|
||||||
}, [selectedItems]);
|
}, [checkedItems]);
|
||||||
|
|
||||||
const handleFocus = useCallback((index, groupIndex) => {
|
const handleFocus = useCallback((index, groupIndex) => {
|
||||||
if(index === 0 && groupIndex === 0){
|
if(index === 0 && groupIndex === 0){
|
||||||
@@ -259,9 +243,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
andThen(() => document.getElementById(sectionId)),
|
andThen(() => document.getElementById(sectionId)),
|
||||||
when(isNil, () => null),
|
when(isNil, () => null),
|
||||||
andThen((targetElement) => {
|
andThen((targetElement) => {
|
||||||
// offsetTop: 부모 컨테이너 기준 절대 위치 사용
|
const y = 0;
|
||||||
// const y = targetElement.offsetTop;
|
|
||||||
const y = 0; //0으로 들어가는것이 깔끔.
|
|
||||||
return scrollTop({ y, animate: true });
|
return scrollTop({ y, animate: true });
|
||||||
})
|
})
|
||||||
)(sectionId)
|
)(sectionId)
|
||||||
@@ -269,22 +251,14 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
[scrollTop]
|
[scrollTop]
|
||||||
);
|
);
|
||||||
|
|
||||||
//장바구니 삭제
|
|
||||||
const deleteCart = useCallback((patnrId, prdtId, prodSno) => {
|
|
||||||
dispatch(deleteMyinfoCart({
|
|
||||||
mbrNo : userNumber,
|
|
||||||
patnrId: String(patnrId),
|
|
||||||
prdtId : String(prdtId),
|
|
||||||
prodSno : String(prodSno)
|
|
||||||
}))
|
|
||||||
},[dispatch])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Object.entries(groupedCartData).map(([partnerKey, group], index) => {
|
{Object.entries(groupedCartData).map(([partnerKey, group], index) => {
|
||||||
const totals = calculatePartnerTotal(group.items);
|
const totals = calculatePartnerTotal(group.items);
|
||||||
return (
|
return (
|
||||||
<Container key={partnerKey} className={css.productBox}>
|
<Container key={partnerKey} className={css.productBox}>
|
||||||
{index === 0 && (
|
{index === 0 && (
|
||||||
<div className={css.scrollMarker} id="cartFocus_0"></div>
|
<div className={css.scrollMarker} id="cartFocus_0"></div>
|
||||||
)}
|
)}
|
||||||
@@ -310,9 +284,9 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
<div className={css.productPrice}>
|
<div className={css.productPrice}>
|
||||||
<div className={css.leftSection}>
|
<div className={css.leftSection}>
|
||||||
Product Total ${totals.productTotal.toLocaleString('en-US', {
|
Product Total ${totals.productTotal.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})} +
|
})} +
|
||||||
{totals.optionTotal > 0 && (
|
{totals.optionTotal > 0 && (
|
||||||
<>
|
<>
|
||||||
Option ${totals.optionTotal.toLocaleString('en-US', {
|
Option ${totals.optionTotal.toLocaleString('en-US', {
|
||||||
@@ -322,9 +296,9 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
S&H ${totals.shippingTotal.toLocaleString('en-US', {
|
S&H ${totals.shippingTotal.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className={css.rightSection}>
|
<div className={css.rightSection}>
|
||||||
Total
|
Total
|
||||||
@@ -345,8 +319,8 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
const normalizedItem = normalizeProductDataForDisplay(item);
|
const normalizedItem = normalizeProductDataForDisplay(item);
|
||||||
|
|
||||||
// ✅ 이미지 우선순위: ProductAllSection 고품질 이미지 → 기타 모든 이미지 필드
|
// ✅ 이미지 우선순위: ProductAllSection 고품질 이미지 → 기타 모든 이미지 필드
|
||||||
const imageSrc = (item.imgUrls600 && item.imgUrls600[0]) || // ✅ ProductAllSection의 고품질 이미지
|
const imageSrc = (item.imgUrls600 && item.imgUrls600[0]) ||
|
||||||
(item.thumbnailUrl960) || // ✅ 960px 썸네일
|
(item.thumbnailUrl960) ||
|
||||||
(normalizedItem.imgUrls && normalizedItem.imgUrls[0]?.imgUrl) ||
|
(normalizedItem.imgUrls && normalizedItem.imgUrls[0]?.imgUrl) ||
|
||||||
(item.imgUrls && item.imgUrls[0]?.imgUrl) ||
|
(item.imgUrls && item.imgUrls[0]?.imgUrl) ||
|
||||||
(item.imgList && item.imgList[0]?.imgUrl) ||
|
(item.imgList && item.imgList[0]?.imgUrl) ||
|
||||||
@@ -356,109 +330,109 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
defaultImage;
|
defaultImage;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.prodSno} className={css.product}>
|
<div key={item.prodSno} className={css.product}>
|
||||||
<div className={css.leftBox}>
|
<div className={css.leftBox}>
|
||||||
<div className={css.checkBox}>
|
<div className={css.checkBox}>
|
||||||
<TCheckBoxSquare
|
<TCheckBoxSquare
|
||||||
className={css.customeCheckbox}
|
className={css.customeCheckbox}
|
||||||
spotlightId={`productCheckbox-${item.prodSno}`}
|
spotlightId={`productCheckbox-${item.prodSno}`}
|
||||||
selected={isItemSelected(item.prodSno)}
|
selected={isItemSelected(item.prodSno)} // ✅ Redux 상태 기반
|
||||||
onToggle={handleCheckboxToggle(item.prodSno)}
|
onToggle={handleCheckboxToggle(item.prodSno, item)} // ✅ item 전체 데이터 전달
|
||||||
onFocus={()=> {handleFocus(index, groupIndex)}}
|
onFocus={()=> {handleFocus(index, groupIndex)}}
|
||||||
/>
|
|
||||||
<span className={css.productId}>
|
|
||||||
ID : {item.prdtId}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={css.productInfo}>
|
|
||||||
<div className={css.leftSection}>
|
|
||||||
<OptimizedImage
|
|
||||||
className={css.productImage}
|
|
||||||
src={imageSrc}
|
|
||||||
fallbackSrc={defaultImage}
|
|
||||||
alt={item.prdtNm || 'Product Image'}
|
|
||||||
/>
|
/>
|
||||||
|
<span className={css.productId}>
|
||||||
|
ID : {item.prdtId}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={css.rightSection}>
|
<div className={css.productInfo}>
|
||||||
<div className={css.productNm}>
|
<div className={css.leftSection}>
|
||||||
{item.prdtNm}
|
<OptimizedImage
|
||||||
|
className={css.productImage}
|
||||||
|
src={imageSrc}
|
||||||
|
fallbackSrc={defaultImage}
|
||||||
|
alt={item.prdtNm || 'Product Image'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{item.optNm && (
|
<div className={css.rightSection}>
|
||||||
<div className={css.optionNm}>{item.optNm}</div>
|
<div className={css.productNm}>
|
||||||
)}
|
{item.prdtNm}
|
||||||
<div className={css.accountBox}>
|
</div>
|
||||||
<span className={css.account}>
|
{item.optNm && (
|
||||||
${parseFloat(Number(item.price3) > 0 ? Number(item.price3) : Number(item.price2) > 0 ? Number(item.price2) : 0).toLocaleString('en-US', {
|
<div className={css.optionNm}>{item.optNm}</div>
|
||||||
minimumFractionDigits: 2,
|
)}
|
||||||
maximumFractionDigits: 2
|
<div className={css.accountBox}>
|
||||||
})}
|
<span className={css.account}>
|
||||||
</span>
|
${parseFloat(Number(item.price3) > 0 ? Number(item.price3) : Number(item.price2) > 0 ? Number(item.price2) : 0).toLocaleString('en-US', {
|
||||||
<div className={css.accountInfo}>
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
<div className={css.accountInfo}>
|
||||||
<span className={css.originalAcc}>
|
<span className={css.originalAcc}>
|
||||||
{item.price2 && (parseFloat(item.price2) > 0 && parseFloat(item.price3) > 0 && parseFloat(item.price2) !== parseFloat(item.price3)) && (
|
{item.price2 && (parseFloat(item.price2) > 0 && parseFloat(item.price3) > 0 && parseFloat(item.price2) !== parseFloat(item.price3)) && (
|
||||||
<>
|
<>
|
||||||
${parseFloat(item.price2).toLocaleString('en-US', {
|
${parseFloat(item.price2).toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
{item.price5 && parseFloat(item.price5) > 0 && (
|
{item.optPrc && parseFloat(item.optPrc) > 0 && parseFloat(item.optPrc) !== parseFloat(item.price2) && parseFloat(item.optPrc) !== parseFloat(item.price3) && (
|
||||||
<span className={css.optionAcc}>
|
<span className={css.optionAcc}>
|
||||||
OPTION : ${parseFloat(item.price5).toLocaleString('en-US', {
|
OPTION : ${parseFloat(item.optPrc).toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{item.shippingCharge && parseFloat(item.shippingCharge) > 0 && (
|
{item.shippingCharge && parseFloat(item.shippingCharge) > 0 && (
|
||||||
<span className={css.shippingAcc}>
|
<span className={css.shippingAcc}>
|
||||||
S&H: ${parseFloat(item.shippingCharge).toLocaleString('en-US', {
|
S&H: ${parseFloat(item.shippingCharge).toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={css.eaBox}>
|
||||||
|
<TButton
|
||||||
|
className={classNames(
|
||||||
|
css.minusBox,
|
||||||
|
item.prodQty === 1 ? css.dimm : ""
|
||||||
|
)}
|
||||||
|
size="cartEa"
|
||||||
|
onClick={() => handleDecreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)}
|
||||||
|
spotlightId={"pd_ea_decrese"}
|
||||||
|
spotlightDisabled={item.prodQty === 1}
|
||||||
|
/>
|
||||||
|
<div className={css.ea}>{item.prodQty}</div>
|
||||||
|
<TButton
|
||||||
|
onClick={() => handleIncreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)}
|
||||||
|
className={css.plusBox}
|
||||||
|
spotlightId={"pd_ea_increse"}
|
||||||
|
size="cartEa"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={css.eaBox}>
|
|
||||||
<TButton
|
|
||||||
className={classNames(
|
|
||||||
css.minusBox,
|
|
||||||
item.prodQty === 1 ? css.dimm : ""
|
|
||||||
)}
|
|
||||||
size="cartEa"
|
|
||||||
onClick={() => handleDecreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)}
|
|
||||||
spotlightId={"pd_ea_decrese"}
|
|
||||||
spotlightDisabled={item.prodQty === 1}
|
|
||||||
/>
|
|
||||||
<div className={css.ea}>{item.prodQty}</div>
|
|
||||||
<TButton
|
|
||||||
onClick={() => handleIncreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)}
|
|
||||||
className={css.plusBox}
|
|
||||||
spotlightId={"pd_ea_increse"}
|
|
||||||
size="cartEa"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={css.rightBox}>
|
||||||
|
<TButton
|
||||||
|
className={css.trashImg}
|
||||||
|
size="cartTrash"
|
||||||
|
onClick={() => deleteCart(item.patnrId, item.prdtId, item.prodSno, item)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={css.rightBox}>
|
|
||||||
<TButton
|
|
||||||
className={css.trashImg}
|
|
||||||
size="cartTrash"
|
|
||||||
onClick={() => deleteCart(item.patnrId, item.prdtId, item.prodSno)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,16 @@ import {
|
|||||||
useSelector,
|
useSelector,
|
||||||
} from 'react-redux';
|
} from 'react-redux';
|
||||||
|
|
||||||
import { pushPanel } from '../../actions/panelActions';
|
import { getMyInfoCheckoutInfo } from '../../actions/checkoutActions';
|
||||||
|
import {
|
||||||
|
changeAppStatus,
|
||||||
|
setShowPopup,
|
||||||
|
showError,
|
||||||
|
} from '../../actions/commonActions';
|
||||||
|
import {
|
||||||
|
popPanel,
|
||||||
|
pushPanel,
|
||||||
|
} from '../../actions/panelActions';
|
||||||
import TButton from '../../components/TButton/TButton';
|
import TButton from '../../components/TButton/TButton';
|
||||||
import { BUYNOW_CONFIG } from '../../utils/BuyNowConfig';
|
import { BUYNOW_CONFIG } from '../../utils/BuyNowConfig';
|
||||||
import * as Config from '../../utils/Config';
|
import * as Config from '../../utils/Config';
|
||||||
@@ -26,175 +35,174 @@ const CartSidebar = ({ cartInfo }) => {
|
|||||||
|
|
||||||
// 실제 장바구니 데이터 (API 모드일 때만 사용)
|
// 실제 장바구니 데이터 (API 모드일 때만 사용)
|
||||||
const fallbackCartInfo = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo);
|
const fallbackCartInfo = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo);
|
||||||
const selectedItems = useSelector((state) => state.mockCart.selectedItems || []);
|
// ✅ Redux에서 체크된 상품 정보 가져오기
|
||||||
|
const checkedItems = useSelector((state) => state.cart.selectCart.checkedItems || []);
|
||||||
|
|
||||||
|
const { userNumber } = useSelector(
|
||||||
|
(state) => state.common.appStatus.loginUserData
|
||||||
|
);
|
||||||
|
|
||||||
// 사용할 장바구니 데이터 결정
|
// 사용할 장바구니 데이터 결정
|
||||||
const displayCartInfo = cartInfo || (isMockMode ? null : fallbackCartInfo);
|
const displayCartInfo = cartInfo || (isMockMode ? null : fallbackCartInfo);
|
||||||
|
|
||||||
// 선택된 상품들만 필터링 - 항상 선택된 상품들만 반환
|
// ✅ 계산할 상품 결정 (체크된 상품이 있으면 체크된 상품, 없으면 전체 상품)
|
||||||
const getSelectedItems = useCallback((items) => {
|
const itemsToCalculate = useMemo(() => {
|
||||||
const DEBUG_LOG = false; // 수동 설정: false로 비활성화
|
if (checkedItems && checkedItems.length > 0) {
|
||||||
|
// 체크된 상품이 있으면 체크된 상품만 사용
|
||||||
if (DEBUG_LOG) {
|
console.log('[CartSidebar] Using checked items for calculation:', checkedItems.length);
|
||||||
console.log('[CartSidebar] getSelectedItems called - isMockMode:', isMockMode, 'selectedItems:', selectedItems);
|
return checkedItems;
|
||||||
|
} else if (displayCartInfo && Array.isArray(displayCartInfo)) {
|
||||||
|
// 체크된 상품이 없으면 전체 장바구니 상품 사용
|
||||||
|
console.log('[CartSidebar] No checked items, using all cart items:', displayCartInfo.length);
|
||||||
|
return displayCartInfo;
|
||||||
}
|
}
|
||||||
|
return [];
|
||||||
|
}, [checkedItems, displayCartInfo]);
|
||||||
|
|
||||||
if (!items || !Array.isArray(items)) {
|
// checkOutValidate 콜백 함수 (SingleOption과 동일한 로직)
|
||||||
if (DEBUG_LOG) {
|
function checkOutValidate(response) {
|
||||||
console.log('[CartSidebar] No items provided, returning empty array');
|
console.log('%c[BuyOption] 🔴 checkOutValidate CALLED', 'background: red; color: white; font-weight: bold; padding: 5px;', {
|
||||||
|
hasResponse: !!response,
|
||||||
|
retCode: response?.retCode,
|
||||||
|
retMsg: response?.retMsg,
|
||||||
|
hasCardInfo: !!response?.data?.cardInfo,
|
||||||
|
hasBillingAddress: response?.data?.billingAddressList?.length > 0,
|
||||||
|
hasShippingAddress: response?.data?.shippingAddressList?.length > 0,
|
||||||
|
hasProductList: response?.data?.productList?.length > 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
if (response.retCode === 0) {
|
||||||
|
// 🔍 조건 체크
|
||||||
|
const isCardInfoNull = response.data.cardInfo === null;
|
||||||
|
const isBillingAddressEmpty = response.data.billingAddressList.length === 0;
|
||||||
|
const isShippingAddressEmpty = response.data.shippingAddressList.length === 0;
|
||||||
|
|
||||||
|
console.log('%c[BuyOption] 🔍 Address & Card Validation:', 'background: blue; color: white; font-weight: bold; padding: 5px;', {
|
||||||
|
isCardInfoNull,
|
||||||
|
isBillingAddressEmpty,
|
||||||
|
isShippingAddressEmpty,
|
||||||
|
needsQRPopup: isCardInfoNull || isBillingAddressEmpty || isShippingAddressEmpty,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
isCardInfoNull ||
|
||||||
|
isBillingAddressEmpty ||
|
||||||
|
isShippingAddressEmpty
|
||||||
|
) {
|
||||||
|
console.log('%c[BuyOption] 🟡 Missing card/address - Showing QR Popup', 'background: orange; color: white; font-weight: bold; padding: 5px;');
|
||||||
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.qrPopup));
|
||||||
|
dispatch(changeAppStatus({ isLoading: false }));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
console.log('%c[BuyOption] ✅ All address & card data present - Proceeding to CheckOutPanel', 'background: green; color: white; font-weight: bold; padding: 5px;');
|
||||||
|
const { mbrId, prdtId, prodSno } = response.data.productList[0];
|
||||||
|
const cartTpSno = `${mbrId}_${prdtId}_${prodSno}`;
|
||||||
|
|
||||||
|
|
||||||
|
// 🔴 CRITICAL: 기존 CheckOutPanel 있으면 제거 후 새로 push (API Mode)
|
||||||
|
dispatch((dispatchFn, getState) => {
|
||||||
|
const panels = getState().panels?.panels || [];
|
||||||
|
const checkoutPanelExists = panels.some(p => p.name === Config.panel_names.CHECKOUT_PANEL);
|
||||||
|
|
||||||
|
console.log('[BuyOption] 📊 API Mode - Current panels:', panels.map(p => p.name));
|
||||||
|
|
||||||
|
// 1️⃣ DetailPanel 제거 (STANDALONE_PANEL이므로 다른 패널 제거 필수)
|
||||||
|
console.log('[BuyOption] 🗑️ API Mode - Removing DetailPanel');
|
||||||
|
dispatchFn(popPanel(Config.panel_names.DETAIL_PANEL));
|
||||||
|
|
||||||
|
// 2️⃣ 기존 CheckOutPanel 제거 (있으면)
|
||||||
|
if (checkoutPanelExists) {
|
||||||
|
console.log('[BuyOption] 🗑️ API Mode - Removing existing CheckOutPanel');
|
||||||
|
dispatchFn(popPanel(Config.panel_names.CHECKOUT_PANEL));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3️⃣ 새로운 CheckOutPanel push
|
||||||
|
console.log('[BuyOption] ➕ API Mode - Pushing new CheckOutPanel');
|
||||||
|
dispatchFn(pushPanel({
|
||||||
|
name: Config.panel_names.CHECKOUT_PANEL,
|
||||||
|
// panelInfo: { logInfo: { ...logInfo, cartTpSno } },
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (response.retCode === 1001) {
|
||||||
|
dispatch(setShowPopup(Config.ACTIVE_POPUP.qrPopup));
|
||||||
|
dispatch(changeAppStatus({ isLoading: false }));
|
||||||
|
} else {
|
||||||
|
dispatch(
|
||||||
|
showError(
|
||||||
|
response.retCode,
|
||||||
|
response.retMsg,
|
||||||
|
false,
|
||||||
|
response.retDetailCode,
|
||||||
|
response.returnBindStrings
|
||||||
|
)
|
||||||
|
);
|
||||||
|
dispatch(changeAppStatus({ isLoading: false }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMockMode) {
|
// ✅ Mock 데이터 또는 실제 데이터 계산 - 최적화 버전
|
||||||
if (DEBUG_LOG) {
|
const calculatedData = useMemo(() => {
|
||||||
console.log('[CartSidebar] API Mode - returning all items');
|
const DEBUG_LOG = false;
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedItems.length === 0) {
|
if (itemsToCalculate && itemsToCalculate.length > 0) {
|
||||||
if (DEBUG_LOG) {
|
let totalItems = 0;
|
||||||
console.log('[CartSidebar] No items selected, returning empty array');
|
let totalOption = 0;
|
||||||
}
|
let totalShipping = 0;
|
||||||
return []; // 선택된 상품이 없으면 빈 배열 반환
|
let totalQuantity = 0;
|
||||||
}
|
|
||||||
|
|
||||||
const filtered = items.filter(item => {
|
itemsToCalculate.forEach((item) => {
|
||||||
const itemId = item.prodSno || item.cartId;
|
// API 모드: 실제 가격 필드 사용
|
||||||
const isSelected = selectedItems.includes(itemId);
|
const productPrice = parseFloat(Number(item.price3) !== 0 ? Number(item.price3) : Number(item.price2) !== 0 ? Number(item.price2) : 0);
|
||||||
if (DEBUG_LOG) {
|
const optionPrice = parseFloat(Number(item.price3) !== Number(item.optPrc) && (Number(item.price3) !== Number(item.optPrc)) ? Number(item.optPrc) : 0 || 0);
|
||||||
console.log('[CartSidebar] Item filter:', {
|
const shippingPrice = parseFloat(Number(item.shippingCharge) || 0);
|
||||||
itemName: item.prdtNm,
|
|
||||||
itemId,
|
|
||||||
isSelected
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return isSelected;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (DEBUG_LOG) {
|
const qty = item.prodQty || item.qty || 1;
|
||||||
console.log('[CartSidebar] Filtered selected items:', filtered.length, 'out of', items.length);
|
totalItems += productPrice * qty;
|
||||||
}
|
totalOption += optionPrice * qty;
|
||||||
return filtered;
|
totalShipping += shippingPrice;
|
||||||
}, [isMockMode, selectedItems]);
|
totalQuantity += qty;
|
||||||
|
|
||||||
// 개별 상품 가격 캐싱 (성능 최적화)
|
if (DEBUG_LOG) {
|
||||||
const itemPriceCache = useMemo(() => {
|
console.log('[CartSidebar] Item calculation:', {
|
||||||
const cache = new Map();
|
name: item.prdtNm,
|
||||||
|
qty,
|
||||||
if (isMockMode && displayCartInfo) {
|
itemPrice: productPrice,
|
||||||
displayCartInfo.forEach(item => {
|
itemOption: optionPrice,
|
||||||
if (!cache.has(item.prodSno || item.cartId)) {
|
itemShipping: shippingPrice,
|
||||||
|
runningTotal: totalItems
|
||||||
const orderSummary = calculateOrderSummaryFromProductInfo(item);
|
|
||||||
cache.set(item.prodSno || item.cartId, {
|
|
||||||
price: orderSummary.items,
|
|
||||||
coupon: 0,
|
|
||||||
shipping: orderSummary.shipping
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return cache;
|
const subtotal = Math.max(0, totalItems + totalOption + totalShipping);
|
||||||
}, [isMockMode, displayCartInfo]);
|
|
||||||
|
|
||||||
// Mock 데이터 또는 실제 데이터 계산 (선택된 상품만) - 최적화 버전
|
if (DEBUG_LOG) {
|
||||||
const calculatedData = useMemo(() => {
|
console.log('[CartSidebar] Final calculation:', {
|
||||||
const DEBUG_LOG = false; // 수동 설정: false로 비활성화
|
isCheckedMode: checkedItems && checkedItems.length > 0,
|
||||||
|
itemCount: itemsToCalculate.length,
|
||||||
if (isMockMode) {
|
totalQuantity,
|
||||||
// Mock Mode: 선택된 상품들로 개별 가격 계산 (캐시 사용)
|
totalItems,
|
||||||
if (displayCartInfo && Array.isArray(displayCartInfo) && displayCartInfo.length > 0) {
|
totalOption,
|
||||||
const selectedCartItems = getSelectedItems(displayCartInfo);
|
totalShipping,
|
||||||
|
subtotal,
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] Selected items for calculation:', selectedCartItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 캐시된 가격 정보 사용
|
|
||||||
let totalItems = 0;
|
|
||||||
let totalCoupon = 0;
|
|
||||||
let totalShipping = 0;
|
|
||||||
let totalQuantity = 0;
|
|
||||||
|
|
||||||
selectedCartItems.forEach((item) => {
|
|
||||||
const itemId = item.prodSno || item.cartId;
|
|
||||||
const cachedPrice = itemPriceCache.get(itemId);
|
|
||||||
|
|
||||||
if (cachedPrice) {
|
|
||||||
const qty = item.prodQty || item.qty || 1;
|
|
||||||
totalItems += cachedPrice.price * qty;
|
|
||||||
totalCoupon += cachedPrice.coupon * qty;
|
|
||||||
totalShipping += cachedPrice.shipping * qty;
|
|
||||||
totalQuantity += qty;
|
|
||||||
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] Item calculation (cached):', {
|
|
||||||
name: item.prdtNm,
|
|
||||||
qty,
|
|
||||||
itemPrice: cachedPrice.price,
|
|
||||||
itemCoupon: cachedPrice.coupon,
|
|
||||||
itemShipping: cachedPrice.shipping,
|
|
||||||
runningTotal: totalItems
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const subtotal = Math.max(0, totalItems - totalCoupon + totalShipping);
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] Final calculation for selected items:', {
|
|
||||||
totalQuantity,
|
|
||||||
totalItems,
|
|
||||||
totalCoupon,
|
|
||||||
totalShipping,
|
|
||||||
subtotal,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
itemCount: totalQuantity,
|
|
||||||
subtotal: totalItems,
|
|
||||||
optionTotal: totalCoupon,
|
|
||||||
shippingHandling: totalShipping,
|
|
||||||
orderTotalBeforeTax: subtotal,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Mock Mode에 데이터가 없는 경우
|
|
||||||
return {
|
|
||||||
itemCount: 0,
|
|
||||||
subtotal: 0,
|
|
||||||
optionTotal: 0,
|
|
||||||
shippingHandling: 0,
|
|
||||||
orderTotalBeforeTax: 0,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} else if (displayCartInfo && Array.isArray(displayCartInfo) && displayCartInfo.length > 0) {
|
|
||||||
// API Mode: 실제 장바구니 데이터로 계산
|
|
||||||
const itemCount = displayCartInfo.reduce((sum, item) => sum + (item.prodQty || 1), 0);
|
|
||||||
const subtotal = displayCartInfo.reduce((sum, item) => {
|
|
||||||
const price = parseFloat(Number(item.price3) !== 0 ? Number(item.price3) : Number(item.price2) !== 0 ? Number(item.price2) : 0);
|
|
||||||
return sum + (price * (item.prodQty || 1));
|
|
||||||
}, 0);
|
|
||||||
const optionTotal = displayCartInfo.reduce((sum, item) => {
|
|
||||||
const optionPrice = parseFloat(Number(item.price5) || Number(item.optPrc) || 0);
|
|
||||||
return sum + (optionPrice * (item.prodQty || 1));
|
|
||||||
}, 0);
|
|
||||||
const shippingHandling = displayCartInfo.reduce((sum, item) => {
|
|
||||||
return sum + parseFloat(Number(item.shippingCharge) * (item.prodQty || 1))
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
itemCount,
|
itemCount: totalQuantity,
|
||||||
subtotal,
|
subtotal: totalItems,
|
||||||
optionTotal,
|
optionTotal: totalOption,
|
||||||
shippingHandling,
|
shippingHandling: totalShipping,
|
||||||
orderTotalBeforeTax: subtotal + optionTotal + shippingHandling,
|
orderTotalBeforeTax: subtotal,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// 데이터가 없는 경우
|
// 상품이 없는 경우
|
||||||
return {
|
return {
|
||||||
itemCount: 0,
|
itemCount: 0,
|
||||||
subtotal: 0,
|
subtotal: 0,
|
||||||
@@ -203,175 +211,129 @@ const CartSidebar = ({ cartInfo }) => {
|
|||||||
orderTotalBeforeTax: 0,
|
orderTotalBeforeTax: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [isMockMode, displayCartInfo, getSelectedItems, itemPriceCache]);
|
}, [itemsToCalculate, checkedItems]);
|
||||||
|
|
||||||
// 체크아웃 버튼 클릭 핸들러 - 완전한 데이터 전송
|
// 체크아웃 버튼 클릭 핸들러
|
||||||
const handleCheckoutClick = useCallback(() => {
|
const handleCheckoutClick = useCallback(() => {
|
||||||
const DEBUG_LOG = true; // 수동 설정: true로 활성화 (디버깅용)
|
const DEBUG_LOG = true; // 수동 설정: true로 활성화 (디버깅용)
|
||||||
|
|
||||||
console.log('[CartSidebar] 🎯 Checkout button clicked! Starting checkout process...');
|
console.log('[CartSidebar] 🎯 Checkout button clicked! Starting checkout process...');
|
||||||
console.log('[CartSidebar] 📊 Current state:', {
|
console.log('[CartSidebar] 📊 Current state:', {
|
||||||
isMockMode,
|
isMockMode,
|
||||||
totalItems: cartInfo?.length || 0,
|
checkedItemsCount: checkedItems.length,
|
||||||
selectedItemsCount: selectedItems.length
|
itemsToCalculateCount: itemsToCalculate.length
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isMockMode) {
|
// ✅ 계산할 상품이 없는 경우
|
||||||
// Mock Mode: 선택된 상품들로 CheckOutPanel로 이동
|
if (itemsToCalculate.length === 0) {
|
||||||
if (DEBUG_LOG) {
|
console.log('[CartSidebar] ❌ No items to checkout');
|
||||||
console.log('[CartSidebar] Mock Mode - Going to Checkout');
|
return;
|
||||||
console.log('[CartSidebar] Mock Mode - cartInfo:', JSON.stringify(cartInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ 선택된 상품들만 필터링 (체크박스 선택된 상품)
|
|
||||||
const allCartItems = cartInfo && Array.isArray(cartInfo) ? cartInfo : [];
|
|
||||||
const selectedCartItems = getSelectedItems(allCartItems);
|
|
||||||
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] Mock Mode - All cart items:', allCartItems.length);
|
|
||||||
console.log('[CartSidebar] Mock Mode - Selected cart items:', selectedCartItems.length);
|
|
||||||
console.log('[CartSidebar] Mock Mode - Selected items:', JSON.stringify(selectedCartItems));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 선택된 상품이 없는 경우
|
|
||||||
if (selectedCartItems.length === 0) {
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] Mock Mode - No items selected, cannot proceed to checkout');
|
|
||||||
}
|
|
||||||
return; // 아무것도 하지 않음
|
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ CheckOutPanel 전송용 데이터 구성 (CheckOutPanel 기대 구조에 맞춤)
|
|
||||||
const checkoutData = {
|
|
||||||
// 하위 호환성: 첫 번째 상품을 productInfo로
|
|
||||||
productInfo: selectedCartItems[0],
|
|
||||||
|
|
||||||
// ✅ CheckOutPanel이 기대하는 cartItems 필드 (isFromCart=true일 때 사용)
|
|
||||||
cartItems: selectedCartItems.map(item => ({
|
|
||||||
prdtId: item.prdtId,
|
|
||||||
prdtNm: item.prdtNm,
|
|
||||||
patnrId: item.patnrId,
|
|
||||||
patncNm: item.patncNm,
|
|
||||||
price2: item.price2, // 원가
|
|
||||||
price3: item.price3, // 할인가
|
|
||||||
price5: item.price5, // 쿠폰
|
|
||||||
prodQty: item.prodQty || item.qty || 1,
|
|
||||||
optNm: item.optNm,
|
|
||||||
shippingCharge: item.shippingCharge || '0',
|
|
||||||
// 추가 필드들
|
|
||||||
finalPrice: item.finalPrice,
|
|
||||||
discountPrice: item.discountPrice,
|
|
||||||
origPrice: item.origPrice,
|
|
||||||
priceInfo: item.priceInfo,
|
|
||||||
// 이미지 정보
|
|
||||||
imgUrl: item.imgUrl,
|
|
||||||
thumbnailUrl: item.thumbnailUrl,
|
|
||||||
imgUrls600: item.imgUrls600
|
|
||||||
})),
|
|
||||||
|
|
||||||
// 메타데이터
|
|
||||||
isFromCart: true,
|
|
||||||
fromCartPanel: true, // 추가 확인용
|
|
||||||
cartTotal: orderTotalBeforeTax,
|
|
||||||
itemCount: itemCount,
|
|
||||||
subtotal: subtotal,
|
|
||||||
optionTotal: optionTotal,
|
|
||||||
shippingHandling: shippingHandling
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('%c🚨🚨🚨 CART SIDEBAR CHECKOUT DATA ANALYSIS 🚨🚨🚨', 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;');
|
|
||||||
console.log('%cOriginal cartInfo:', 'background: yellow; color: black; padding: 3px;', cartInfo);
|
|
||||||
console.log('%c🔍 ORIGINAL CART ITEM 1 PRICE FIELDS:', 'background: magenta; color: white; padding: 3px;');
|
|
||||||
console.log('price2:', cartInfo?.[0]?.price2);
|
|
||||||
console.log('price3:', cartInfo?.[0]?.price3);
|
|
||||||
console.log('price5:', cartInfo?.[0]?.price5);
|
|
||||||
console.log('optPrc:', cartInfo?.[0]?.optPrc);
|
|
||||||
console.log('finalPrice:', cartInfo?.[0]?.finalPrice);
|
|
||||||
console.log('discountPrice:', cartInfo?.[0]?.discountPrice);
|
|
||||||
console.log('price:', cartInfo?.[0]?.price);
|
|
||||||
console.log('origPrice:', cartInfo?.[0]?.origPrice);
|
|
||||||
console.log('Full first item:', cartInfo?.[0]);
|
|
||||||
console.log('%cSelected items array:', 'background: yellow; color: black; padding: 3px;', selectedItems);
|
|
||||||
console.log('%cSelected cart items (filtered):', 'background: yellow; color: black; padding: 3px;', selectedCartItems);
|
|
||||||
console.log('%cCheckout data prepared:', 'background: yellow; color: black; padding: 3px;', checkoutData);
|
|
||||||
console.log('%cCartItems count:', 'background: yellow; color: black; padding: 3px;', checkoutData.cartItems.length);
|
|
||||||
console.log('%cCartItems details:', 'background: yellow; color: black; padding: 3px;', checkoutData.cartItems);
|
|
||||||
console.log('%cisFromCart value:', 'background: yellow; color: black; padding: 3px;', checkoutData.isFromCart);
|
|
||||||
console.log('%cAbout to pushPanel to CHECKOUT_PANEL', 'background: yellow; color: black; padding: 3px;');
|
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ CheckOutPanel로 이동
|
|
||||||
console.log('[CartSidebar] 🚀 Executing pushPanel to CHECKOUT_PANEL');
|
|
||||||
console.log('[CartSidebar] 📦 Checkout data summary:', {
|
|
||||||
itemCount: checkoutData.cartItems?.length || 0,
|
|
||||||
cartTotal: checkoutData.cartTotal,
|
|
||||||
hasProductInfo: !!checkoutData.productInfo,
|
|
||||||
isFromCart: checkoutData.isFromCart,
|
|
||||||
panelName: Config.panel_names.CHECKOUT_PANEL
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
dispatch(pushPanel({
|
|
||||||
name: Config.panel_names.CHECKOUT_PANEL,
|
|
||||||
panelInfo: checkoutData
|
|
||||||
}));
|
|
||||||
console.log('[CartSidebar] ✅ pushPanel executed successfully');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[CartSidebar] ❌ pushPanel failed:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// API Mode: 실제 API 데이터로 처리
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] API Mode - Checkout (to be implemented)');
|
|
||||||
}
|
|
||||||
|
|
||||||
// API Mode에서도 동일한 로직 적용
|
|
||||||
const allCartItems = cartInfo && Array.isArray(cartInfo) ? cartInfo : [];
|
|
||||||
const selectedCartItems = getSelectedItems(allCartItems);
|
|
||||||
|
|
||||||
if (selectedCartItems.length === 0) {
|
|
||||||
if (DEBUG_LOG) {
|
|
||||||
console.log('[CartSidebar] API Mode - No items selected, cannot proceed to checkout');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkoutData = {
|
|
||||||
productInfo: selectedCartItems[0],
|
|
||||||
cartItems: selectedCartItems.map(item => ({
|
|
||||||
prdtId: item.prdtId,
|
|
||||||
prdtNm: item.prdtNm,
|
|
||||||
patnrId: item.patnrId,
|
|
||||||
patncNm: item.patncNm,
|
|
||||||
price2: item.price2,
|
|
||||||
price3: item.price3,
|
|
||||||
price5: item.price5,
|
|
||||||
prodQty: item.prodQty || item.qty || 1,
|
|
||||||
optNm: item.optNm,
|
|
||||||
shippingCharge: item.shippingCharge || '0'
|
|
||||||
})),
|
|
||||||
isFromCart: true,
|
|
||||||
fromCartPanel: true, // 추가 확인용
|
|
||||||
cartTotal: orderTotalBeforeTax,
|
|
||||||
itemCount: itemCount
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatch(pushPanel({
|
|
||||||
name: Config.panel_names.CHECKOUT_PANEL,
|
|
||||||
panelInfo: checkoutData
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}, [dispatch, isMockMode, cartInfo, getSelectedItems, orderTotalBeforeTax, itemCount, subtotal, optionTotal, shippingHandling]);
|
|
||||||
|
if (DEBUG_LOG) {
|
||||||
|
console.log('[CartSidebar] Items to checkout:', JSON.stringify(itemsToCalculate));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ CheckOutPanel 전송용 데이터 구성
|
||||||
|
const { itemCount, subtotal, optionTotal, shippingHandling, orderTotalBeforeTax } = calculatedData;
|
||||||
|
|
||||||
|
const checkoutData = {
|
||||||
|
// 하위 호환성: 첫 번째 상품을 productInfo로
|
||||||
|
productInfo: itemsToCalculate[0],
|
||||||
|
|
||||||
|
// ✅ CheckOutPanel이 기대하는 cartItems 필드
|
||||||
|
cartItems: itemsToCalculate.map(item => ({
|
||||||
|
prdtId: item.prdtId,
|
||||||
|
prdtNm: item.prdtNm,
|
||||||
|
patnrId: item.patnrId,
|
||||||
|
patncNm: item.patncNm,
|
||||||
|
price2: item.price2, // 원가
|
||||||
|
price3: item.price3, // 할인가
|
||||||
|
price5: item.price5, // 옵션가
|
||||||
|
prodQty: item.prodQty || item.qty || 1,
|
||||||
|
optNm: item.optNm,
|
||||||
|
shippingCharge: item.shippingCharge || '0',
|
||||||
|
// 추가 필드들
|
||||||
|
finalPrice: item.finalPrice,
|
||||||
|
discountPrice: item.discountPrice,
|
||||||
|
origPrice: item.origPrice,
|
||||||
|
priceInfo: item.priceInfo,
|
||||||
|
// 이미지 정보
|
||||||
|
imgUrl: item.imgUrl,
|
||||||
|
thumbnailUrl: item.thumbnailUrl,
|
||||||
|
imgUrls600: item.imgUrls600,
|
||||||
|
prodSno: item.prodSno,
|
||||||
|
})),
|
||||||
|
|
||||||
|
// 메타데이터
|
||||||
|
isFromCart: true,
|
||||||
|
fromCartPanel: true,
|
||||||
|
isCheckedMode: checkedItems && checkedItems.length > 0, // ✅ 체크 모드 여부
|
||||||
|
cartTotal: orderTotalBeforeTax,
|
||||||
|
itemCount: itemCount,
|
||||||
|
subtotal: subtotal,
|
||||||
|
optionTotal: optionTotal,
|
||||||
|
shippingHandling: shippingHandling
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DEBUG_LOG) {
|
||||||
|
console.log('%c🚨🚨🚨 CART SIDEBAR CHECKOUT DATA 🚨🚨🚨', 'background: yellow; color: black; font-weight: bold; font-size: 14px; padding: 5px;');
|
||||||
|
console.log('%cMode:', 'background: yellow; color: black; padding: 3px;', checkedItems.length > 0 ? 'CHECKED ITEMS MODE' : 'ALL ITEMS MODE');
|
||||||
|
console.log('%cItems to checkout:', 'background: yellow; color: black; padding: 3px;', itemsToCalculate);
|
||||||
|
console.log('%cCheckout data prepared:', 'background: yellow; color: black; padding: 3px;', checkoutData);
|
||||||
|
console.log('%cCartItems count:', 'background: yellow; color: black; padding: 3px;', checkoutData.cartItems.length);
|
||||||
|
console.log('%cCalculated totals:', 'background: yellow; color: black; padding: 3px;', {
|
||||||
|
itemCount,
|
||||||
|
subtotal,
|
||||||
|
optionTotal,
|
||||||
|
shippingHandling,
|
||||||
|
orderTotalBeforeTax
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ CheckOutPanel로 이동
|
||||||
|
console.log('[CartSidebar] 🚀 Executing pushPanel to CHECKOUT_PANEL');
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(
|
||||||
|
getMyInfoCheckoutInfo(
|
||||||
|
{
|
||||||
|
mbrNo: userNumber,
|
||||||
|
dirPurcSelYn: 'Y',
|
||||||
|
cartList:
|
||||||
|
checkedItems && checkedItems.map((item) => ({
|
||||||
|
patnrId: item.patnrId,
|
||||||
|
prdtId: item.prdtId,
|
||||||
|
prodOptCdCval: item.prodOptCdCval ? item.prodOptCdCval : null,
|
||||||
|
prodQty: String(item.prodQty),
|
||||||
|
prodOptTpCdCval: item.prodOptTpCdCval,
|
||||||
|
}))
|
||||||
|
|
||||||
|
},
|
||||||
|
checkOutValidate
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// dispatch(pushPanel({
|
||||||
|
// name: Config.panel_names.CHECKOUT_PANEL,
|
||||||
|
// panelInfo: checkoutData
|
||||||
|
// }));
|
||||||
|
console.log('[CartSidebar] ✅ pushPanel executed successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[CartSidebar] ❌ pushPanel failed:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [dispatch, checkedItems, itemsToCalculate, calculatedData]);
|
||||||
|
|
||||||
const { itemCount, subtotal, optionTotal, shippingHandling, orderTotalBeforeTax } = calculatedData;
|
const { itemCount, subtotal, optionTotal, shippingHandling, orderTotalBeforeTax } = calculatedData;
|
||||||
|
|
||||||
const formatPrice = (price) => {
|
const formatPrice = (price) => {
|
||||||
return `$${price.toLocaleString('en-US', {
|
return `$${price.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}`;
|
})}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -429,6 +391,7 @@ const CartSidebar = ({ cartInfo }) => {
|
|||||||
className={css.checkoutButton}
|
className={css.checkoutButton}
|
||||||
spotlightId="cart-checkout-button"
|
spotlightId="cart-checkout-button"
|
||||||
onClick={handleCheckoutClick}
|
onClick={handleCheckoutClick}
|
||||||
|
disabled={itemsToCalculate.length === 0}
|
||||||
>
|
>
|
||||||
Checkout
|
Checkout
|
||||||
</TButton>
|
</TButton>
|
||||||
@@ -437,4 +400,4 @@ const CartSidebar = ({ cartInfo }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CartSidebar;
|
export default CartSidebar;
|
||||||
@@ -138,6 +138,7 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
const empTermsData = useSelector((state) => state.emp.empTermsData.terms);
|
const empTermsData = useSelector((state) => state.emp.empTermsData.terms);
|
||||||
const { popupVisible, activePopup } = useSelector((state) => state.common.popup);
|
const { popupVisible, activePopup } = useSelector((state) => state.common.popup);
|
||||||
const popup = 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에서 상품 데이터 사용
|
// Mock Mode: panelInfo.productInfo 또는 Redux에서 상품 데이터 사용
|
||||||
const productData = BUYNOW_CONFIG.isMockMode()
|
const productData = BUYNOW_CONFIG.isMockMode()
|
||||||
@@ -360,9 +361,10 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
getCheckoutTotalAmt(
|
getCheckoutTotalAmt(
|
||||||
{
|
{
|
||||||
mbrNo: userNumber,
|
mbrNo: userNumber,
|
||||||
dirPurcSelYn: 'Y',
|
dirPurcSelYn: cartSelectInfo.length > 0 ? 'N' : 'Y',
|
||||||
bilAddrSno: infoForCheckoutData.bilAddrSno,
|
bilAddrSno: infoForCheckoutData.bilAddrSno,
|
||||||
dlvrAddrSno: infoForCheckoutData.dlvrAddrSno,
|
dlvrAddrSno: infoForCheckoutData.dlvrAddrSno,
|
||||||
|
isPageLoading: "Y",
|
||||||
orderProductCoupontUse,
|
orderProductCoupontUse,
|
||||||
},
|
},
|
||||||
totalAmtValidate
|
totalAmtValidate
|
||||||
@@ -667,7 +669,7 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
closeSideBar={toggleOrderSideBar}
|
closeSideBar={toggleOrderSideBar}
|
||||||
productData={safeProductData}
|
productData={safeProductData}
|
||||||
rawProductData={productData}
|
rawProductData={productData}
|
||||||
productInfo={panelInfo?.productInfo}
|
productInfo={reduxProductData}
|
||||||
fromCartPanel={panelInfo?.fromCartPanel}
|
fromCartPanel={panelInfo?.fromCartPanel}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export default function OrderItemsSideBar({
|
|||||||
patncLogPath={item.patncLogPath}
|
patncLogPath={item.patncLogPath}
|
||||||
prdtId={item.prdtId}
|
prdtId={item.prdtId}
|
||||||
expsPrdtNo={item.expsPrdtNo}
|
expsPrdtNo={item.expsPrdtNo}
|
||||||
price={item.price2 >= item.price3 ? item.price3 : item.price2}
|
price={(item.price2 >= item.price3 && item.price3 !== 0) ? item.price3 : item.price2}
|
||||||
currSign={item.currSign}
|
currSign={item.currSign}
|
||||||
currSignLoc={item.currSignLoc}
|
currSignLoc={item.currSignLoc}
|
||||||
shippingCharge={item.shippingCharge}
|
shippingCharge={item.shippingCharge}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default function SummaryContainer({
|
|||||||
|
|
||||||
// Check if priceTotalData has actual data (ordPmtReqAmt is the key field)
|
// Check if priceTotalData has actual data (ordPmtReqAmt is the key field)
|
||||||
const hasValidPriceTotalData = priceTotalData && Object.keys(priceTotalData).length > 0 && priceTotalData.ordPmtReqAmt;
|
const hasValidPriceTotalData = priceTotalData && Object.keys(priceTotalData).length > 0 && priceTotalData.ordPmtReqAmt;
|
||||||
|
console.log("###hasValidPriceTotalData",hasValidPriceTotalData)
|
||||||
// Mock Mode: priceTotalData가 없으면 가짜 데이터 제공
|
// Mock Mode: priceTotalData가 없으면 가짜 데이터 제공
|
||||||
const effectivePriceTotalData = hasValidPriceTotalData ? priceTotalData : {
|
const effectivePriceTotalData = hasValidPriceTotalData ? priceTotalData : {
|
||||||
totProdPrc: 0.00,
|
totProdPrc: 0.00,
|
||||||
|
|||||||
Reference in New Issue
Block a user