From 301e00298590d74d2029515b02e1ef4b9feeda1c Mon Sep 17 00:00:00 2001 From: "junghoon86.park" Date: Wed, 12 Nov 2025 19:40:55 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=B6=94=EA=B0=80]#1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 작업 진행중 - api로 데이터 보내도록 처리중. --- .../src/actions/actionTypes.js | 7 +- .../src/actions/cartActions.js | 145 ++++++++++++++++++ com.twin.app.shoptime/src/api/apiConfig.js | 9 +- .../src/reducers/cartReducer.js | 66 +++++++- .../src/views/CartPanel/CartPanel.jsx | 3 +- .../src/views/CartPanel/CartProduct.jsx | 18 ++- .../DetailPanel/components/BuyOption.jsx | 14 +- 7 files changed, 244 insertions(+), 18 deletions(-) diff --git a/com.twin.app.shoptime/src/actions/actionTypes.js b/com.twin.app.shoptime/src/actions/actionTypes.js index 2cc6e5a3..cffa6b8b 100644 --- a/com.twin.app.shoptime/src/actions/actionTypes.js +++ b/com.twin.app.shoptime/src/actions/actionTypes.js @@ -76,11 +76,16 @@ export const types = { GET_MY_INFO_SHIPPING_SEARCH: 'GET_MY_INFO_SHIPPING_SEARCH', // cart actions - GET_MY_INFO_CART_SEARCH: 'GET_MY_INFO_CART_SEARCH', ADD_TO_CART: 'ADD_TO_CART', REMOVE_FROM_CART: 'REMOVE_FROM_CART', UPDATE_CART_ITEM: 'UPDATE_CART_ITEM', CLEAR_CART: 'CLEAR_CART', + //cart api action + GET_MY_INFO_CART_SEARCH: 'GET_MY_INFO_CART_SEARCH', + INSERT_MY_INFO_CART : "INSERT_MY_INFO_CART", + DELETE_MY_INFO_CART : "DELETE_MY_INFO_CART", + DELETE_ALL_MY_INFO_CART : "DELETE_ALL_MY_INFO_CART", + UPDATE_MY_INFO_CART : "UPDATE_MY_INFO_CART", // appData actions ADD_MAIN_INDEX: 'ADD_MAIN_INDEX', diff --git a/com.twin.app.shoptime/src/actions/cartActions.js b/com.twin.app.shoptime/src/actions/cartActions.js index 4f6f9c8b..f63c5ae5 100644 --- a/com.twin.app.shoptime/src/actions/cartActions.js +++ b/com.twin.app.shoptime/src/actions/cartActions.js @@ -50,6 +50,151 @@ export const getMyInfoCartSearch = (props) => (dispatch, getState) => { ); }; +/** + * 장바구니 상품 추가 API + */ +export const insertMyinfoCart = (props) => (dispatch, getState) => { + const { mbrNo, patnrId, prdtId, prdtOpt, prodQty } = props; + + const onSuccess = (response) => { + console.log("✅ insertMyinfoCart API 성공:", response.data); + if (response.data.retCode !== '0' && response.data.retCode !== 0) { + console.error("❌ retCode 에러:", response.data.retCode); + console.error("에러 메시지:", response.data.retMsg); + + return; + } + // response.data.data가 실제 상품 정보인지 확인 + if (!response.data.data) { + console.warn("⚠️ response.data.data가 undefined입니다"); + } + + dispatch({ + type: types.INSERT_MY_INFO_CART, + payload: response.data.data, + }); + + dispatch(getMyInfoCartSearch({ mbrNo })); + }; + + const onFail = (error) => { + console.error("insertMyinfoCart OnFail: ", error); + }; + + TAxios( + dispatch, + getState, + "post", + URLS.INSERT_MY_INFO_CART, + {}, + { mbrNo, patnrId, prdtId, prdtOpt, prodQty }, + onSuccess, + onFail + ); +}; + +/** + * 장바구니 상품 삭제 API + */ +export const deleteMyinfoCart = (props) => (dispatch, getState) => { + const { mbrNo, patnrId, prdtId, prodSno } = props; + + const onSuccess = (response) => { + console.log("deleteMyinfoCart onSuccess: ", response.data); + + dispatch({ + type: types.DELETE_MY_INFO_CART, + payload: response.data.data, + }); + + // 장바구니 목록 재조회 + dispatch(getMyInfoCartSearch({ mbrNo })); + }; + + const onFail = (error) => { + console.error("deleteMyinfoCart OnFail: ", error); + }; + + TAxios( + dispatch, + getState, + "post", + URLS.DELETE_MY_INFO_CART, + {}, + { mbrNo, patnrId, prdtId, prodSno }, + onSuccess, + onFail + ); +}; + +/** + * 장바구니 상품 전체 삭제 + */ +export const deleteAllMyinfoCart = (props) => (dispatch, getState) => { + const { mbrNo } = props; + + const onSuccess = (response) => { + console.log("deleteAllMyinfoCart onSuccess: ", response.data); + + dispatch({ + type: types.DELETE_ALL_MY_INFO_CART, + payload: response.data.data, + }); + + // 장바구니 목록 재조회 + dispatch(getMyInfoCartSearch({ mbrNo })); + }; + + const onFail = (error) => { + console.error("deleteAllMyinfoCart OnFail: ", error); + }; + + TAxios( + dispatch, + getState, + "post", + URLS.DELETE_ALL_MY_INFO_CART, + {}, + { mbrNo }, + onSuccess, + onFail + ); +}; + +/** + * 장바구니 상품 수정 + */ +export const updateMyinfoCart = (props) => (dispatch, getState) => { + const { mbrNo, patnrId, prdtId, prodQty, prodSno } = props; + + const onSuccess = (response) => { + console.log("updateMyinfoCart onSuccess: ", response.data); + + dispatch({ + type: types.UPDATE_MY_INFO_CART, + payload: response.data.data, + }); + + // 장바구니 목록 재조회 + dispatch(getMyInfoCartSearch({ mbrNo })); + }; + + const onFail = (error) => { + console.error("updateMyinfoCart OnFail: ", error); + }; + + TAxios( + dispatch, + getState, + "post", + URLS.UPDATE_MY_INFO_CART, + {}, + { mbrNo, patnrId, prdtId, prodQty, prodSno }, + onSuccess, + onFail + ); +}; + /** * 장바구니에 상품 추가 * @param {Object} props - 장바구니 상품 정보 diff --git a/com.twin.app.shoptime/src/api/apiConfig.js b/com.twin.app.shoptime/src/api/apiConfig.js index f37d181d..71fbec14 100644 --- a/com.twin.app.shoptime/src/api/apiConfig.js +++ b/com.twin.app.shoptime/src/api/apiConfig.js @@ -20,10 +20,15 @@ export const URLS = { GET_MY_INFO_CARD_SEARCH: "/lgsp/v1/myinfo/card/search.lge", // cart controller - GET_MY_INFO_CART_SEARCH: "/lgsp/v1/myinfo/cart/search.lge", ADD_TO_CART: "/lgsp/v1/myinfo/cart/add.lge", REMOVE_FROM_CART: "/lgsp/v1/myinfo/cart/remove.lge", - UPDATE_CART_ITEM: "/lgsp/v1/myinfo/cart/update.lge", + UPDATE_CART_ITEM: "/lgsp/v1/myinfo/cart/update.lge", + // cart api + GET_MY_INFO_CART_SEARCH: "/lgsp/v1/myinfo/cart/search.lge", + INSERT_MY_INFO_CART: "/lgsp/v1/myinfo/cart/add.lge", + DELETE_MY_INFO_CART : "/lgsp/v1/myinfo/cart/delete.lge", + DELETE_ALL_MY_INFO_CART : "/lgsp/v1/myinfo/cart/deleteAll.lge", + UPDATE_MY_INFO_CART : "/lgsp/v1/myinfo/cart/update.lge", // shipping controller GET_MY_INFO_SHIPPING_SEARCH: "/lgsp/v1/myinfo/address/shipping/search.lge", diff --git a/com.twin.app.shoptime/src/reducers/cartReducer.js b/com.twin.app.shoptime/src/reducers/cartReducer.js index d0d14f6d..b576a605 100644 --- a/com.twin.app.shoptime/src/reducers/cartReducer.js +++ b/com.twin.app.shoptime/src/reducers/cartReducer.js @@ -1,4 +1,4 @@ -import { types } from "../actions/actionTypes"; +import { types } from '../actions/actionTypes'; /** * Cart Reducer 초기 상태 @@ -18,9 +18,9 @@ const initialState = { * Cart Reducer * 장바구니 관련 상태를 관리합니다. */ -export const cartReducer = (state = initialState, action) => { +export const cartReducer = (state = initialState, action) => { switch (action.type) { - // 장바구니 조회 + // 장바구니 조회 - API에서 가져온 전체 목록 case types.GET_MY_INFO_CART_SEARCH: return { ...state, @@ -32,6 +32,56 @@ export const cartReducer = (state = initialState, action) => { }; // 장바구니에 상품 추가 + case types.INSERT_MY_INFO_CART: + return { + ...state, + getMyinfoCartSearch: { + ...state.getMyinfoCartSearch, + cartList: [...state.getMyinfoCartSearch.cartList, action.payload], + totalCount: (state.getMyinfoCartSearch.totalCount || 0) + 1, + }, + lastAction: { + type: "insert", + data: action.payload, + timestamp: Date.now(), + }, + error: null, + }; + + // 장바구니에서 상품 삭제 + case types.DELETE_MY_INFO_CART: + return { + ...state, + getMyinfoCartSearch: { + ...state.getMyinfoCartSearch, + cartList: state.getMyinfoCartSearch.cartList.filter( + item => item.prodSno !== action.payload.prodSno + ), + totalCount: Math.max(0, (state.getMyinfoCartSearch.totalCount || 0) - 1), + }, + lastAction: { + type: "delete", + data: action.payload, + timestamp: Date.now(), + }, + error: null, + }; + + case types.UPDATE_MY_INFO_CART: + return { + ...state, + getMyinfoCartSearch: { + ...state.getMyinfoCartSearch, + cartList: state.getMyinfoCartSearch.cartList.map(item => + item.prodSno === action.payload.prodSno + ? { ...item, ...action.payload } + : item + ), + }, + error: null, + }; + + // 장바구니에 상품 추가 (addToCart - 로컬 상태용) case types.ADD_TO_CART: return { ...state, @@ -43,7 +93,7 @@ export const cartReducer = (state = initialState, action) => { error: null, }; - // 장바구니에서 상품 제거 + // 장바구니에서 상품 제거 (removeFromCart) case types.REMOVE_FROM_CART: return { ...state, @@ -55,19 +105,19 @@ export const cartReducer = (state = initialState, action) => { error: null, }; - // 장바구니 상품 수량 업데이트 + // 장바구니 상품 수량 업데이트 (updateCartItem) case types.UPDATE_CART_ITEM: return { ...state, lastAction: { - type: "update", + type: "updateQty", data: action.payload, timestamp: Date.now(), }, error: null, }; - // 장바구니 전체 비우기 + // 장바구니 전체 비우기 (clearCart - 로컬 상태 전용) case types.CLEAR_CART: return { ...state, @@ -85,4 +135,4 @@ export const cartReducer = (state = initialState, action) => { default: return state; } -}; +}; \ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/CartPanel/CartPanel.jsx b/com.twin.app.shoptime/src/views/CartPanel/CartPanel.jsx index ef78a4c1..a835bbd5 100644 --- a/com.twin.app.shoptime/src/views/CartPanel/CartPanel.jsx +++ b/com.twin.app.shoptime/src/views/CartPanel/CartPanel.jsx @@ -46,7 +46,8 @@ export default function CartPanel({ spotlightId, scrollOptions = [], panelInfo } ); // Mock Mode 여부 확인 및 적절한 데이터 선택 - const isMockMode = BUYNOW_CONFIG.isMockMode(); + // const isMockMode = BUYNOW_CONFIG.isMockMode(); + const isMockMode = false; const displayCartData = useMemo(() => { return isMockMode ? mockCartData : cartData; }, [isMockMode, mockCartData, cartData]); diff --git a/com.twin.app.shoptime/src/views/CartPanel/CartProduct.jsx b/com.twin.app.shoptime/src/views/CartPanel/CartProduct.jsx index 5a82fb49..5227dd52 100644 --- a/com.twin.app.shoptime/src/views/CartPanel/CartProduct.jsx +++ b/com.twin.app.shoptime/src/views/CartPanel/CartProduct.jsx @@ -18,6 +18,7 @@ import SpotlightContainerDecorator import logoImage from '../../../assets/images/ic-partners-qvc@3x.png'; import defaultImage from '../../../assets/images/img-thumb-empty-144@3x.png'; import { + deleteMyinfoCart, removeFromCart, updateCartItem, } from '../../actions/cartActions'; @@ -264,6 +265,21 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { [scrollTop] ); + //장바구니 삭제 + const deleteCart = (patnrId, prdtId, prodSno) => { + const { userNumber } = store.getState().common.appStatus.loginUserData; + console.log("###test",userNumber, + patnrId, + prdtId, + prodSno) + // dispatch(deleteMyinfoCart({ + // mbrNo : userNumber, + // patnrId, + // prdtId, + // prodSno + // })) + } + return ( <> {Object.entries(groupedCartData).map(([partnerKey, group], index) => { @@ -433,7 +449,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { handleDeleteClick(item.prodSno)} + onClick={() => deleteCart(item.patnrId, item.prdtId, item.prodSno)} /> diff --git a/com.twin.app.shoptime/src/views/DetailPanel/components/BuyOption.jsx b/com.twin.app.shoptime/src/views/DetailPanel/components/BuyOption.jsx index 827b1610..a53c9078 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/components/BuyOption.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/components/BuyOption.jsx @@ -15,7 +15,10 @@ import Spotlight from '@enact/spotlight'; import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; -import { addToCart } from '../../../actions/cartActions'; +import { + addToCart, + insertMyinfoCart, +} from '../../../actions/cartActions'; import { getMyInfoCheckoutInfo } from '../../../actions/checkoutActions'; import { changeAppStatus, @@ -1084,17 +1087,18 @@ const BuyOption = ({ if (!isMock) { dispatch( - addToCart({ + insertMyinfoCart({ mbrNo: userNumber, patnrId: selectedPatnrId, prdtId: selectedPrdtId, - prodQty: String(effectiveQuantity), + prodQty: Number(effectiveQuantity), prdtOpt: { - prodOptCdCval: optionForUse?.prodOptCdCval || '', - prodOptCval: optionLabel, prodOptSno: productOptionInfos?.[0]?.prodOptSno || '', + prodOptCdCval: optionForUse?.prodOptCdCval || '', prodOptTpCdCval: productOptionInfos?.[0]?.prodOptTpCdCval || '', + prodOptCval: optionLabel, }, + }) );