diff --git a/com.twin.app.shoptime/src/actions/actionTypes.js b/com.twin.app.shoptime/src/actions/actionTypes.js index ba5f877d..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', @@ -308,11 +313,8 @@ export const types = { SET_MODAL_BORDER: 'SET_MODAL_BORDER', SET_BANNER_VISIBILITY: 'SET_BANNER_VISIBILITY', - // πŸ”½ [μΆ”κ°€] JustForYou μƒν’ˆ 관리 λΆ€λΆ„ - GET_RECENTLY_SAW_ITEM: 'GET_RECENTLY_SAW_ITEM', - GET_LIKE_BRAND_PRODUCT: 'GET_LIKE_BRAND_PRODUCT', - GET_MORE_TO_CONCIDER_AT_THIS_PRICE: 'GET_MORE_TO_CONCIDER_AT_THIS_PRICE', - GET_JUSTFORYOU_INFO: 'GET_JUSTFORYOU_INFO', + // πŸ”½ [μΆ”κ°€] JustForYou μƒν’ˆ 관리 λΆ€λΆ„ + JUSTFORYOU: 'JUSTFORYOU', // πŸ”½ Voice Conductor κ΄€λ ¨ μ•‘μ…˜ νƒ€μž… VOICE_REGISTER_SUCCESS: 'VOICE_REGISTER_SUCCESS', diff --git a/com.twin.app.shoptime/src/actions/cartActions.js b/com.twin.app.shoptime/src/actions/cartActions.js index 4f6f9c8b..70258e5e 100644 --- a/com.twin.app.shoptime/src/actions/cartActions.js +++ b/com.twin.app.shoptime/src/actions/cartActions.js @@ -1,6 +1,7 @@ import { URLS } from '../api/apiConfig'; import { TAxios } from '../api/TAxios'; import { types } from './actionTypes'; +import { showError } from './commonActions'; /** * νšŒμ› μž₯λ°”κ΅¬λ‹ˆ 정보 쑰회 @@ -50,6 +51,160 @@ 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.retCode); + // if (response.data?.retCode !== '0' && response.data.retCode !== 0) { + // console.error("❌ retCode μ—λŸ¬:", response.data.retCode); + // console.error("μ—λŸ¬ λ©”μ‹œμ§€:", response.data.retMsg); + + // return; + // } + + if (response.data.retCode === 0) { + dispatch({ + type: types.INSERT_MY_INFO_CART, + payload: response.data.data, + }); + dispatch(getMyInfoCartSearch({ mbrNo })); + } else { + dispatch( + showError( + response.data.retCode, + response.data.retMsg, + false, + null, + null + ) + ); + console.error("❌ retCode μ—λŸ¬:", response.data.retCode); + console.error("μ—λŸ¬ λ©”μ‹œμ§€:", response.data.retMsg); + } + }; + + 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/actions/convertActions.js b/com.twin.app.shoptime/src/actions/convertActions.js index afeccf8a..9b12062a 100644 --- a/com.twin.app.shoptime/src/actions/convertActions.js +++ b/com.twin.app.shoptime/src/actions/convertActions.js @@ -1,6 +1,7 @@ import { URLS } from '../api/apiConfig'; import { TAxios } from '../api/TAxios'; import { types } from './actionTypes'; +import { getReAuthenticationCode } from './deviceActions'; /** * PDFλ₯Ό μ΄λ―Έμ§€λ‘œ λ³€ν™˜ (μž¬μ‹œλ„ 둜직 포함) @@ -52,10 +53,10 @@ export const convertPdfToImage = clearTimeout(timeoutId); timeoutId = null; } - + // retCode 체크 (ν”„λ‘œμ νŠΈ API κ·œμ•½: 200이어도 retCode둜 성곡/μ‹€νŒ¨ ꡬ뢄) const retCode = response.headers?.retcode || response.headers?.retCode; - + if (retCode !== undefined && retCode !== 0 && retCode !== '0') { const error = new Error(`API Error: retCode=${retCode}`); console.warn(`⚠️ [EnergyLabel] API returned error on attempt ${attempts}:`, retCode); @@ -79,56 +80,62 @@ export const convertPdfToImage = } return; } - - let imageUrl; - try { - if (response.data instanceof Blob) { - if (response.data.size === 0) { - throw new Error('Invalid image data (empty blob)'); - } - imageUrl = URL.createObjectURL(response.data); - } else if (response.data instanceof ArrayBuffer) { - if (response.data.byteLength === 0) { - throw new Error('Invalid image data (empty buffer)'); - } - const blob = new Blob([response.data], { type: 'image/png' }); - imageUrl = URL.createObjectURL(blob); - } else { - const blob = new Blob([response.data], { type: 'image/png' }); - if (blob.size === 0) { - throw new Error('Invalid image data (empty blob)'); - } - imageUrl = URL.createObjectURL(blob); - } - - console.log(`βœ… [EnergyLabel] Conversion successful on attempt ${attempts}:`, pdfUrl); - dispatch({ - type: types.CONVERT_PDF_TO_IMAGE_SUCCESS, - payload: { pdfUrl, imageUrl }, - }); - - callback && callback(null, imageUrl); - } catch (error) { - console.error(`❌ [EnergyLabel] Image creation failed on attempt ${attempts}:`, error); - - // 이미지 생성 μ‹€νŒ¨λ„ μž¬μ‹œλ„ - if (attempts < maxRetries + 1) { - console.log( - `πŸ”„ [EnergyLabel] Retrying due to image creation error... (${attempts}/${maxRetries + 1})` - ); + + if(response.data.type !== "image/png"){ + dispatch(getReAuthenticationCode()); attemptConversion(); - } else { - console.error( - `❌ [EnergyLabel] Final failure after ${attempts} attempts (image error):`, - pdfUrl - ); - dispatch({ - type: types.CONVERT_PDF_TO_IMAGE_FAILURE, - payload: { pdfUrl, error }, - }); - callback && callback(error, null); + return; + } + + let imageUrl; + try { + if (response.data instanceof Blob) { + if (response.data.size === 0) { + throw new Error('Invalid image data (empty blob)'); + } + imageUrl = URL.createObjectURL(response.data); + } else if (response.data instanceof ArrayBuffer) { + if (response.data.byteLength === 0) { + throw new Error('Invalid image data (empty buffer)'); + } + const blob = new Blob([response.data], { type: 'image/png' }); + imageUrl = URL.createObjectURL(blob); + } else { + const blob = new Blob([response.data], { type: 'image/png' }); + if (blob.size === 0) { + throw new Error('Invalid image data (empty blob)'); + } + imageUrl = URL.createObjectURL(blob); + } + + console.log(`βœ… [EnergyLabel] Conversion successful on attempt ${attempts}:`, pdfUrl); + dispatch({ + type: types.CONVERT_PDF_TO_IMAGE_SUCCESS, + payload: { pdfUrl, imageUrl }, + }); + + callback && callback(null, imageUrl); + } catch (error) { + console.error(`❌ [EnergyLabel] Image creation failed on attempt ${attempts}:`, error); + + // 이미지 생성 μ‹€νŒ¨λ„ μž¬μ‹œλ„ + if (attempts < maxRetries + 1) { + console.log( + `πŸ”„ [EnergyLabel] Retrying due to image creation error... (${attempts}/${maxRetries + 1})` + ); + attemptConversion(); + } else { + console.error( + `❌ [EnergyLabel] Final failure after ${attempts} attempts (image error):`, + pdfUrl + ); + dispatch({ + type: types.CONVERT_PDF_TO_IMAGE_FAILURE, + payload: { pdfUrl, error }, + }); + callback && callback(error, null); + } } - } }; const onFail = (error) => { diff --git a/com.twin.app.shoptime/src/actions/forYouActions.js b/com.twin.app.shoptime/src/actions/forYouActions.js index 5844d7df..18445341 100644 --- a/com.twin.app.shoptime/src/actions/forYouActions.js +++ b/com.twin.app.shoptime/src/actions/forYouActions.js @@ -1,36 +1,16 @@ import { URLS } from '../api/apiConfig'; import { TAxios } from '../api/TAxios'; -import { - curry, - get, - set, -} from '../utils/fp'; +import { get } from '../utils/fp'; import { types } from './actionTypes'; import { changeAppStatus } from './commonActions'; -// 졜근 λ³Έ μ•„μ΄ν…œ κ΄€λ ¨ μ•‘μ…˜ -export const getRecentlySawItem = (data) => ({ - type: types.GET_RECENTLY_SAW_ITEM, - payload: data, -}); - -// μ’‹μ•„ν•˜λŠ” λΈŒλžœλ“œ μ œν’ˆ κ΄€λ ¨ μ•‘μ…˜ -export const getLikeBrandProduct = (data) => ({ - type: types.GET_LIKE_BRAND_PRODUCT, - payload: data, -}); - -// 이 κ°€κ²©λŒ€μ—μ„œ κ³ λ €ν•  λ§Œν•œ 더 λ§Žμ€ μ œν’ˆ κ΄€λ ¨ μ•‘μ…˜ -export const getMoreToConciderAtThisPrice = (data) => ({ - type: types.GET_MORE_TO_CONCIDER_AT_THIS_PRICE, - payload: data, -}); - -export const getJustForYouInfo = (callback) => (dispatch, getState) => { +export const justForYou = (callback) => (dispatch, getState) => { + const macAddress = getState().common.macAddress; + const macAddr = macAddress?.wired || macAddress?.wifi || "00:1A:2B:3C:4D:5E"; const onSuccess = (response) => { - console.log("getJustForYouInfo onSuccess", response.data); + console.log("JustForYou onSuccess", response.data); dispatch({ - type: types.GET_JUSTFORYOU_INFO, + type: types.JUSTFORYOU, payload: get("data.data", response), }); dispatch(changeAppStatus({ showLoadingPanel: { show: false } })); @@ -38,7 +18,7 @@ export const getJustForYouInfo = (callback) => (dispatch, getState) => { }; const onFail = (error) => { - console.error("getJustForYouInfo onFail", error); + console.error("JustForYou onFail", error); dispatch(changeAppStatus({ showLoadingPanel: { show: false } })); callback && callback(); }; @@ -46,10 +26,10 @@ export const getJustForYouInfo = (callback) => (dispatch, getState) => { TAxios( dispatch, getState, - "get", - URLS.GET_JUSTFORYOU_INFO, - {}, + "post", + URLS.JUSTFORYOU, {}, + {macAddr}, onSuccess, onFail ); diff --git a/com.twin.app.shoptime/src/actions/mainActions.js b/com.twin.app.shoptime/src/actions/mainActions.js index e1469564..448b4f1d 100644 --- a/com.twin.app.shoptime/src/actions/mainActions.js +++ b/com.twin.app.shoptime/src/actions/mainActions.js @@ -1,10 +1,18 @@ import { URLS } from '../api/apiConfig'; import { TAxios } from '../api/TAxios'; import { convertUtcToLocal } from '../components/MediaPlayer/util'; -import { CATEGORY_DATA_MAX_RESULTS_LIMIT, LOG_CONTEXT_NAME, LOG_MESSAGE_ID } from '../utils/Config'; +import { + CATEGORY_DATA_MAX_RESULTS_LIMIT, + LOG_CONTEXT_NAME, + LOG_MESSAGE_ID, +} from '../utils/Config'; import * as HelperMethods from '../utils/helperMethods'; import { types } from './actionTypes'; -import { addReservation, changeAppStatus, deleteReservation } from './commonActions'; +import { + addReservation, + changeAppStatus, + deleteReservation, +} from './commonActions'; //IF-LGSP-007 export const getMainLiveShow = (props) => (dispatch, getState) => { @@ -155,7 +163,7 @@ let lastSubCategoryParams = {}; export const getSubCategory = (params, pageNo = 1, key = null, clear = false) => (dispatch, getState) => { - const { lgCatCd, patnrIdList, tabType, filterType } = params; + const { lgCatCd, patnrIdList, tabType, filterType, recommendIncFlag } = params; let pageSize = params.pageSize || CATEGORY_DATA_MAX_RESULTS_LIMIT; if (pageNo === 1) { @@ -179,21 +187,34 @@ export const getSubCategory = if (pageNo === 1) { getSubCategoryKey = new Date(); currentKey = getSubCategoryKey; + + // βœ… recommendProduct 뢄리 + const { recommendProduct, ...restData } = response.data.data; + dispatch({ type: types.GET_SUB_CATEGORY, - payload: response.data.data, + payload: { + ...restData, + recommendProduct, + }, categoryParams: { lgCatCd, patnrIdList, tabType, filterType, + recommendIncFlag, pageSize, }, }); } else if (getSubCategoryKey === currentKey) { + const { recommendProduct, ...restData } = response.data.data; + dispatch({ type: types.GET_SUB_CATEGORY, - payload: response.data.data, + payload: { + ...restData, + recommendProduct, + }, append: true, startIndex: (pageNo - 1) * pageSize, }); @@ -212,7 +233,7 @@ export const getSubCategory = getState, 'get', URLS.GET_SUB_CATEGORY, - { lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType }, + { lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType,recommendIncFlag }, {}, onSuccess, onFail diff --git a/com.twin.app.shoptime/src/api/apiConfig.js b/com.twin.app.shoptime/src/api/apiConfig.js index b8e8d15f..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", @@ -141,8 +146,9 @@ export const URLS = { UPDATE_ORDER_PARTIAL_CANCEL: "/lgsp/v1/myinfo/order/orderPartialCancel.lge", PAYMENT_TOTAL_CANCEL: "/lgsp/v1/myinfo/order/paymentTotalCancel.lge", - // foryou controller - GET_JUSTFORYOU_INFO: "/lgsp/v1/justforyou/list.lge", + // foryou controller + JUSTFORYOU: "/lgsp/v1/recommend/justforyou.lge", + // emp controller GET_SHOPTIME_TERMS: "/lgsp/v1/emp/shoptime/terms.lge", diff --git a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less index c3ad8c47..dee8ea6e 100644 --- a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less +++ b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.module.less @@ -245,7 +245,7 @@ > p { font-weight: bold; - font-size: 30px; + font-size: 28px; color: @PRIMARY_COLOR_RED; margin-top: 8px; diff --git a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx index 346c9372..dd1792f3 100644 --- a/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx +++ b/com.twin.app.shoptime/src/components/TItemCard/TItemCard.new.jsx @@ -86,7 +86,7 @@ export const removeDotAndColon = (string) => { }; const parsePrice = (price) => { - return parseFloat(price?.replace(/[^0-9.-]+/g, "") || "0"); + return parseFloat(price?.replace(/[^0-9.-]+/g, "").replace("οΏ‘","") || "0"); }; const generateMockEnergyLabels = (productId) => { @@ -474,12 +474,18 @@ export default memo(function TItemCardNew({ className={classNames( css.descWrap, catNm && css.hstNmWrap, - parsePrice(originPrice) >= 1000 && - parsePrice(dcPrice) >= 1000 && + (parsePrice(originalPrice) >= 1000 || parsePrice(originPrice) >= 1000 ) && + (parsePrice(discountedPrice) >= 1000 || parsePrice(dcPrice) >= 1000 ) && + euEnrgLblInfos?.length > 0 && + euEnrgLblInfos[0]?.enrgLblIcnUrl !== null && + euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined && (countryCode === "GB" || countryCode === "DE") && css.labelBox, - parsePrice(originPrice) >= 10000 && - parsePrice(dcPrice) >= 10000 && + (parsePrice(originalPrice) >= 10000 || parsePrice(originPrice) >= 10000 ) && + (parsePrice(discountedPrice) >= 10000 || parsePrice(dcPrice) >= 10000 ) && + euEnrgLblInfos?.length > 0 && + euEnrgLblInfos[0]?.enrgLblIcnUrl !== null && + euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined && (countryCode === "GB" || countryCode === "DE") && css.labelOverBox )} @@ -525,11 +531,11 @@ export default memo(function TItemCardNew({ )} {(() => { - const hasValidApiData = + {/* const hasValidApiData = euEnrgLblInfos?.length > 0 && euEnrgLblInfos[0]?.enrgLblIcnUrl !== null && - euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined; - + euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined; */} + const hasValidApiData = true; let energyLabels; if (CURRENT_ENERGY_LABEL_MODE === ENERGY_LABEL_MODE.API_ONLY) { @@ -550,7 +556,11 @@ export default memo(function TItemCardNew({ } return ( - (countryCode === "GB" || countryCode === "DE") && ( + (countryCode === "GB" || countryCode === "DE") && + (euEnrgLblInfos?.length > 0 && + euEnrgLblInfos[0]?.enrgLblIcnUrl !== null && + euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined) && + (
{type !== "videoShow" && energyLabels diff --git a/com.twin.app.shoptime/src/reducers/cartReducer.js b/com.twin.app.shoptime/src/reducers/cartReducer.js index d0d14f6d..a4a7143c 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,43 @@ 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, + }, + }; + + // μž₯λ°”κ΅¬λ‹ˆμ—μ„œ μƒν’ˆ μ‚­μ œ + 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), + }, + }; + + 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 + ), + }, + }; + + // μž₯λ°”κ΅¬λ‹ˆμ— μƒν’ˆ μΆ”κ°€ (addToCart - 둜컬 μƒνƒœμš©) case types.ADD_TO_CART: return { ...state, @@ -43,7 +80,7 @@ export const cartReducer = (state = initialState, action) => { error: null, }; - // μž₯λ°”κ΅¬λ‹ˆμ—μ„œ μƒν’ˆ 제거 + // μž₯λ°”κ΅¬λ‹ˆμ—μ„œ μƒν’ˆ 제거 (removeFromCart) case types.REMOVE_FROM_CART: return { ...state, @@ -55,19 +92,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 +122,4 @@ export const cartReducer = (state = initialState, action) => { default: return state; } -}; +}; \ No newline at end of file diff --git a/com.twin.app.shoptime/src/reducers/forYouReducer.js b/com.twin.app.shoptime/src/reducers/forYouReducer.js index c899f5d4..bdd344c6 100644 --- a/com.twin.app.shoptime/src/reducers/forYouReducer.js +++ b/com.twin.app.shoptime/src/reducers/forYouReducer.js @@ -5,50 +5,16 @@ import { set, } from '../utils/fp'; -// 초기 μƒνƒœ μ •μ˜ -// const initialState = { -// recentlySawItems: [], -// likeBrandProducts: [], -// moreToConciderAtThisPrice: [], -// }; const initialState = { - justForYouInfo: {}, + recommendInfo: {}, }; -// const foryouReducer = (state = initialState, action) => { -// switch (action.type) { -// // 졜근 λ³Έ μ•„μ΄ν…œ -// case types.GET_RECENTLY_SAW_ITEM: -// return { -// ...state, -// recentlySawItems: action.payload, -// }; - -// // μ’‹μ•„ν•˜λŠ” λΈŒλžœλ“œ μ œν’ˆ -// case types.GET_LIKE_BRAND_PRODUCT: -// return { -// ...state, -// likeBrandProducts: action.payload, -// }; - -// // 이 κ°€κ²©λŒ€μ—μ„œ κ³ λ €ν•  λ§Œν•œ 더 λ§Žμ€ μ œν’ˆ -// case types.GET_MORE_TO_CONCIDER_AT_THIS_PRICE: -// return { -// ...state, -// moreToConciderAtThisPrice: action.payload, -// }; - -// default: -// return state; -// } -// }; - -const justForYouInfo = curry((state, action) => - set("justForYouInfo", get("payload", action), state) +const recommendInfo = curry((state, action) => + set("recommendInfo", get("payload", action), state) ); const handlers = { - [types.GET_JUSTFORYOU_INFO]: justForYouInfo, + [types.JUSTFORYOU]: recommendInfo, }; export const foryouReducer = (state = initialState, action = {}) => { diff --git a/com.twin.app.shoptime/src/reducers/mainReducer.js b/com.twin.app.shoptime/src/reducers/mainReducer.js index a66815c7..8143b9f5 100644 --- a/com.twin.app.shoptime/src/reducers/mainReducer.js +++ b/com.twin.app.shoptime/src/reducers/mainReducer.js @@ -10,11 +10,13 @@ const initialState = { showDetailInfo: [], showNowInfo: null, featuredShowsInfos: {}, + recommendProduct: null, categoryParams: { lgCatCd: null, patnrIdList: null, tabType: null, filterType: null, + recommendIncFlag: null, pageSize: CATEGORY_DATA_MAX_RESULTS_LIMIT, }, }; @@ -39,6 +41,7 @@ export const mainReducer = (state = initialState, action) => { categoryFilterCd: action.payload.categoryFilterCd, topShowInfo: action.payload.topShowInfo, partnerInfos: action.payload.partnerInfos, + recommendProduct: action.payload.recommendProduct, categoryParams: action.categoryParams, }; } @@ -63,6 +66,7 @@ export const mainReducer = (state = initialState, action) => { categoryFilterCd: action.payload.categoryFilterCd, topShowInfo: action.payload.topShowInfo, partnerInfos: action.payload.partnerInfos, + recommendProduct: action.payload.recommendProduct, categoryParams: action.categoryParams, }; } @@ -93,6 +97,7 @@ export const mainReducer = (state = initialState, action) => { categoryFilterCd: action.payload.categoryFilterCd, topShowInfo: action.payload.topShowInfo, partnerInfos: action.payload.partnerInfos, + recommendProduct: action.payload.recommendProduct, }; } else { return { @@ -107,6 +112,7 @@ export const mainReducer = (state = initialState, action) => { categoryFilterCd: action.payload.categoryFilterCd, topShowInfo: action.payload.topShowInfo, partnerInfos: action.payload.partnerInfos, + recommendProduct: action.payload.recommendProduct, categoryParams: action.categoryParams, }; } @@ -206,6 +212,7 @@ export const mainReducer = (state = initialState, action) => { return { ...state, subCategoryData: {}, + recommendProduct: null, }; default: diff --git a/com.twin.app.shoptime/src/utils/Config.js b/com.twin.app.shoptime/src/utils/Config.js index 9be17c52..8d7bd238 100644 --- a/com.twin.app.shoptime/src/utils/Config.js +++ b/com.twin.app.shoptime/src/utils/Config.js @@ -79,6 +79,7 @@ export const ACTIVE_POPUP = { exitPopup: 'exitPopup', favoritePopup: 'favoritePopup', loginPopup: 'loginPopup', + logoutPopup: 'logoutPopup', noShowPopup: 'noShowPopup', optionPopup: 'optionPopup', qrPopup: 'qrPopup', @@ -292,6 +293,7 @@ export const LOG_MENU = { HOME_ON_SALE: 'Home/On Sale', HOME_POPULAR_SHOWS: 'Home/Popular Shows', HOME_BEST_SELLER: 'Home/Best Sellers', + HOME_PICKED_FOR_YOU: 'Home/Picked For You', TRENDING_NOW_POPULAR_SHOWS: 'Trending Now/Popular Shows', TRENDING_NOW_BEST_SELLER: 'Trending Now/Best Sellers', 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 299e3195..8280d01e 100644 --- a/com.twin.app.shoptime/src/views/CartPanel/CartProduct.jsx +++ b/com.twin.app.shoptime/src/views/CartPanel/CartProduct.jsx @@ -11,19 +11,17 @@ import { useSelector, } from 'react-redux'; -import Spotlight from '@enact/spotlight'; import SpotlightContainerDecorator from '@enact/spotlight/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, + updateMyinfoCart, } from '../../actions/cartActions'; import { removeFromMockCart, - setMockCartItemQuantity, updateSelectedItems, } from '../../actions/mockCartActions'; import CustomImage from '../../components/CustomImage/CustomImage'; @@ -97,6 +95,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { // 항상 ν˜ΈμΆœλ˜μ–΄μ•Ό ν•˜λŠ” Hookλ“€ const fallbackCartData = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo); const selectedItems = useSelector((state) => state.mockCart.selectedItems || []); + const userNumber = useSelector((state) => state.common.appStatus.loginUserData.userNumber); // μ‹€μ œ μž₯λ°”κ΅¬λ‹ˆ 데이터와 Mock 데이터 쀑 선택 const cartData = cartInfo || fallbackCartData; @@ -138,12 +137,12 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { // νŒŒνŠΈλ„ˆμ‚¬λ³„ 총합 계산 const calculatePartnerTotal = (items) => { const productTotal = items.reduce((sum, item) => - sum + (parseFloat(item.price3 || item.price2 || 0) * item.prodQty), 0 + sum + (parseFloat(Number(item.price3) !== 0 ? Number(item.price3) : Number(item.price2) !== 0 ? Number(item.price2) : 0) * item.prodQty), 0 ); - // const optionTotal = items.reduce((sum, item) => - // sum + (parseFloat(item.optPrc.replace("$","") || 0) * item.prodQty), 0 - // ); - const optionTotal = 0; + 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 + ); + const shippingTotal = items.reduce((sum, item) => sum + parseFloat((item.shippingCharge) * item.prodQty || 0), 0 ); @@ -157,32 +156,38 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { }; // μˆ˜λŸ‰ 쑰절 ν•Έλ“€λŸ¬ - const handleDecreseClick = useCallback((prodSno, currentQty) => { + const handleDecreseClick = useCallback((prodSno, patnrId, prdtId, currentQty) => { if (currentQty > 1) { const newQty = currentQty - 1; if (isMockMode) { - dispatch(setMockCartItemQuantity(prodSno, newQty)); + // dispatch(setMockCartItemQuantity(prodSno, newQty)); } else { // μ‹€μ œ API ν˜ΈμΆœμ„ μœ„ν•œ μ‚¬μš©μž 정보 ν•„μš” - const { userNumber } = store.getState().common.appStatus.loginUserData; + if (userNumber) { - dispatch(updateCartItem({ mbrNo: userNumber, cartSno: prodSno, prodQty: newQty })); + dispatch(updateMyinfoCart({ + mbrNo: userNumber, + patnrId, + prdtId, + prodSno, + prodQty: newQty + })); } } } }, [dispatch, isMockMode]); - const handleIncreseClick = useCallback((prodSno, currentQty) => { + const handleIncreseClick = useCallback((prodSno, patnrId, prdtId, currentQty) => { const newQty = currentQty + 1; if (isMockMode) { - dispatch(setMockCartItemQuantity(prodSno, newQty)); + // dispatch(setMockCartItemQuantity(prodSno, newQty)); } else { // μ‹€μ œ API ν˜ΈμΆœμ„ μœ„ν•œ μ‚¬μš©μž 정보 ν•„μš” - const { userNumber } = store.getState().common.appStatus.loginUserData; + if (userNumber) { - dispatch(updateCartItem({ mbrNo: userNumber, cartSno: prodSno, prodQty: newQty })); + dispatch(updateMyinfoCart({ mbrNo: userNumber, patnrId, prdtId, prodSno, prodQty: newQty })); } } }, [dispatch, isMockMode]); @@ -264,11 +269,20 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { [scrollTop] ); + //μž₯λ°”κ΅¬λ‹ˆ μ‚­μ œ + const deleteCart = useCallback((patnrId, prdtId, prodSno) => { + dispatch(deleteMyinfoCart({ + mbrNo : userNumber, + patnrId: String(patnrId), + prdtId : String(prdtId), + prodSno : String(prodSno) + })) + },[dispatch]) + return ( <> {Object.entries(groupedCartData).map(([partnerKey, group], index) => { const totals = calculatePartnerTotal(group.items); - return ( {index === 0 && ( @@ -298,13 +312,15 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { Product Total ${totals.productTotal.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 - })} + - - {/* Option ${totals.optionTotal.toLocaleString('en-US', { + })} + + {totals.optionTotal > 0 && ( + <> + Option ${totals.optionTotal.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 - })} + */} - Option $0.00 + + })} + + + )} S&H ${totals.shippingTotal.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 @@ -372,20 +388,22 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { )}
- ${parseFloat(item.price3 || item.price2 || 0).toLocaleString('en-US', { + ${parseFloat(Number(item.price3) > 0 ? Number(item.price3) : Number(item.price2) > 0 ? Number(item.price2) : 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {item.price2 && ( + {item.price2 && (parseFloat(item.price2) > 0 && parseFloat(item.price3) > 0 && parseFloat(item.price2) !== parseFloat(item.price3)) && ( + <> ${parseFloat(item.price2).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} - + )} + {item.price5 && parseFloat(item.price5) > 0 && ( OPTION : ${parseFloat(item.price5).toLocaleString('en-US', { @@ -411,13 +429,13 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => { item.prodQty === 1 ? css.dimm : "" )} size="cartEa" - onClick={() => handleDecreseClick(item.prodSno, item.prodQty)} + onClick={() => handleDecreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)} spotlightId={"pd_ea_decrese"} spotlightDisabled={item.prodQty === 1} />
{item.prodQty}
handleIncreseClick(item.prodSno, item.prodQty)} + onClick={() => handleIncreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)} className={css.plusBox} spotlightId={"pd_ea_increse"} size="cartEa" @@ -430,7 +448,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/CartPanel/CartSidebar.jsx b/com.twin.app.shoptime/src/views/CartPanel/CartSidebar.jsx index 8c869a0a..b850ac53 100644 --- a/com.twin.app.shoptime/src/views/CartPanel/CartSidebar.jsx +++ b/com.twin.app.shoptime/src/views/CartPanel/CartSidebar.jsx @@ -175,16 +175,16 @@ const CartSidebar = ({ cartInfo }) => { // API Mode: μ‹€μ œ μž₯λ°”κ΅¬λ‹ˆ λ°μ΄ν„°λ‘œ 계산 const itemCount = displayCartInfo.reduce((sum, item) => sum + (item.prodQty || 1), 0); const subtotal = displayCartInfo.reduce((sum, item) => { - const price = parseFloat(item.price3 || item.price2 || 0); + 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(item.price5 || item.optPrc || 0); + const optionPrice = parseFloat(Number(item.price5) || Number(item.optPrc) || 0); return sum + (optionPrice * (item.prodQty || 1)); }, 0); - const shippingHandling = displayCartInfo.reduce((sum, item) => - sum + parseFloat(item.shippingCharge || 0), 0 - ); + const shippingHandling = displayCartInfo.reduce((sum, item) => { + return sum + parseFloat(Number(item.shippingCharge) * (item.prodQty || 1)) + }, 0); return { itemCount, diff --git a/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.jsx b/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.jsx index d4c980a3..42d8c1b6 100644 --- a/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.jsx +++ b/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.jsx @@ -79,6 +79,7 @@ export default function ItemContents({ onClick }) { lastLabel=" go to detail, button" data-wheel-point={index >= 5} euEnrgLblInfos={euEnrgLblInfos} + className={css.itemCardNewCate} /> ); })} diff --git a/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.module.less b/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.module.less index 7a15773a..d19d221d 100644 --- a/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.module.less +++ b/com.twin.app.shoptime/src/views/CategoryPanel/CategoryContents/ItemContents/ItemContents.module.less @@ -6,7 +6,7 @@ display: flex; flex-wrap: wrap; margin-top: 34px; - > div { + > div.itemCardNewCate { margin: 0 15px 15px 0; } } diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx index b9d43c1f..361a73eb 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/CheckOutPanel.jsx @@ -30,7 +30,10 @@ import { sendLogPaymentEntry, sendLogTotalRecommend, } from '../../actions/logActions'; -import { popPanel, updatePanel } from '../../actions/panelActions'; +import { + popPanel, + updatePanel, +} from '../../actions/panelActions'; import TBody from '../../components/TBody/TBody'; import TButton from '../../components/TButton/TButton'; import TButtonScroller from '../../components/TButtonScroller/TButtonScroller'; @@ -615,7 +618,7 @@ export default function CheckOutPanel({ panelInfo }) {
- {BUYNOW_CONFIG.isMockMode() ? ( + {/* {BUYNOW_CONFIG.isMockMode() ? ( - ) : ( + ) : ( */} - )} - {BUYNOW_CONFIG.isMockMode() ? ( + {/* )} */} + {/* {BUYNOW_CONFIG.isMockMode() ? ( - ) : ( + ) : ( */} - )} + {/* )} */}
diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/components/OrderItemCard.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/components/OrderItemCard.jsx index 1cc71093..3353f526 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/components/OrderItemCard.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/components/OrderItemCard.jsx @@ -41,7 +41,6 @@ export default memo(function OrderItemCard({ const priceTotalData = useSelector( (state) => state.checkout?.checkoutTotalData ); - console.log("###priceTotalData",priceTotalData); const formattedPrices = useMemo(() => { return { @@ -83,7 +82,7 @@ export default memo(function OrderItemCard({

- $ {(price * prodQty).toLocaleString('en-US', { + $ {(Number(price) * Number(prodQty)).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/container/InformationContainer.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/container/InformationContainer.jsx index 5cbdfebc..ede5c703 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/container/InformationContainer.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/container/InformationContainer.jsx @@ -1,27 +1,42 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; import Spotlight from '@enact/spotlight'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; -import { setHidePopup, setShowPopup } from '../../../actions/commonActions'; +import { + setHidePopup, + setShowPopup, +} from '../../../actions/commonActions'; +import { sendLogTotalRecommend } from '../../../actions/logActions'; import { popPanel } from '../../../actions/panelActions'; import TButton from '../../../components/TButton/TButton'; import TPopUp from '../../../components/TPopUp/TPopUp'; import TQRCode from '../../../components/TQRCode/TQRCode'; import useScrollTo from '../../../hooks/useScrollTo'; import useScrollTopByDistance from '../../../hooks/useScrollTopByDistance'; +import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig'; import * as Config from '../../../utils/Config'; -import { $L, getQRCodeUrl } from '../../../utils/helperMethods'; +import { + $L, + getQRCodeUrl, +} from '../../../utils/helperMethods'; import BillingAddressCard from '../components/BillingAddressCard'; import PaymentCard from '../components/PaymentCard'; import ShippingAddressCard from '../components/ShippingAddressCard'; import Subject from '../components/Subject'; import css from './InformationContainer.module.less'; -import { sendLogTotalRecommend } from '../../../actions/logActions'; -import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig'; const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); @@ -282,9 +297,12 @@ export default function InformationContainer({ ADD/EDIT {/* BillingAddressCard disabled due to infinite render loop in Mock Mode */} -

+ {/*
Mock Billing Address -
+
*/} + {checkoutData?.billingAddressList && ( + + )}
diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/container/OrderItemsSideBar.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/container/OrderItemsSideBar.jsx index 82838475..35700b0e 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/container/OrderItemsSideBar.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/container/OrderItemsSideBar.jsx @@ -165,7 +165,7 @@ export default function OrderItemsSideBar({ patncLogPath={item.patncLogPath} prdtId={item.prdtId} expsPrdtNo={item.expsPrdtNo} - price={item.price >= item.originalPrice ? item.originalPrice : item.price} + price={item.price2 >= item.price3 ? item.price3 : item.price2} currSign={item.currSign} currSignLoc={item.currSignLoc} shippingCharge={item.shippingCharge} diff --git a/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx b/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx index 4d8c99f1..c803ac1c 100644 --- a/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx +++ b/com.twin.app.shoptime/src/views/CheckOutPanel/container/SummaryCotainer.jsx @@ -1,21 +1,32 @@ -import React, { useCallback, useEffect, useMemo } from "react"; +import React, { + useCallback, + useEffect, + useMemo, +} from 'react'; -import { useDispatch, useSelector } from "react-redux"; +import { + useDispatch, + useSelector, +} from 'react-redux'; -import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; -import { setHidePopup, setShowPopup } from "../../../actions/commonActions"; -import { popPanel } from "../../../actions/panelActions"; -import TButton from "../../../components/TButton/TButton"; -import TPopUp from "../../../components/TPopUp/TPopUp"; -import * as Config from "../../../utils/Config"; +import { + setHidePopup, + setShowPopup, +} from '../../../actions/commonActions'; +import { sendLogTotalRecommend } from '../../../actions/logActions'; +import { popPanel } from '../../../actions/panelActions'; +import TButton from '../../../components/TButton/TButton'; +import TPopUp from '../../../components/TPopUp/TPopUp'; +import * as Config from '../../../utils/Config'; import { $L, formatCurrencyValue, getErrorMessage, -} from "../../../utils/helperMethods"; -import css from "./SummaryContainer.module.less"; -import { sendLogTotalRecommend } from "../../../actions/logActions"; +} from '../../../utils/helperMethods'; +import css from './SummaryContainer.module.less'; const Container = SpotlightContainerDecorator( { enterTo: "last-focused" }, @@ -51,12 +62,12 @@ export default function SummaryContainer({ // Mock Mode: priceTotalDataκ°€ μ—†μœΌλ©΄ κ°€μ§œ 데이터 제곡 const effectivePriceTotalData = hasValidPriceTotalData ? priceTotalData : { - totProdPrc: 521.66, + totProdPrc: 0.00, totDcAmt: 0, totDlvrAmt: 0, - ordPmtNoTaxAmt: 521.66, - ordTotTaxAmt: 50, - ordPmtReqAmt: 571.66 + ordPmtNoTaxAmt: 0.0, + ordTotTaxAmt: 0, + ordPmtReqAmt: 0.00, }; const items = useMemo( diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx index 812b75fd..f62f6892 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx @@ -185,6 +185,9 @@ export default function ProductAllSection({ const [isShowQRCode, setIsShowQRCode] = useState(true); const timerRef = useRef(null); + //ꡬ맀 ν•˜λ‹¨ ν† μŠ€νŠΈ λ…ΈμΆœ 확인을 μœ„ν•œ μš©λ„ + const [openToast, setOpenToast] = useState(false); + // λͺ¨λ“  timeout/timerλ₯Ό μΆ”μ ν•˜κΈ° μœ„ν•œ ref const timersRef = useRef([]); @@ -378,31 +381,36 @@ export default function ProductAllSection({ prdtNm: productData?.prdtNm, hasProductData: !!productData, }); - - dispatch( - showToast({ - id: productData.prdtId, - message: '', - type: 'buyOption', - duration: 0, - position: 'bottom-center', - // πŸš€ BuyOption에 전달할 props 데이터 - productInfo: productData, - selectedPatnrId: productData?.patnrId, - selectedPrdtId: productData?.prdtId, - // BuyOption Toastκ°€ λ‹«νž λ•Œ BUY NOW λ²„νŠΌμœΌλ‘œ 포컀슀 볡ꡬ - onToastClose: () => { - setTimeout(() => { - Spotlight.focus('detail-buy-now-button'); - }, 100); - }, - }) - ); - }, [dispatch, productData]); + if(openToast === false){ + dispatch( + showToast({ + id: productData.prdtId, + message: '', + type: 'buyOption', + duration: 0, + position: 'bottom-center', + // πŸš€ BuyOption에 전달할 props 데이터 + productInfo: productData, + selectedPatnrId: productData?.patnrId, + selectedPrdtId: productData?.prdtId, + // BuyOption Toastκ°€ λ‹«νž λ•Œ BUY NOW λ²„νŠΌμœΌλ‘œ 포컀슀 볡ꡬ + onToastClose: () => { + setTimeout(() => { + setOpenToast(false); + Spotlight.focus('detail-buy-now-button'); + }, 100); + }, + }) + ); + + setOpenToast(true); + } + }, [dispatch, productData, openToast]); //λ‹«νžˆλ„λ‘ const handleCloseToast = useCallback(() => { - dispatch(clearAllToasts()) + dispatch(clearAllToasts()); + setOpenToast(false); },[dispatch]) // 슀크둀 μ»¨ν…Œμ΄λ„ˆμ˜ 클릭 이벀트 μΆ”μ μš© λ‘œκΉ… diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx index c34f953a..5777d5b6 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.jsx @@ -1,20 +1,40 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; import { Job } from '@enact/core/util'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; import { clearThemeDetail } from '../../../../actions/homeActions'; -import { popPanel, pushPanel, updatePanel } from '../../../../actions/panelActions'; +import { + popPanel, + pushPanel, + updatePanel, +} from '../../../../actions/panelActions'; import { finishVideoPreview } from '../../../../actions/playActions'; import THeader from '../../../../components/THeader/THeader'; -import TItemCard from '../../../../components/TItemCard/TItemCard'; -import TVerticalPagenator from '../../../../components/TVerticalPagenator/TVerticalPagenator'; -import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList'; +import TItemCardNew from '../../../../components/TItemCard/TItemCard.new'; +import TVerticalPagenator + from '../../../../components/TVerticalPagenator/TVerticalPagenator'; +import TVirtualGridList + from '../../../../components/TVirtualGridList/TVirtualGridList'; import useScrollTo from '../../../../hooks/useScrollTo'; -import { LOG_CONTEXT_NAME, LOG_MESSAGE_ID, panel_names } from '../../../../utils/Config'; +import { + LOG_CONTEXT_NAME, + LOG_MESSAGE_ID, + panel_names, +} from '../../../../utils/Config'; import { $L } from '../../../../utils/helperMethods'; import css from './YouMayAlsoLike.module.less'; @@ -136,6 +156,7 @@ export default function YouMayAlsoLike({ patncNm, brndNm, lgCatCd, + euEnrgLblInfos, } = product; const handleItemClick = () => { @@ -166,8 +187,9 @@ export default function YouMayAlsoLike({ cursorOpen.current.stop(); }; return ( - ); })} diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.module.less b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.module.less index 0906deeb..fea0513d 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.module.less +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/YouMayAlsoLike/YouMayAlsoLike.module.less @@ -62,7 +62,7 @@ display: flex; flex-wrap: wrap; // margin-top: 34px; - > div { + > div.itemCardNew { /* item card */ margin: 0 15px 15px 0; .size(@w:360px,@h:494px); @@ -81,7 +81,7 @@ > div:nth-child(2) { margin-top: 15px; /* desc wrapper */ - > div > h3 { + > div > div > h3 { /* title */ color: rgba(234, 234, 234, 1); .size(@w:100%,@h:64px); diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.jsx index 24f242b5..15031a90 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.jsx @@ -1,19 +1,59 @@ import React, { useCallback, useMemo, + useState, } from 'react'; import classNames from 'classnames'; -import { useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; +import Spotlight from '@enact/spotlight'; +import Spottable from '@enact/spotlight/Spottable'; + +import { + setHidePopup, + setShowPopup, +} from '../../../../actions/commonActions'; +import { + clearConvertedImage, + convertPdfToImage, +} from '../../../../actions/convertActions'; +import CustomImage from '../../../../components/CustomImage/CustomImage'; +import TPopUp from '../../../../components/TPopUp/TPopUp'; import usePriceInfo from '../../../../hooks/usePriceInfo'; +import * as Config from '../../../../utils/Config'; import { $L } from '../../../../utils/helperMethods'; +import { SpotlightIds } from '../../../../utils/SpotlightIds'; import BuyNowPriceDisplay from './BuyNowPriceDisplay/BuyNowPriceDisplay'; import css from './ProductPriceDisplay.module.less'; import ShopByMobilePriceDisplay from './ShopByMobilePriceDisplay/ShopByMobilePriceDisplay'; +const SpottableComponent = Spottable("div"); + +const STRING_CONF = { + ENERGY_LOADING: "Loading energy label...", + ENERGY_ERROR: "Failed to load energy label", +}; + export default function ProductPriceDisplay({ productType, productInfo }) { + const dispatch = useDispatch(); + + const [currentPdfUrl, setCurrentPdfUrl] = useState(null); + + const cursorVisible = useSelector( + (state) => state.common.appStatus.cursorVisible + ); + const { activePopup, popupVisible } = useSelector( + (state) => state.common.popup + ); + + const convert = useSelector((state) => state.convert); + const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd); + const webOSVersion = useSelector( (state) => state.common.appStatus.webOSVersion ); @@ -27,6 +67,7 @@ export default function ProductPriceDisplay({ productType, productInfo }) { patnrName, installmentMonths, orderPhnNo, + euEnrgLblInfos, } = productInfo; const { @@ -65,6 +106,67 @@ export default function ProductPriceDisplay({ productType, productInfo }) { ); }, [productType, productInfo?.pmtSuptYn, webOSVersion]); + const handleClosePopup = useCallback(() => { + if (convert?.convertedImage && convert.convertedImage.startsWith("blob:")) { + URL.revokeObjectURL(convert.convertedImage); + } + + dispatch(setHidePopup()); + dispatch(clearConvertedImage()); + setCurrentPdfUrl(null); + }, [dispatch, convert?.convertedImage]); + + const onEnergyClick = useCallback( + (e, pdfUrl) => { + e.stopPropagation(); + setCurrentPdfUrl(pdfUrl); + + // PNG μ΄λ―Έμ§€λŠ” 직접 ν‘œμ‹œ + if (pdfUrl.endsWith(".png")) { + // console.log(`πŸ“Έ [EnergyLabel] Displaying PNG directly:`, pdfUrl); + dispatch({ + type: "CONVERT_PDF_TO_IMAGE_SUCCESS", + payload: { pdfUrl, imageUrl: pdfUrl }, + }); + dispatch(setShowPopup(Config.ACTIVE_POPUP.energyPopup)); + setTimeout(() => { + Spotlight.focus(SpotlightIds.TPOPUP); + }, 250); + return; + } + + // PDF λ³€ν™˜ μ‹œμž‘ (μ΅œλŒ€ 5회 μž¬μ‹œλ„, 60초 νƒ€μž„μ•„μ›ƒ) + // console.log(`πŸ“„ [EnergyLabel] Starting PDF conversion:`, pdfUrl); + dispatch( + convertPdfToImage( + pdfUrl, + (error, imageUrl) => { + if (error) { + console.error( + "[EnergyLabel] μ΅œμ’… λ³€ν™˜ μ‹€νŒ¨:", + error.message || error + ); + // μ‹€νŒ¨ν•΄λ„ νŒμ—…μ€ μ—΄μ–΄μ„œ μ—λŸ¬ λ©”μ‹œμ§€ ν‘œμ‹œ + dispatch(setShowPopup(Config.ACTIVE_POPUP.energyPopup)); + setTimeout(() => { + Spotlight.focus(SpotlightIds.TPOPUP); + }, 250); + } else { + console.log(`[EnergyLabel] PDF λ³€ν™˜ μ™„λ£Œ, νŒμ—… ν‘œμ‹œ`); + dispatch(setShowPopup(Config.ACTIVE_POPUP.energyPopup)); + setTimeout(() => { + Spotlight.focus(SpotlightIds.TPOPUP); + }, 250); + } + }, + 5, // μ΅œλŒ€ 5회 μž¬μ‹œλ„ + 60000 // 60초 νƒ€μž„μ•„μ›ƒ + ) + ); + }, + [dispatch] + ); + return ( <> {productType && productInfo && ( @@ -91,8 +193,125 @@ export default function ProductPriceDisplay({ productType, productInfo }) { isDiscounted={isDiscounted} /> )} +
+ {euEnrgLblInfos && (countryCode === "GB" || countryCode === "DE") && euEnrgLblInfos.map((item, index)=>{ + return( + onEnergyClick(e, item.enrgLblUrl)} + aria-label={`Energy Efficiency ${item.enrgGrade || ""}`} + className={css.enrgLbImg} + > + + + ) + })} +
)} + {(() => { + // νŒμ—…μ΄ ν‘œμ‹œλ˜μ–΄μ•Ό ν•˜λŠ” 쑰건 검증 + const isEnergyPopup = activePopup === Config.ACTIVE_POPUP.energyPopup; + const hasPdfUrl = !!currentPdfUrl; + const shouldShowPopup = isEnergyPopup && hasPdfUrl; + + if (!shouldShowPopup) { + // console.log('[EnergyLabel] Popup not showing:', { + // isEnergyPopup, + // hasPdfUrl, + // popupVisible, + // }); + return null; + } + + // console.log('[EnergyLabel] Rendering popup:', { + // popupVisible, + // activePopup, + // currentPdfUrl, + // isConverting: convert?.isConverting, + // hasImage: !!convert?.convertedImage, + // hasError: !!convert?.error, + // }); + + return ( + +
+ {convert ? ( + <> +
+ {convert.convertedImage ? ( + Energy Label + ) : convert.error ? ( +
+

{$L(STRING_CONF.ENERGY_ERROR)}

+

+ {convert.error?.message || String(convert.error)} +

+
+ ) : convert.isConverting ? ( +
+

{$L(STRING_CONF.ENERGY_LOADING)}

+

+ Converting PDF to image... (attempt in progress) +

+
+ ) : ( +
+

{$L(STRING_CONF.ENERGY_ERROR)}

+

+ Unknown state - no image or error +

+
+ )} +
+ + ) : ( +
+

{$L(STRING_CONF.ENERGY_ERROR)}

+

+ Convert reducer state not found +

+
+ )} +
+
+ ); + })()} ); } diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.module.less b/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.module.less index ad2fc607..f608d8ae 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.module.less +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductPriceDisplay/ProductPriceDisplay.module.less @@ -99,3 +99,90 @@ } } } + +.enrgLbImgBox { + display:flex; + justify-content: flex-start; + align-items: center; + .enrgLbImg { + width:62px; + height:38px; + border:4px solid transparent; + &:focus { + border: 4px solid @PRIMARY_COLOR_RED; + box-shadow: 0 0 22px 0 rgba(0, 0, 0, 0.5); + border-radius: 12px; + box-sizing: border-box; + } + > img { + width:100%; + } + } +} + +.popupContainer { + .header { + .size(@w: 780px , @h: 102px); + .flex(@display: flex, @justifyCenter: center, @alignCenter: center, @direction: row); + background-color: #e7ebef; + + > h3 { + font-size: 36px; + color: #222222; + font-weight: bold; + } + } + + .qrcodeContainer { + padding: 30px 0; + display: flex; + flex-direction: column; + align-items: center; + + .qrcode { + .size(@w: 360px , @h: 360px); + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 0 0 1px #dadada inset; + margin-bottom: 41px; + } + + > h3 { + display: flex; + text-align: center; + word-break: break-word; + line-height: 1.27; + } + + .popupBtn { + .size(@w: 300px , @h: 78px); + margin-top: 38px; + } + } +} + +// πŸ”½ μ—λ„ˆμ§€ 라벨 νŒμ—… μŠ€νƒ€μΌ (1920x1080 TV ν™”λ©΄ κΈ°μ€€) +.energyPopupContent { + width: 100%; + max-height: 800px; // νŒμ—… 타이틀/λ²„νŠΌ μ˜μ—­ μ œμ™Έν•œ μ½˜ν…μΈ  μ΅œλŒ€ 높이 + overflow-y: auto; + display: flex; + justify-content: center; + align-items: center; + padding: 20px; +} + +.energyImagesContainer { + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.energyImage { + max-width: 100%; + max-height: 750px; // 1080px - 타이틀(~120px) - λ²„νŠΌ(~120px) - μ—¬λ°±(~90px) + width: auto; + height: auto; + object-fit: contain; // λΉ„μœ¨ μœ μ§€ν•˜λ©΄μ„œ μ»¨ν…Œμ΄λ„ˆμ— 맞좀 +} 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 7894469b..d2b4afa9 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, @@ -33,7 +36,10 @@ import { popPanel, pushPanel, } from '../../../actions/panelActions'; -import { clearAllVideoTimers, finishVideoPreview } from '../../../actions/playActions'; +import { + clearAllVideoTimers, + finishVideoPreview, +} from '../../../actions/playActions'; import { getProductOption, getProductOptionId, @@ -463,7 +469,7 @@ const BuyOption = ({ }); // API Mode: μ‹€μ œ API 호좜 - if (!isMockMode) { + if (!isMockMode) { // ⚠️ ν•„μˆ˜ κ°’ 검증 if (!selectedPatnrId || !selectedPrdtId) { console.warn('[BuyOption] ⚠️ [getProductOption] MISSING REQUIRED PARAMS', { @@ -550,7 +556,7 @@ const BuyOption = ({ 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; @@ -623,7 +629,7 @@ const BuyOption = ({ response.retDetailCode, response.returnBindStrings ) - ); + ); dispatch(changeAppStatus({ isLoading: false })); return; } @@ -1081,17 +1087,18 @@ const BuyOption = ({ if (!isMock) { dispatch( - addToCart({ + insertMyinfoCart({ mbrNo: userNumber, patnrId: selectedPatnrId, prdtId: selectedPrdtId, - prodQty: String(effectiveQuantity), - prdtOpt: { - prodOptCdCval: optionForUse?.prodOptCdCval || '', - prodOptCval: optionLabel, + prodQty: Number(effectiveQuantity), + prdtOpt: [{ prodOptSno: productOptionInfos?.[0]?.prodOptSno || '', + prodOptCdCval: optionForUse?.prodOptCdCval || '', prodOptTpCdCval: productOptionInfos?.[0]?.prodOptTpCdCval || '', - }, + prodOptCval: optionLabel, + }], + }) ); @@ -1405,7 +1412,7 @@ const BuyOption = ({ {/* 동적 μ˜΅μ…˜ λ Œλ”λ§ */} {productOptionInfos && productOptionInfos?.length > 0 && - (productInfo?.optProdYn === 'Y' || hasMockOptions) && ( + productInfo?.optProdYn === 'Y' && ( <> {/* 첫번째 μ˜΅μ…˜ (μ—¬λŸ¬ μ˜΅μ…˜μ΄ μžˆμ„ λ•Œλ§Œ) */} {productOptionInfos?.length > 1 && ( diff --git a/com.twin.app.shoptime/src/views/HomePanel/BestSeller/BestSeller.jsx b/com.twin.app.shoptime/src/views/HomePanel/BestSeller/BestSeller.jsx index 7b224278..ee16c131 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/BestSeller/BestSeller.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/BestSeller/BestSeller.jsx @@ -68,17 +68,60 @@ const BestSeller = ({ const { cursorVisible } = useSelector((state) => state.common.appStatus); const bestSellerDatas = useSelector( - (state) => state.product.bestSellerData?.bestSeller - ); + (state) => state.product.bestSellerData?.bestSeller + ); + + const bestSellerNewDatas = useSelector( + (state) => + state.foryou?.recommendInfo?.recommendProduct + ); + + const [drawChk, setDrawChk] = useState(false); const [firstChk, setFirstChk] = useState(0); - const orderStyle = useMemo(() => ({ order: order }), [order]); + const [bestInfos, setBestInfos] = useState(null); + const [bestItemNewData, setBestItemNewData] = useState([]); + + useEffect(()=>{ + setBestInfos( + bestSellerNewDatas?.filter( + (item) => item.recommendTpCd === "BESTSELLER" + ) || [] // κΈ°λ³Έκ°’μœΌλ‘œ 빈 λ°°μ—΄ μ„€μ • + ) + },[bestSellerNewDatas]) useEffect(() => { + if (!bestInfos || bestInfos.length === 0) { + const baseData = bestSellerDatas?.map((item) => ({ + ...item, + foryou: false, + })) || []; + setBestItemNewData(baseData); + return; + } + + const recommendedData = bestInfos[0].productInfos?.map((item) => ({ + ...item, + foryou: true, + })) || []; + + const recommendedPrdtIds = new Set(recommendedData.map(item => item.prdtId)); + + const baseData = bestSellerDatas?.map((item) => ({ + ...item, + foryou: recommendedPrdtIds.has(item.prdtId), + })) || []; + + setBestItemNewData(baseData); + }, [bestSellerDatas, bestInfos]); + + const orderStyle = useMemo(() => ({ order: order }), [order]); + + useEffect(() => { setDrawChk(true); - }, [bestSellerDatas]); + }, [bestSellerNewDatas]); const handleCardClick = useCallback( (patnrId, prdtId) => () => { @@ -176,22 +219,7 @@ const BestSeller = ({ handleShelfFocus(); } }, [handleShelfFocus]); - - const [bestSellerNewData, setBestSellerNewData] = useState([]); - - const _randomProduct = useCallback(() => { - const randomChk = Math.round(Math.random()) === 0 ? false : true; - return randomChk; - }, []); - - useEffect(() => { - setBestSellerNewData( - bestSellerDatas?.map((item) => ({ - ...item, - // foryou: _randomProduct(), - })) - ); - }, [bestSellerDatas]); + return ( - {bestSellerNewData && - bestSellerNewData.map( + {bestItemNewData && + bestItemNewData.map( ( { prdtId, @@ -226,8 +254,8 @@ const BestSeller = ({ offerInfo, brndNm, patncNm, - catNm, - //foryou, + //catNm, μ—†μŒ + foryou, euEnrgLblInfos, }, itemIndex @@ -251,7 +279,7 @@ const BestSeller = ({ shelfTitle={shelfTitle} patnerName={patncNm} brandName={brndNm} - catNm={catNm} + // catNm={catNm} imageAlt={prdtId} imageSource={imgUrl} priceInfo={priceInfo} @@ -265,11 +293,11 @@ const BestSeller = ({ offerInfo={offerInfo} spotlightId={"bestsellerItem" + itemIndex} firstLabel={rankText} - label={itemIndex * 1 + 1 + " of " + bestSellerNewData.length} + label={itemIndex * 1 + 1 + " of " + bestItemNewData.length} lastLabel=" go to detail, button" euEnrgLblInfos={euEnrgLblInfos} > - {/* {foryou === true && } */} + {foryou === true && } ); } @@ -290,4 +318,4 @@ const BestSeller = ({ ); }; -export default BestSeller; +export default BestSeller; \ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx index 182bf392..b57ed8e3 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx @@ -28,7 +28,7 @@ import { setOptionalTermsUserDecision, updateOptionalTermsAgreement, } from '../../../actions/commonActions'; -import { getJustForYouInfo } from '../../../actions/forYouActions'; +import { justForYou } from '../../../actions/forYouActions'; import { fetchCurrentUserHomeTerms, setDefaultFocus, @@ -39,11 +39,11 @@ import { pushPanel, } from '../../../actions/panelActions'; import { + clearAllVideoTimers, releasePlayControl, requestPlayControl, startVideoPlayer, startVideoPlayerNew, - clearAllVideoTimers, } from '../../../actions/playActions'; import CustomImage from '../../../components/CustomImage/CustomImage'; // import TButtonScroller from "../../../components/TButtonScroller/TButtonScroller"; @@ -82,8 +82,8 @@ export default function HomeBanner({ handleShelfFocus, }) { const dispatch = useDispatch(); - useEffect(() => { - dispatch(getJustForYouInfo()); + useEffect(() => { + dispatch(justForYou()); }, [dispatch]); const homeTopDisplayInfo = useSelector( (state) => state.home.homeTopDisplayInfo diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx index 185f058e..61ea8efb 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx @@ -107,7 +107,7 @@ export default function RollingUnit({ const nowMenu = useSelector((state) => state.common.menu.nowMenu); const entryMenu = useSelector((state) => state.common.menu.entryMenu); const introTermsAgree = useSelector( - (state) => state.common.termsFlag.optionalTerms + (state) => state.common.optionalTermsAgree ); const homeCategory = useSelector( (state) => state.home.menuData?.data?.homeCategory @@ -120,7 +120,7 @@ export default function RollingUnit({ // μ»΄ν¬λ„ŒνŠΈ μƒλ‹¨μ—μ„œ 필터링 const filteredRollingData = useMemo(() => { return rollingData.filter( - (item) => introTermsAgree === "Y" || item.shptmLnkTpCd !== "DSP00510" + (item) => introTermsAgree === true || item.shptmLnkTpCd !== "DSP00510" ); }, [rollingData, introTermsAgree]); diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx index 091e5598..123fdc68 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx @@ -1,7 +1,17 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import classNames from 'classnames'; -import { useDispatch, useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; +import { applyMiddleware } from 'redux'; import Spotlight from '@enact/spotlight'; import { @@ -23,20 +33,31 @@ import { getHomeMainContents, updateHomeInfo, } from '../../actions/homeActions'; -import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions'; -import { getSubCategory, getTop20Show } from '../../actions/mainActions'; +import { + sendLogGNB, + sendLogTotalRecommend, +} from '../../actions/logActions'; +import { + getSubCategory, + getTop20Show, +} from '../../actions/mainActions'; import { getHomeOnSaleInfo } from '../../actions/onSaleActions'; -import { finishVideoPreview, shrinkVideoTo1px, expandVideoFrom1px } from '../../actions/playActions'; import { updatePanel } from '../../actions/panelActions'; +import { + expandVideoFrom1px, + finishVideoPreview, + shrinkVideoTo1px, +} from '../../actions/playActions'; import { getBestSeller } from '../../actions/productActions'; import TBody from '../../components/TBody/TBody'; import TButton, { TYPES } from '../../components/TButton/TButton'; import TPanel from '../../components/TPanel/TPanel'; import TPopUp from '../../components/TPopUp/TPopUp'; -import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator'; +import TVerticalPagenator + from '../../components/TVerticalPagenator/TVerticalPagenator'; import useDebugKey from '../../hooks/useDebugKey'; -import usePrevious from '../../hooks/usePrevious'; import { useFocusHistory } from '../../hooks/useFocusHistory/useFocusHistory'; +import usePrevious from '../../hooks/usePrevious'; import { useVideoPlay } from '../../hooks/useVideoPlay/useVideoPlay'; import { useVideoMove } from '../../hooks/useVideoTransition/useVideoMove'; import { @@ -55,7 +76,7 @@ import css from '../HomePanel/HomePanel.module.less'; import PopularShow from '../HomePanel/PopularShow/PopularShow'; import SubCategory from '../HomePanel/SubCategory/SubCategory'; import EventPopUpBanner from './EventPopUpBanner/EventPopUpBanner'; -import { applyMiddleware } from 'redux'; +import PickedForYou from './PickedForYou/PickedForYou'; export const TEMPLATE_CODE_CONF = { TOP: 'DSP00101', @@ -63,6 +84,7 @@ export const TEMPLATE_CODE_CONF = { ON_SALE: 'DSP00103', POPULAR_SHOW: 'DSP00104', BEST_SELLER: 'DSP00105', + PICK_FOR_YOU: 'DSP00106', }; const HomePanel = ({ isOnTop }) => { @@ -251,6 +273,9 @@ const HomePanel = ({ isOnTop }) => { case TEMPLATE_CODE_CONF.BEST_SELLER: nowMenu = LOG_MENU.HOME_BEST_SELLER; break; + case TEMPLATE_CODE_CONF.PICK_FOR_YOU: + nowMenu = LOG_MENU.HOME_PICKED_FOR_YOU; + break; default: nowMenu = LOG_MENU.HOME_TOP; break; @@ -384,6 +409,24 @@ const HomePanel = ({ isOnTop }) => { ); } else break; } + case TEMPLATE_CODE_CONF.PICK_FOR_YOU: { + if (bestSellerDatas && bestSellerDatas.length > 0) { + return ( + + ); + } else break; + } } })} {loadingComplete && sortedHomeLayoutInfo && sortedHomeLayoutInfo.length > 0 && ( @@ -593,6 +636,7 @@ const HomePanel = ({ isOnTop }) => { pageSize: 10, tabType: 'CAT00102', filterType: 'CAT00202', + recommendIncFlag: 'Y', }, 1 ) diff --git a/com.twin.app.shoptime/src/views/HomePanel/PickedForYou/PickedForYou.jsx b/com.twin.app.shoptime/src/views/HomePanel/PickedForYou/PickedForYou.jsx index 9dbb6e57..b6f3ccf4 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/PickedForYou/PickedForYou.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/PickedForYou/PickedForYou.jsx @@ -16,12 +16,9 @@ import { } from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; -import { - pushPanel, - updatePanel, -} from '../../../actions/panelActions'; +import { pushPanel } from '../../../actions/panelActions'; import SectionTitle from '../../../components/SectionTitle/SectionTitle'; -import TItemCard from '../../../components/TItemCard/TItemCard'; +import TItemCardNew from '../../../components/TItemCard/TItemCard.new'; import TScroller from '../../../components/TScroller/TScroller'; import useScrollReset from '../../../hooks/useScrollReset'; import useScrollTo from '../../../hooks/useScrollTo'; @@ -30,10 +27,7 @@ import { LOG_MESSAGE_ID, panel_names, } from '../../../utils/Config'; -import { - $L, - scaleW, -} from '../../../utils/helperMethods'; +import { $L } from '../../../utils/helperMethods'; import { SpotlightIds } from '../../../utils/SpotlightIds'; import css from './PickedForYou.module.less'; @@ -52,7 +46,7 @@ const PickedForYou = ({ shelfLocation, shelfTitle, }) => { - console.log("###Test pjh μ—¬κΈ°μ§€ ?"); + const { getScrollTo, scrollLeft } = useScrollTo(); const { handleScrollReset, handleStopScrolling } = useScrollReset( scrollLeft, @@ -63,18 +57,28 @@ const PickedForYou = ({ const { cursorVisible } = useSelector((state) => state.common.appStatus); - const justForYouDatas = useSelector( - (state) => state.product.bestSellerData?.bestSeller - ); - + const justForYouDatasNew = useSelector( + (state) => state.foryou?.recommendInfo?.recommendProduct + ) + const [drawChk, setDrawChk] = useState(false); const [firstChk, setFirstChk] = useState(0); + const [pickedForYou, setPickedForYou] = useState(null); + const orderStyle = useMemo(() => ({ order: order }), [order]); + useEffect(()=>{ + setPickedForYou( + justForYouDatasNew?.filter( + (item) => item.recommendTpCd === "PICKEDFORYOU" + ) + ) + },[justForYouDatasNew]) + useEffect(() => { setDrawChk(true); - }, [justForYouDatas]); + }, [justForYouDatasNew]); const handleCardClick = useCallback( (patnrId, prdtId) => () => { @@ -193,25 +197,26 @@ const PickedForYou = ({ cbScrollTo={getScrollTo} noScrollByWheel > - {justForYouDatas && - justForYouDatas.map( + {pickedForYou && + pickedForYou?.[0] && + pickedForYou?.[0].productInfos.map( ( { prdtId, imgUrl, priceInfo, - prdtNm, - rankOrd, + prdtNm, patnrId, offerInfo, brndNm, patncNm, catNm, + euEnrgLblInfos }, itemIndex ) => { return ( - ); } diff --git a/com.twin.app.shoptime/src/views/HomePanel/PopularShow/PopularShow.jsx b/com.twin.app.shoptime/src/views/HomePanel/PopularShow/PopularShow.jsx index 7e5e80f7..9305dbf4 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/PopularShow/PopularShow.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/PopularShow/PopularShow.jsx @@ -71,17 +71,57 @@ const PopularShow = ({ const { cursorVisible } = useSelector((state) => state.common.appStatus); const topInfos = useSelector((state) => state.main.top20ShowData.topInfos); + const recommendInfo = useSelector((state) => state.foryou?.recommendInfo?.recommendShow); + - const [drawChk, setDrawChk] = useState(false); const orderStyle = useMemo(() => ({ order: order }), [order]); - + const [drawChk, setDrawChk] = useState(false); const [firstChk, setFirstChk] = useState(0); + const [showInfos, setShowInfos] = useState(null); + const [showNewInfos, setShowNewInfos] = useState([]); + useEffect(() => { - setDrawChk(true); + setDrawChk(true); }, [topInfos]); + useEffect(()=>{ + setShowInfos( + recommendInfo?.filter( + (item) => item.recommendTpCd === "POPULARSHOW" + ) || [] + ) + },[recommendInfo]) + + useEffect(() => { + if (!showInfos || showInfos.length === 0) { + const baseData = topInfos?.map((item) => ({ + ...item, + foryou: false, + })) || []; + setShowNewInfos(baseData); + return; + } + + const recommendedData = showInfos[0].showInfos?.map((item) => ({ + ...item, + foryou: true, + })) || []; + + const recommendedPrdtIds = new Set(recommendedData?.map(item => item.showId)); + + const baseData = topInfos?.map((item) => ({ + ...item, + foryou: recommendedPrdtIds.has(item.showId), + })) || []; + + setShowNewInfos([ ...baseData]); + + }, [topInfos, showInfos]); + + + const handleCardClick = useCallback( (patnrId, showId, catCd, showUrl) => () => { dispatch( @@ -187,23 +227,7 @@ const PopularShow = ({ if (handleShelfFocus) { handleShelfFocus(); } - }, [handleShelfFocus]); - - const [topInfosNewData, setTopInfosNewData] = useState([]); - - const _randomProduct = useCallback(() => { - const randomChk = Math.round(Math.random()) === 0 ? false : true; - return randomChk; - }, []); - - useEffect(() => { - setTopInfosNewData( - topInfos?.map((item) => ({ - ...item, - // foryou: _randomProduct(), - })) - ); - }, [topInfos]); + }, [handleShelfFocus]); return ( - {topInfosNewData && - topInfosNewData.map( + {showNewInfos && + showNewInfos.map( ( { showId, @@ -240,7 +264,7 @@ const PopularShow = ({ patncNm, catCd, showUrl, - //foryou, + foryou, }, itemIndex ) => { @@ -258,9 +282,11 @@ const PopularShow = ({ contentId={showId} contentTitle={showNm} imageSource={ + (thumbnailUrl && thumbnailUrl960) ? thumbnailUrl !== thumbnailUrl960 ? thumbnailUrl960 : thumbnailUrl + : thumbnailUrl } imageAlt={showNm} productName={showNm} @@ -277,10 +303,10 @@ const PopularShow = ({ onBlur={handleBlur(itemIndex)} onClick={handleCardClick(patnrId, showId, catCd, showUrl)} firstLabel={patncNm + " "} - label={itemIndex * 1 + 1 + " of " + topInfos.length} + label={itemIndex * 1 + 1 + " of " + showNewInfos.length} lastLabel=" go to detail, button" > - {/* {foryou === true && } */} + {foryou === true && } ); } diff --git a/com.twin.app.shoptime/src/views/HomePanel/SubCategory/SubCategory.jsx b/com.twin.app.shoptime/src/views/HomePanel/SubCategory/SubCategory.jsx index f366aac2..20f95377 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/SubCategory/SubCategory.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/SubCategory/SubCategory.jsx @@ -16,7 +16,6 @@ import { import Spottable from '@enact/spotlight/Spottable'; import { setContainerLastFocusedElement } from '@enact/spotlight/src/container'; -import { getRecentlySawItem } from '../../../actions/forYouActions'; import { sendLogCuration } from '../../../actions/logActions'; import { getSubCategory } from '../../../actions/mainActions'; import { pushPanel } from '../../../actions/panelActions'; @@ -71,6 +70,10 @@ export default memo(function SubCategory({ (state) => state.main.subCategoryData?.categoryItemInfos ); + const foruItemInfos = useSelector( + (state) => state.main.recommendProduct[0]?.productInfos + ); + const nowMenu = useSelector((state) => state.common.menu.nowMenu); const [currentLgCatCd, setCurrentLgCatCd] = useState(catCd ? catCd : null); @@ -110,6 +113,7 @@ export default memo(function SubCategory({ pageSize: "10", tabType: "CAT00102", filterType: "CAT00202", + recommendIncFlag: 'Y', }, 1 ) @@ -117,7 +121,7 @@ export default memo(function SubCategory({ } setDrawChk(true); } - }, [currentLgCatCd, dispatch]); + }, [currentLgCatCd, dispatch, firstChk]); useEffect(() => { if (!nowMenuRef.current || !nowMenuRef.current.startsWith("Home")) { @@ -134,7 +138,7 @@ export default memo(function SubCategory({ dispatch(sendLogCuration(params)); } - }, [categoryInfos, currentLgCatCd, currentLgCatNm]); + }, [categoryInfos, currentLgCatCd, currentLgCatNm, dispatch, nowMenuRef]); const handleCategoryNav = useCallback( (lgCatCd, lgCatNm) => { @@ -149,7 +153,7 @@ export default memo(function SubCategory({ setContainerLastFocusedElement(null, [SpotlightIds.HOME_CATEGORY_NAV]); }, - [currentLgCatCd] + [currentLgCatCd, handleScrollReset] ); const handleFocus = useCallback( @@ -160,7 +164,7 @@ export default memo(function SubCategory({ handleScrollReset(); } }, - [_handleItemFocus] + [_handleItemFocus, handleScrollReset] ); const handleBlur = useCallback( @@ -169,7 +173,7 @@ export default memo(function SubCategory({ handleStopScrolling(); } }, - [] + [handleStopScrolling] ); const handleCardClick = useCallback( @@ -181,7 +185,7 @@ export default memo(function SubCategory({ }) ); }, - [] + [dispatch, spotlightId] ); const handleScrollRight = useCallback((e) => { @@ -189,7 +193,7 @@ export default memo(function SubCategory({ const x = container.scrollWidth - container.clientWidth; setTimeout(() => scrollLeft({ x, animate: true })); - }, []); + }, [scrollLeft]); const handleMoreCardClick = useCallback((e) => { const lgCatCd = e.currentTarget?.getAttribute("data-catcd-num"); @@ -208,7 +212,7 @@ export default memo(function SubCategory({ }) ); } - }, []); + }, [dispatch]); const _handleItemFocus = useCallback(() => { if (handleItemFocus) { @@ -222,27 +226,30 @@ export default memo(function SubCategory({ } }, [handleShelfFocus]); - const _randomProduct = useCallback(() => { - const randomChk = Math.round(Math.random()) === 0 ? false : true; - return randomChk; - }, []); - useEffect(() => { - setCategoryItemNewData( - categoryItemInfos?.subCatItemList?.map((item) => ({ + if (!foruItemInfos || foruItemInfos.length === 0) { + const baseData = categoryItemInfos?.subCatItemList?.map((item) => ({ ...item, - foryou: _randomProduct(), - })) - ); - }, [categoryItemInfos?.subCatItemList]); + foryou: false, + })) || []; + setCategoryItemNewData(baseData); + return; + } - useEffect(() => { - dispatch( - getRecentlySawItem( - categoryItemNewData.filter((item) => item.foryou === true) - ) - ); - }, [categoryItemNewData, dispatch]); + const recommendedData = foruItemInfos?.map((item) => ({ + ...item, + foryou: true, + })) || []; + + const recommendedPrdtIds = new Set(recommendedData.map(item => item.prdtId)); + + const baseData = categoryItemInfos?.subCatItemList?.map((item) => ({ + ...item, + foryou: recommendedPrdtIds.has(item.prdtId), + })) || []; + + setCategoryItemNewData([...baseData]); + }, [categoryItemInfos?.subCatItemList, foruItemInfos]); return ( - {/* {categoryItemInfos && - categoryItemInfos?.subCatItemList.map( - ( - { - prdtId, - imgUrl, - priceInfo, - prdtNm, - patnrId, - offerInfo, - brndNm, - patncNm, - }, - itemIndex - ) => { - return ( - - - - - - ); - } - )} 원본 보관*/} {categoryItemNewData && categoryItemNewData.map( ( @@ -332,7 +286,8 @@ export default memo(function SubCategory({ offerInfo, brndNm, patncNm, - //foryou, + foryou, + euEnrgLblInfos, }, itemIndex ) => { @@ -341,7 +296,7 @@ export default memo(function SubCategory({ key={"subItem" + itemIndex} contextName={LOG_CONTEXT_NAME.HOME} messageId={LOG_MESSAGE_ID.SHELF_CLICK} - catNm={categoryItemInfos.catNm} + catNm={categoryItemInfos?.catNm} order={itemIndex + 1} shelfId={spotlightId} shelfLocation={shelfLocation} @@ -363,11 +318,12 @@ export default memo(function SubCategory({ itemIndex * 1 + 1 + " of " + - categoryItemInfos?.subCatItemList.length + (categoryItemNewData?.length || 0) } lastLabel=" go to detail, button" + euEnrgLblInfos={euEnrgLblInfos} > - {/* {foryou === true && } */} + {foryou === true && } ); } @@ -389,4 +345,4 @@ export default memo(function SubCategory({ ); -}); +}); \ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/JustForYouTestPanel/JustForYouTestPanel.jsx b/com.twin.app.shoptime/src/views/JustForYouTestPanel/JustForYouTestPanel.jsx index 3ebef3e9..b9d5e928 100644 --- a/com.twin.app.shoptime/src/views/JustForYouTestPanel/JustForYouTestPanel.jsx +++ b/com.twin.app.shoptime/src/views/JustForYouTestPanel/JustForYouTestPanel.jsx @@ -47,11 +47,11 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => { const cbChangePageRef = useRef(null); const shelfInfos = useSelector( - (state) => state.foryou?.justForYouInfo?.shelfInfos + (state) => state.foryou?.recommendInfo?.recommendProduct ); const justForYouInfo = useSelector( - (state) => state.foryou?.justForYouInfo?.justForYouInfo + (state) => state.foryou?.recommendInfo?.justForYouInfo ); const onClick = useCallback(() => { @@ -80,25 +80,19 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => { } const product = productInfos[index]; - const { - contentId, - title, - thumbnail, - price, - dcPrice, - partnerName, - partnerLogo, + const { + prdtNm, + imgUrl, + priceInfo, + patncNm, + patnrId, + prdtId, } = product; const handleItemClick = () => { - // Extract product ID from contentId if needed - const tokens = contentId.split("_"); - const patnrId = tokens?.[4] || ""; - const prdtId = tokens?.[5] || ""; dispatch( pushPanel({ - name: panel_names.DETAIL_PANEL, - // panelInfo: { prdtId: contentId }, + name: panel_names.DETAIL_PANEL, panelInfo: { patnrId: patnrId, prdtId: prdtId, @@ -109,16 +103,14 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => { return ( { key={shelf.shelfId} className={classNames( css.itemsContainer, - shelfIndex === 0 && css.itemsContinerFirst + shelfIndex === 1 && css.itemsContinerFirst )} spotlightId={`justForYouList_${shelf.shelfExpsOrd}`} data-wheel-point diff --git a/com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx b/com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx index b8947209..39c8c303 100644 --- a/com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx +++ b/com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx @@ -1,10 +1,21 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import classNames from 'classnames'; -import { useDispatch, useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; +import Dropdown from '@enact/sandstone/Dropdown'; import Spotlight from '@enact/spotlight'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; import downBtnImg from '../../../assets/images/btn/search_btn_down_arrow.png'; @@ -14,7 +25,8 @@ import { hideShopperHouseError } from '../../actions/searchActions'; import CustomImage from '../../components/CustomImage/CustomImage'; import TButtonTab, { LIST_TYPE } from '../../components/TButtonTab/TButtonTab'; import TDropDown from '../../components/TDropDown/TDropDown'; -import TVirtualGridList from '../../components/TVirtualGridList/TVirtualGridList'; +import TVirtualGridList + from '../../components/TVirtualGridList/TVirtualGridList'; import { panel_names } from '../../utils/Config'; import { $L } from '../../utils/helperMethods'; import { SpotlightIds } from '../../utils/SpotlightIds'; @@ -24,8 +36,6 @@ import HowAboutTheseSmall from './HowAboutThese/HowAboutThese.small'; import css from './SearchResults.new.v2.module.less'; import ItemCard from './SearchResultsNew/ItemCard'; import ShowCard from './SearchResultsNew/ShowCard'; -import Dropdown from '@enact/sandstone/Dropdown'; - const ITEMS_PER_PAGE = 10; @@ -926,7 +936,7 @@ const SearchResultsNew = ({ No matches, Showing suggestions )} - + {hasShopperHouseItems && ( {filterMethods} - + )} {/* μ•„μ΄ν…œ/μ‡Ό 컨텐츠 */} diff --git a/com.twin.app.shoptime/src/views/SearchPanel/SearchResultsNew/ItemCard.jsx b/com.twin.app.shoptime/src/views/SearchPanel/SearchResultsNew/ItemCard.jsx index 27319243..2a8aeb77 100644 --- a/com.twin.app.shoptime/src/views/SearchPanel/SearchResultsNew/ItemCard.jsx +++ b/com.twin.app.shoptime/src/views/SearchPanel/SearchResultsNew/ItemCard.jsx @@ -4,7 +4,10 @@ import { useDispatch } from 'react-redux'; import Spotlight from '@enact/spotlight'; -import { pushPanel, updatePanel } from '../../../actions/panelActions'; +import { + pushPanel, + updatePanel, +} from '../../../actions/panelActions'; import { navigateToDetailPanel } from '../../../actions/panelNavigationActions'; import TItemCardNew from '../../../components/TItemCard/TItemCard.new'; import TScroller from '../../../components/TScroller/TScroller'; @@ -62,7 +65,7 @@ const ItemCard = ({ onClick, itemInfo, searchQuery }) => { <> {itemInfo.map((item, index) => { - const { thumbnail, title, dcPrice, price, soldout, contentId } = item; + const { thumbnail, title, dcPrice, price, soldout, contentId,euEnrgLblInfos } = item; const tokens = contentId && contentId.split('_'); const patnrId = tokens?.[4] || ''; const prdtId = tokens?.[5] || ''; @@ -83,6 +86,7 @@ const ItemCard = ({ onClick, itemInfo, searchQuery }) => { {...(index === 0 ? { 'data-spotlight-up': 'searchtabContainer' } : {})} label={index * 1 + 1 + ' of ' + itemInfo.length + 1} lastLabel=" go to detail, button" + euEnrgLblInfos={euEnrgLblInfos} /> ); })}