Merge branch 'detail_v3' of http://gitlab.t-win.kr/ifheone/shoptime into detail_v3
This commit is contained in:
@@ -76,11 +76,16 @@ export const types = {
|
|||||||
GET_MY_INFO_SHIPPING_SEARCH: 'GET_MY_INFO_SHIPPING_SEARCH',
|
GET_MY_INFO_SHIPPING_SEARCH: 'GET_MY_INFO_SHIPPING_SEARCH',
|
||||||
|
|
||||||
// cart actions
|
// cart actions
|
||||||
GET_MY_INFO_CART_SEARCH: 'GET_MY_INFO_CART_SEARCH',
|
|
||||||
ADD_TO_CART: 'ADD_TO_CART',
|
ADD_TO_CART: 'ADD_TO_CART',
|
||||||
REMOVE_FROM_CART: 'REMOVE_FROM_CART',
|
REMOVE_FROM_CART: 'REMOVE_FROM_CART',
|
||||||
UPDATE_CART_ITEM: 'UPDATE_CART_ITEM',
|
UPDATE_CART_ITEM: 'UPDATE_CART_ITEM',
|
||||||
CLEAR_CART: 'CLEAR_CART',
|
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
|
// appData actions
|
||||||
ADD_MAIN_INDEX: 'ADD_MAIN_INDEX',
|
ADD_MAIN_INDEX: 'ADD_MAIN_INDEX',
|
||||||
@@ -308,11 +313,8 @@ export const types = {
|
|||||||
SET_MODAL_BORDER: 'SET_MODAL_BORDER',
|
SET_MODAL_BORDER: 'SET_MODAL_BORDER',
|
||||||
SET_BANNER_VISIBILITY: 'SET_BANNER_VISIBILITY',
|
SET_BANNER_VISIBILITY: 'SET_BANNER_VISIBILITY',
|
||||||
|
|
||||||
// 🔽 [추가] JustForYou 상품 관리 부분
|
// 🔽 [추가] JustForYou 상품 관리 부분
|
||||||
GET_RECENTLY_SAW_ITEM: 'GET_RECENTLY_SAW_ITEM',
|
JUSTFORYOU: 'JUSTFORYOU',
|
||||||
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',
|
|
||||||
|
|
||||||
// 🔽 Voice Conductor 관련 액션 타입
|
// 🔽 Voice Conductor 관련 액션 타입
|
||||||
VOICE_REGISTER_SUCCESS: 'VOICE_REGISTER_SUCCESS',
|
VOICE_REGISTER_SUCCESS: 'VOICE_REGISTER_SUCCESS',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { URLS } from '../api/apiConfig';
|
import { URLS } from '../api/apiConfig';
|
||||||
import { TAxios } from '../api/TAxios';
|
import { TAxios } from '../api/TAxios';
|
||||||
import { types } from './actionTypes';
|
import { types } from './actionTypes';
|
||||||
|
import { 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 - 장바구니 상품 정보
|
* @param {Object} props - 장바구니 상품 정보
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { URLS } from '../api/apiConfig';
|
import { URLS } from '../api/apiConfig';
|
||||||
import { TAxios } from '../api/TAxios';
|
import { TAxios } from '../api/TAxios';
|
||||||
import { types } from './actionTypes';
|
import { types } from './actionTypes';
|
||||||
|
import { getReAuthenticationCode } from './deviceActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PDF를 이미지로 변환 (재시도 로직 포함)
|
* PDF를 이미지로 변환 (재시도 로직 포함)
|
||||||
@@ -52,10 +53,10 @@ export const convertPdfToImage =
|
|||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
timeoutId = null;
|
timeoutId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// retCode 체크 (프로젝트 API 규약: 200이어도 retCode로 성공/실패 구분)
|
// retCode 체크 (프로젝트 API 규약: 200이어도 retCode로 성공/실패 구분)
|
||||||
const retCode = response.headers?.retcode || response.headers?.retCode;
|
const retCode = response.headers?.retcode || response.headers?.retCode;
|
||||||
|
|
||||||
if (retCode !== undefined && retCode !== 0 && retCode !== '0') {
|
if (retCode !== undefined && retCode !== 0 && retCode !== '0') {
|
||||||
const error = new Error(`API Error: retCode=${retCode}`);
|
const error = new Error(`API Error: retCode=${retCode}`);
|
||||||
console.warn(`⚠️ [EnergyLabel] API returned error on attempt ${attempts}:`, retCode);
|
console.warn(`⚠️ [EnergyLabel] API returned error on attempt ${attempts}:`, retCode);
|
||||||
@@ -79,56 +80,62 @@ export const convertPdfToImage =
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageUrl;
|
if(response.data.type !== "image/png"){
|
||||||
try {
|
dispatch(getReAuthenticationCode());
|
||||||
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();
|
attemptConversion();
|
||||||
} else {
|
return;
|
||||||
console.error(
|
}
|
||||||
`❌ [EnergyLabel] Final failure after ${attempts} attempts (image error):`,
|
|
||||||
pdfUrl
|
let imageUrl;
|
||||||
);
|
try {
|
||||||
dispatch({
|
if (response.data instanceof Blob) {
|
||||||
type: types.CONVERT_PDF_TO_IMAGE_FAILURE,
|
if (response.data.size === 0) {
|
||||||
payload: { pdfUrl, error },
|
throw new Error('Invalid image data (empty blob)');
|
||||||
});
|
}
|
||||||
callback && callback(error, null);
|
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) => {
|
const onFail = (error) => {
|
||||||
|
|||||||
@@ -1,36 +1,16 @@
|
|||||||
import { URLS } from '../api/apiConfig';
|
import { URLS } from '../api/apiConfig';
|
||||||
import { TAxios } from '../api/TAxios';
|
import { TAxios } from '../api/TAxios';
|
||||||
import {
|
import { get } from '../utils/fp';
|
||||||
curry,
|
|
||||||
get,
|
|
||||||
set,
|
|
||||||
} from '../utils/fp';
|
|
||||||
import { types } from './actionTypes';
|
import { types } from './actionTypes';
|
||||||
import { changeAppStatus } from './commonActions';
|
import { changeAppStatus } from './commonActions';
|
||||||
|
|
||||||
// 최근 본 아이템 관련 액션
|
export const justForYou = (callback) => (dispatch, getState) => {
|
||||||
export const getRecentlySawItem = (data) => ({
|
const macAddress = getState().common.macAddress;
|
||||||
type: types.GET_RECENTLY_SAW_ITEM,
|
const macAddr = macAddress?.wired || macAddress?.wifi || "00:1A:2B:3C:4D:5E";
|
||||||
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) => {
|
|
||||||
const onSuccess = (response) => {
|
const onSuccess = (response) => {
|
||||||
console.log("getJustForYouInfo onSuccess", response.data);
|
console.log("JustForYou onSuccess", response.data);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.GET_JUSTFORYOU_INFO,
|
type: types.JUSTFORYOU,
|
||||||
payload: get("data.data", response),
|
payload: get("data.data", response),
|
||||||
});
|
});
|
||||||
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
|
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
|
||||||
@@ -38,7 +18,7 @@ export const getJustForYouInfo = (callback) => (dispatch, getState) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onFail = (error) => {
|
const onFail = (error) => {
|
||||||
console.error("getJustForYouInfo onFail", error);
|
console.error("JustForYou onFail", error);
|
||||||
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
|
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
|
||||||
callback && callback();
|
callback && callback();
|
||||||
};
|
};
|
||||||
@@ -46,10 +26,10 @@ export const getJustForYouInfo = (callback) => (dispatch, getState) => {
|
|||||||
TAxios(
|
TAxios(
|
||||||
dispatch,
|
dispatch,
|
||||||
getState,
|
getState,
|
||||||
"get",
|
"post",
|
||||||
URLS.GET_JUSTFORYOU_INFO,
|
URLS.JUSTFORYOU,
|
||||||
{},
|
|
||||||
{},
|
{},
|
||||||
|
{macAddr},
|
||||||
onSuccess,
|
onSuccess,
|
||||||
onFail
|
onFail
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
import { URLS } from '../api/apiConfig';
|
import { URLS } from '../api/apiConfig';
|
||||||
import { TAxios } from '../api/TAxios';
|
import { TAxios } from '../api/TAxios';
|
||||||
import { convertUtcToLocal } from '../components/MediaPlayer/util';
|
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 * as HelperMethods from '../utils/helperMethods';
|
||||||
import { types } from './actionTypes';
|
import { types } from './actionTypes';
|
||||||
import { addReservation, changeAppStatus, deleteReservation } from './commonActions';
|
import {
|
||||||
|
addReservation,
|
||||||
|
changeAppStatus,
|
||||||
|
deleteReservation,
|
||||||
|
} from './commonActions';
|
||||||
|
|
||||||
//IF-LGSP-007
|
//IF-LGSP-007
|
||||||
export const getMainLiveShow = (props) => (dispatch, getState) => {
|
export const getMainLiveShow = (props) => (dispatch, getState) => {
|
||||||
@@ -155,7 +163,7 @@ let lastSubCategoryParams = {};
|
|||||||
export const getSubCategory =
|
export const getSubCategory =
|
||||||
(params, pageNo = 1, key = null, clear = false) =>
|
(params, pageNo = 1, key = null, clear = false) =>
|
||||||
(dispatch, getState) => {
|
(dispatch, getState) => {
|
||||||
const { lgCatCd, patnrIdList, tabType, filterType } = params;
|
const { lgCatCd, patnrIdList, tabType, filterType, recommendIncFlag } = params;
|
||||||
let pageSize = params.pageSize || CATEGORY_DATA_MAX_RESULTS_LIMIT;
|
let pageSize = params.pageSize || CATEGORY_DATA_MAX_RESULTS_LIMIT;
|
||||||
|
|
||||||
if (pageNo === 1) {
|
if (pageNo === 1) {
|
||||||
@@ -179,21 +187,34 @@ export const getSubCategory =
|
|||||||
if (pageNo === 1) {
|
if (pageNo === 1) {
|
||||||
getSubCategoryKey = new Date();
|
getSubCategoryKey = new Date();
|
||||||
currentKey = getSubCategoryKey;
|
currentKey = getSubCategoryKey;
|
||||||
|
|
||||||
|
// ✅ recommendProduct 분리
|
||||||
|
const { recommendProduct, ...restData } = response.data.data;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.GET_SUB_CATEGORY,
|
type: types.GET_SUB_CATEGORY,
|
||||||
payload: response.data.data,
|
payload: {
|
||||||
|
...restData,
|
||||||
|
recommendProduct,
|
||||||
|
},
|
||||||
categoryParams: {
|
categoryParams: {
|
||||||
lgCatCd,
|
lgCatCd,
|
||||||
patnrIdList,
|
patnrIdList,
|
||||||
tabType,
|
tabType,
|
||||||
filterType,
|
filterType,
|
||||||
|
recommendIncFlag,
|
||||||
pageSize,
|
pageSize,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (getSubCategoryKey === currentKey) {
|
} else if (getSubCategoryKey === currentKey) {
|
||||||
|
const { recommendProduct, ...restData } = response.data.data;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.GET_SUB_CATEGORY,
|
type: types.GET_SUB_CATEGORY,
|
||||||
payload: response.data.data,
|
payload: {
|
||||||
|
...restData,
|
||||||
|
recommendProduct,
|
||||||
|
},
|
||||||
append: true,
|
append: true,
|
||||||
startIndex: (pageNo - 1) * pageSize,
|
startIndex: (pageNo - 1) * pageSize,
|
||||||
});
|
});
|
||||||
@@ -212,7 +233,7 @@ export const getSubCategory =
|
|||||||
getState,
|
getState,
|
||||||
'get',
|
'get',
|
||||||
URLS.GET_SUB_CATEGORY,
|
URLS.GET_SUB_CATEGORY,
|
||||||
{ lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType },
|
{ lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType,recommendIncFlag },
|
||||||
{},
|
{},
|
||||||
onSuccess,
|
onSuccess,
|
||||||
onFail
|
onFail
|
||||||
|
|||||||
@@ -20,10 +20,15 @@ export const URLS = {
|
|||||||
GET_MY_INFO_CARD_SEARCH: "/lgsp/v1/myinfo/card/search.lge",
|
GET_MY_INFO_CARD_SEARCH: "/lgsp/v1/myinfo/card/search.lge",
|
||||||
|
|
||||||
// cart controller
|
// cart controller
|
||||||
GET_MY_INFO_CART_SEARCH: "/lgsp/v1/myinfo/cart/search.lge",
|
|
||||||
ADD_TO_CART: "/lgsp/v1/myinfo/cart/add.lge",
|
ADD_TO_CART: "/lgsp/v1/myinfo/cart/add.lge",
|
||||||
REMOVE_FROM_CART: "/lgsp/v1/myinfo/cart/remove.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
|
// shipping controller
|
||||||
GET_MY_INFO_SHIPPING_SEARCH: "/lgsp/v1/myinfo/address/shipping/search.lge",
|
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",
|
UPDATE_ORDER_PARTIAL_CANCEL: "/lgsp/v1/myinfo/order/orderPartialCancel.lge",
|
||||||
PAYMENT_TOTAL_CANCEL: "/lgsp/v1/myinfo/order/paymentTotalCancel.lge",
|
PAYMENT_TOTAL_CANCEL: "/lgsp/v1/myinfo/order/paymentTotalCancel.lge",
|
||||||
|
|
||||||
// foryou controller
|
// foryou controller
|
||||||
GET_JUSTFORYOU_INFO: "/lgsp/v1/justforyou/list.lge",
|
JUSTFORYOU: "/lgsp/v1/recommend/justforyou.lge",
|
||||||
|
|
||||||
|
|
||||||
// emp controller
|
// emp controller
|
||||||
GET_SHOPTIME_TERMS: "/lgsp/v1/emp/shoptime/terms.lge",
|
GET_SHOPTIME_TERMS: "/lgsp/v1/emp/shoptime/terms.lge",
|
||||||
|
|||||||
@@ -245,7 +245,7 @@
|
|||||||
|
|
||||||
> p {
|
> p {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 30px;
|
font-size: 28px;
|
||||||
color: @PRIMARY_COLOR_RED;
|
color: @PRIMARY_COLOR_RED;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const removeDotAndColon = (string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const parsePrice = (price) => {
|
const parsePrice = (price) => {
|
||||||
return parseFloat(price?.replace(/[^0-9.-]+/g, "") || "0");
|
return parseFloat(price?.replace(/[^0-9.-]+/g, "").replace("£","") || "0");
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateMockEnergyLabels = (productId) => {
|
const generateMockEnergyLabels = (productId) => {
|
||||||
@@ -474,12 +474,18 @@ export default memo(function TItemCardNew({
|
|||||||
className={classNames(
|
className={classNames(
|
||||||
css.descWrap,
|
css.descWrap,
|
||||||
catNm && css.hstNmWrap,
|
catNm && css.hstNmWrap,
|
||||||
parsePrice(originPrice) >= 1000 &&
|
(parsePrice(originalPrice) >= 1000 || parsePrice(originPrice) >= 1000 ) &&
|
||||||
parsePrice(dcPrice) >= 1000 &&
|
(parsePrice(discountedPrice) >= 1000 || parsePrice(dcPrice) >= 1000 ) &&
|
||||||
|
euEnrgLblInfos?.length > 0 &&
|
||||||
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== null &&
|
||||||
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined &&
|
||||||
(countryCode === "GB" || countryCode === "DE") &&
|
(countryCode === "GB" || countryCode === "DE") &&
|
||||||
css.labelBox,
|
css.labelBox,
|
||||||
parsePrice(originPrice) >= 10000 &&
|
(parsePrice(originalPrice) >= 10000 || parsePrice(originPrice) >= 10000 ) &&
|
||||||
parsePrice(dcPrice) >= 10000 &&
|
(parsePrice(discountedPrice) >= 10000 || parsePrice(dcPrice) >= 10000 ) &&
|
||||||
|
euEnrgLblInfos?.length > 0 &&
|
||||||
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== null &&
|
||||||
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined &&
|
||||||
(countryCode === "GB" || countryCode === "DE") &&
|
(countryCode === "GB" || countryCode === "DE") &&
|
||||||
css.labelOverBox
|
css.labelOverBox
|
||||||
)}
|
)}
|
||||||
@@ -525,11 +531,11 @@ export default memo(function TItemCardNew({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{(() => {
|
{(() => {
|
||||||
const hasValidApiData =
|
{/* const hasValidApiData =
|
||||||
euEnrgLblInfos?.length > 0 &&
|
euEnrgLblInfos?.length > 0 &&
|
||||||
euEnrgLblInfos[0]?.enrgLblIcnUrl !== null &&
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== null &&
|
||||||
euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined;
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined; */}
|
||||||
|
const hasValidApiData = true;
|
||||||
let energyLabels;
|
let energyLabels;
|
||||||
|
|
||||||
if (CURRENT_ENERGY_LABEL_MODE === ENERGY_LABEL_MODE.API_ONLY) {
|
if (CURRENT_ENERGY_LABEL_MODE === ENERGY_LABEL_MODE.API_ONLY) {
|
||||||
@@ -550,7 +556,11 @@ export default memo(function TItemCardNew({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(countryCode === "GB" || countryCode === "DE") && (
|
(countryCode === "GB" || countryCode === "DE") &&
|
||||||
|
(euEnrgLblInfos?.length > 0 &&
|
||||||
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== null &&
|
||||||
|
euEnrgLblInfos[0]?.enrgLblIcnUrl !== undefined) &&
|
||||||
|
(
|
||||||
<div className={css.labelImgBox}>
|
<div className={css.labelImgBox}>
|
||||||
{type !== "videoShow" &&
|
{type !== "videoShow" &&
|
||||||
energyLabels
|
energyLabels
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { types } from "../actions/actionTypes";
|
import { types } from '../actions/actionTypes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cart Reducer 초기 상태
|
* Cart Reducer 초기 상태
|
||||||
@@ -18,9 +18,9 @@ const initialState = {
|
|||||||
* Cart Reducer
|
* Cart Reducer
|
||||||
* 장바구니 관련 상태를 관리합니다.
|
* 장바구니 관련 상태를 관리합니다.
|
||||||
*/
|
*/
|
||||||
export const cartReducer = (state = initialState, action) => {
|
export const cartReducer = (state = initialState, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
// 장바구니 조회
|
// 장바구니 조회 - API에서 가져온 전체 목록
|
||||||
case types.GET_MY_INFO_CART_SEARCH:
|
case types.GET_MY_INFO_CART_SEARCH:
|
||||||
return {
|
return {
|
||||||
...state,
|
...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:
|
case types.ADD_TO_CART:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -43,7 +80,7 @@ export const cartReducer = (state = initialState, action) => {
|
|||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 장바구니에서 상품 제거
|
// 장바구니에서 상품 제거 (removeFromCart)
|
||||||
case types.REMOVE_FROM_CART:
|
case types.REMOVE_FROM_CART:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -55,19 +92,19 @@ export const cartReducer = (state = initialState, action) => {
|
|||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 장바구니 상품 수량 업데이트
|
// 장바구니 상품 수량 업데이트 (updateCartItem)
|
||||||
case types.UPDATE_CART_ITEM:
|
case types.UPDATE_CART_ITEM:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
lastAction: {
|
lastAction: {
|
||||||
type: "update",
|
type: "updateQty",
|
||||||
data: action.payload,
|
data: action.payload,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
},
|
},
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 장바구니 전체 비우기
|
// 장바구니 전체 비우기 (clearCart - 로컬 상태 전용)
|
||||||
case types.CLEAR_CART:
|
case types.CLEAR_CART:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -85,4 +122,4 @@ export const cartReducer = (state = initialState, action) => {
|
|||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5,50 +5,16 @@ import {
|
|||||||
set,
|
set,
|
||||||
} from '../utils/fp';
|
} from '../utils/fp';
|
||||||
|
|
||||||
// 초기 상태 정의
|
|
||||||
// const initialState = {
|
|
||||||
// recentlySawItems: [],
|
|
||||||
// likeBrandProducts: [],
|
|
||||||
// moreToConciderAtThisPrice: [],
|
|
||||||
// };
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
justForYouInfo: {},
|
recommendInfo: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
// const foryouReducer = (state = initialState, action) => {
|
const recommendInfo = curry((state, action) =>
|
||||||
// switch (action.type) {
|
set("recommendInfo", get("payload", action), state)
|
||||||
// // 최근 본 아이템
|
|
||||||
// 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 handlers = {
|
const handlers = {
|
||||||
[types.GET_JUSTFORYOU_INFO]: justForYouInfo,
|
[types.JUSTFORYOU]: recommendInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const foryouReducer = (state = initialState, action = {}) => {
|
export const foryouReducer = (state = initialState, action = {}) => {
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ const initialState = {
|
|||||||
showDetailInfo: [],
|
showDetailInfo: [],
|
||||||
showNowInfo: null,
|
showNowInfo: null,
|
||||||
featuredShowsInfos: {},
|
featuredShowsInfos: {},
|
||||||
|
recommendProduct: null,
|
||||||
categoryParams: {
|
categoryParams: {
|
||||||
lgCatCd: null,
|
lgCatCd: null,
|
||||||
patnrIdList: null,
|
patnrIdList: null,
|
||||||
tabType: null,
|
tabType: null,
|
||||||
filterType: null,
|
filterType: null,
|
||||||
|
recommendIncFlag: null,
|
||||||
pageSize: CATEGORY_DATA_MAX_RESULTS_LIMIT,
|
pageSize: CATEGORY_DATA_MAX_RESULTS_LIMIT,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -39,6 +41,7 @@ export const mainReducer = (state = initialState, action) => {
|
|||||||
categoryFilterCd: action.payload.categoryFilterCd,
|
categoryFilterCd: action.payload.categoryFilterCd,
|
||||||
topShowInfo: action.payload.topShowInfo,
|
topShowInfo: action.payload.topShowInfo,
|
||||||
partnerInfos: action.payload.partnerInfos,
|
partnerInfos: action.payload.partnerInfos,
|
||||||
|
recommendProduct: action.payload.recommendProduct,
|
||||||
categoryParams: action.categoryParams,
|
categoryParams: action.categoryParams,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -63,6 +66,7 @@ export const mainReducer = (state = initialState, action) => {
|
|||||||
categoryFilterCd: action.payload.categoryFilterCd,
|
categoryFilterCd: action.payload.categoryFilterCd,
|
||||||
topShowInfo: action.payload.topShowInfo,
|
topShowInfo: action.payload.topShowInfo,
|
||||||
partnerInfos: action.payload.partnerInfos,
|
partnerInfos: action.payload.partnerInfos,
|
||||||
|
recommendProduct: action.payload.recommendProduct,
|
||||||
categoryParams: action.categoryParams,
|
categoryParams: action.categoryParams,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -93,6 +97,7 @@ export const mainReducer = (state = initialState, action) => {
|
|||||||
categoryFilterCd: action.payload.categoryFilterCd,
|
categoryFilterCd: action.payload.categoryFilterCd,
|
||||||
topShowInfo: action.payload.topShowInfo,
|
topShowInfo: action.payload.topShowInfo,
|
||||||
partnerInfos: action.payload.partnerInfos,
|
partnerInfos: action.payload.partnerInfos,
|
||||||
|
recommendProduct: action.payload.recommendProduct,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
@@ -107,6 +112,7 @@ export const mainReducer = (state = initialState, action) => {
|
|||||||
categoryFilterCd: action.payload.categoryFilterCd,
|
categoryFilterCd: action.payload.categoryFilterCd,
|
||||||
topShowInfo: action.payload.topShowInfo,
|
topShowInfo: action.payload.topShowInfo,
|
||||||
partnerInfos: action.payload.partnerInfos,
|
partnerInfos: action.payload.partnerInfos,
|
||||||
|
recommendProduct: action.payload.recommendProduct,
|
||||||
categoryParams: action.categoryParams,
|
categoryParams: action.categoryParams,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -206,6 +212,7 @@ export const mainReducer = (state = initialState, action) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
subCategoryData: {},
|
subCategoryData: {},
|
||||||
|
recommendProduct: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ export const ACTIVE_POPUP = {
|
|||||||
exitPopup: 'exitPopup',
|
exitPopup: 'exitPopup',
|
||||||
favoritePopup: 'favoritePopup',
|
favoritePopup: 'favoritePopup',
|
||||||
loginPopup: 'loginPopup',
|
loginPopup: 'loginPopup',
|
||||||
|
logoutPopup: 'logoutPopup',
|
||||||
noShowPopup: 'noShowPopup',
|
noShowPopup: 'noShowPopup',
|
||||||
optionPopup: 'optionPopup',
|
optionPopup: 'optionPopup',
|
||||||
qrPopup: 'qrPopup',
|
qrPopup: 'qrPopup',
|
||||||
@@ -292,6 +293,7 @@ export const LOG_MENU = {
|
|||||||
HOME_ON_SALE: 'Home/On Sale',
|
HOME_ON_SALE: 'Home/On Sale',
|
||||||
HOME_POPULAR_SHOWS: 'Home/Popular Shows',
|
HOME_POPULAR_SHOWS: 'Home/Popular Shows',
|
||||||
HOME_BEST_SELLER: 'Home/Best Sellers',
|
HOME_BEST_SELLER: 'Home/Best Sellers',
|
||||||
|
HOME_PICKED_FOR_YOU: 'Home/Picked For You',
|
||||||
|
|
||||||
TRENDING_NOW_POPULAR_SHOWS: 'Trending Now/Popular Shows',
|
TRENDING_NOW_POPULAR_SHOWS: 'Trending Now/Popular Shows',
|
||||||
TRENDING_NOW_BEST_SELLER: 'Trending Now/Best Sellers',
|
TRENDING_NOW_BEST_SELLER: 'Trending Now/Best Sellers',
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ export default function CartPanel({ spotlightId, scrollOptions = [], panelInfo }
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Mock Mode 여부 확인 및 적절한 데이터 선택
|
// Mock Mode 여부 확인 및 적절한 데이터 선택
|
||||||
const isMockMode = BUYNOW_CONFIG.isMockMode();
|
// const isMockMode = BUYNOW_CONFIG.isMockMode();
|
||||||
|
const isMockMode = false;
|
||||||
const displayCartData = useMemo(() => {
|
const displayCartData = useMemo(() => {
|
||||||
return isMockMode ? mockCartData : cartData;
|
return isMockMode ? mockCartData : cartData;
|
||||||
}, [isMockMode, mockCartData, cartData]);
|
}, [isMockMode, mockCartData, cartData]);
|
||||||
|
|||||||
@@ -11,19 +11,17 @@ import {
|
|||||||
useSelector,
|
useSelector,
|
||||||
} from 'react-redux';
|
} from 'react-redux';
|
||||||
|
|
||||||
import Spotlight from '@enact/spotlight';
|
|
||||||
import SpotlightContainerDecorator
|
import SpotlightContainerDecorator
|
||||||
from '@enact/spotlight/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 defaultImage from '../../../assets/images/img-thumb-empty-144@3x.png';
|
||||||
import {
|
import {
|
||||||
|
deleteMyinfoCart,
|
||||||
removeFromCart,
|
removeFromCart,
|
||||||
updateCartItem,
|
updateMyinfoCart,
|
||||||
} from '../../actions/cartActions';
|
} from '../../actions/cartActions';
|
||||||
import {
|
import {
|
||||||
removeFromMockCart,
|
removeFromMockCart,
|
||||||
setMockCartItemQuantity,
|
|
||||||
updateSelectedItems,
|
updateSelectedItems,
|
||||||
} from '../../actions/mockCartActions';
|
} from '../../actions/mockCartActions';
|
||||||
import CustomImage from '../../components/CustomImage/CustomImage';
|
import CustomImage from '../../components/CustomImage/CustomImage';
|
||||||
@@ -97,6 +95,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
// 항상 호출되어야 하는 Hook들
|
// 항상 호출되어야 하는 Hook들
|
||||||
const fallbackCartData = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo);
|
const fallbackCartData = useSelector((state) => state.cart.getMyinfoCartSearch.cartInfo);
|
||||||
const selectedItems = useSelector((state) => state.mockCart.selectedItems || []);
|
const selectedItems = useSelector((state) => state.mockCart.selectedItems || []);
|
||||||
|
const userNumber = useSelector((state) => state.common.appStatus.loginUserData.userNumber);
|
||||||
|
|
||||||
// 실제 장바구니 데이터와 Mock 데이터 중 선택
|
// 실제 장바구니 데이터와 Mock 데이터 중 선택
|
||||||
const cartData = cartInfo || fallbackCartData;
|
const cartData = cartInfo || fallbackCartData;
|
||||||
@@ -138,12 +137,12 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
// 파트너사별 총합 계산
|
// 파트너사별 총합 계산
|
||||||
const calculatePartnerTotal = (items) => {
|
const calculatePartnerTotal = (items) => {
|
||||||
const productTotal = items.reduce((sum, item) =>
|
const productTotal = items.reduce((sum, item) =>
|
||||||
sum + (parseFloat(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) =>
|
const optionTotal = items.reduce((sum, item) =>
|
||||||
// sum + (parseFloat(item.optPrc.replace("$","") || 0) * item.prodQty), 0
|
sum + (parseFloat(Number(item.price5) !== 0 ? Number(item.price5) : Number(item.optPrc) !== 0 ? Number(item.optPrc) : 0) * item.prodQty), 0
|
||||||
// );
|
);
|
||||||
const optionTotal = 0;
|
|
||||||
const shippingTotal = items.reduce((sum, item) =>
|
const shippingTotal = items.reduce((sum, item) =>
|
||||||
sum + parseFloat((item.shippingCharge) * item.prodQty || 0), 0
|
sum + parseFloat((item.shippingCharge) * 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) {
|
if (currentQty > 1) {
|
||||||
const newQty = currentQty - 1;
|
const newQty = currentQty - 1;
|
||||||
|
|
||||||
if (isMockMode) {
|
if (isMockMode) {
|
||||||
dispatch(setMockCartItemQuantity(prodSno, newQty));
|
// dispatch(setMockCartItemQuantity(prodSno, newQty));
|
||||||
} else {
|
} else {
|
||||||
// 실제 API 호출을 위한 사용자 정보 필요
|
// 실제 API 호출을 위한 사용자 정보 필요
|
||||||
const { userNumber } = store.getState().common.appStatus.loginUserData;
|
|
||||||
if (userNumber) {
|
if (userNumber) {
|
||||||
dispatch(updateCartItem({ mbrNo: userNumber, cartSno: prodSno, prodQty: newQty }));
|
dispatch(updateMyinfoCart({
|
||||||
|
mbrNo: userNumber,
|
||||||
|
patnrId,
|
||||||
|
prdtId,
|
||||||
|
prodSno,
|
||||||
|
prodQty: newQty
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [dispatch, isMockMode]);
|
}, [dispatch, isMockMode]);
|
||||||
|
|
||||||
const handleIncreseClick = useCallback((prodSno, currentQty) => {
|
const handleIncreseClick = useCallback((prodSno, patnrId, prdtId, currentQty) => {
|
||||||
const newQty = currentQty + 1;
|
const newQty = currentQty + 1;
|
||||||
|
|
||||||
if (isMockMode) {
|
if (isMockMode) {
|
||||||
dispatch(setMockCartItemQuantity(prodSno, newQty));
|
// dispatch(setMockCartItemQuantity(prodSno, newQty));
|
||||||
} else {
|
} else {
|
||||||
// 실제 API 호출을 위한 사용자 정보 필요
|
// 실제 API 호출을 위한 사용자 정보 필요
|
||||||
const { userNumber } = store.getState().common.appStatus.loginUserData;
|
|
||||||
if (userNumber) {
|
if (userNumber) {
|
||||||
dispatch(updateCartItem({ mbrNo: userNumber, cartSno: prodSno, prodQty: newQty }));
|
dispatch(updateMyinfoCart({ mbrNo: userNumber, patnrId, prdtId, prodSno, prodQty: newQty }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [dispatch, isMockMode]);
|
}, [dispatch, isMockMode]);
|
||||||
@@ -264,11 +269,20 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
[scrollTop]
|
[scrollTop]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//장바구니 삭제
|
||||||
|
const deleteCart = useCallback((patnrId, prdtId, prodSno) => {
|
||||||
|
dispatch(deleteMyinfoCart({
|
||||||
|
mbrNo : userNumber,
|
||||||
|
patnrId: String(patnrId),
|
||||||
|
prdtId : String(prdtId),
|
||||||
|
prodSno : String(prodSno)
|
||||||
|
}))
|
||||||
|
},[dispatch])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Object.entries(groupedCartData).map(([partnerKey, group], index) => {
|
{Object.entries(groupedCartData).map(([partnerKey, group], index) => {
|
||||||
const totals = calculatePartnerTotal(group.items);
|
const totals = calculatePartnerTotal(group.items);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container key={partnerKey} className={css.productBox}>
|
<Container key={partnerKey} className={css.productBox}>
|
||||||
{index === 0 && (
|
{index === 0 && (
|
||||||
@@ -298,13 +312,15 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
Product Total ${totals.productTotal.toLocaleString('en-US', {
|
Product Total ${totals.productTotal.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})} +
|
})} +
|
||||||
|
{totals.optionTotal > 0 && (
|
||||||
{/* Option ${totals.optionTotal.toLocaleString('en-US', {
|
<>
|
||||||
|
Option ${totals.optionTotal.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})} + */}
|
})} +
|
||||||
Option $0.00 +
|
</>
|
||||||
|
)}
|
||||||
S&H ${totals.shippingTotal.toLocaleString('en-US', {
|
S&H ${totals.shippingTotal.toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
@@ -372,20 +388,22 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
)}
|
)}
|
||||||
<div className={css.accountBox}>
|
<div className={css.accountBox}>
|
||||||
<span className={css.account}>
|
<span className={css.account}>
|
||||||
${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,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
<div className={css.accountInfo}>
|
<div className={css.accountInfo}>
|
||||||
{item.price2 && (
|
|
||||||
<span className={css.originalAcc}>
|
<span className={css.originalAcc}>
|
||||||
|
{item.price2 && (parseFloat(item.price2) > 0 && parseFloat(item.price3) > 0 && parseFloat(item.price2) !== parseFloat(item.price3)) && (
|
||||||
|
<>
|
||||||
${parseFloat(item.price2).toLocaleString('en-US', {
|
${parseFloat(item.price2).toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
</span>
|
</>
|
||||||
)}
|
)}
|
||||||
|
</span>
|
||||||
{item.price5 && parseFloat(item.price5) > 0 && (
|
{item.price5 && parseFloat(item.price5) > 0 && (
|
||||||
<span className={css.optionAcc}>
|
<span className={css.optionAcc}>
|
||||||
OPTION : ${parseFloat(item.price5).toLocaleString('en-US', {
|
OPTION : ${parseFloat(item.price5).toLocaleString('en-US', {
|
||||||
@@ -411,13 +429,13 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
item.prodQty === 1 ? css.dimm : ""
|
item.prodQty === 1 ? css.dimm : ""
|
||||||
)}
|
)}
|
||||||
size="cartEa"
|
size="cartEa"
|
||||||
onClick={() => handleDecreseClick(item.prodSno, item.prodQty)}
|
onClick={() => handleDecreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)}
|
||||||
spotlightId={"pd_ea_decrese"}
|
spotlightId={"pd_ea_decrese"}
|
||||||
spotlightDisabled={item.prodQty === 1}
|
spotlightDisabled={item.prodQty === 1}
|
||||||
/>
|
/>
|
||||||
<div className={css.ea}>{item.prodQty}</div>
|
<div className={css.ea}>{item.prodQty}</div>
|
||||||
<TButton
|
<TButton
|
||||||
onClick={() => handleIncreseClick(item.prodSno, item.prodQty)}
|
onClick={() => handleIncreseClick(item.prodSno, item.patnrId, item.prdtId, item.prodQty)}
|
||||||
className={css.plusBox}
|
className={css.plusBox}
|
||||||
spotlightId={"pd_ea_increse"}
|
spotlightId={"pd_ea_increse"}
|
||||||
size="cartEa"
|
size="cartEa"
|
||||||
@@ -430,7 +448,7 @@ const CartProduct = ({ cartInfo, getScrollTo, scrollTop }) => {
|
|||||||
<TButton
|
<TButton
|
||||||
className={css.trashImg}
|
className={css.trashImg}
|
||||||
size="cartTrash"
|
size="cartTrash"
|
||||||
onClick={() => handleDeleteClick(item.prodSno)}
|
onClick={() => deleteCart(item.patnrId, item.prdtId, item.prodSno)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -175,16 +175,16 @@ const CartSidebar = ({ cartInfo }) => {
|
|||||||
// API Mode: 실제 장바구니 데이터로 계산
|
// API Mode: 실제 장바구니 데이터로 계산
|
||||||
const itemCount = displayCartInfo.reduce((sum, item) => sum + (item.prodQty || 1), 0);
|
const itemCount = displayCartInfo.reduce((sum, item) => sum + (item.prodQty || 1), 0);
|
||||||
const subtotal = displayCartInfo.reduce((sum, item) => {
|
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));
|
return sum + (price * (item.prodQty || 1));
|
||||||
}, 0);
|
}, 0);
|
||||||
const optionTotal = displayCartInfo.reduce((sum, item) => {
|
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));
|
return sum + (optionPrice * (item.prodQty || 1));
|
||||||
}, 0);
|
}, 0);
|
||||||
const shippingHandling = displayCartInfo.reduce((sum, item) =>
|
const shippingHandling = displayCartInfo.reduce((sum, item) => {
|
||||||
sum + parseFloat(item.shippingCharge || 0), 0
|
return sum + parseFloat(Number(item.shippingCharge) * (item.prodQty || 1))
|
||||||
);
|
}, 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
itemCount,
|
itemCount,
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ export default function ItemContents({ onClick }) {
|
|||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
data-wheel-point={index >= 5}
|
data-wheel-point={index >= 5}
|
||||||
euEnrgLblInfos={euEnrgLblInfos}
|
euEnrgLblInfos={euEnrgLblInfos}
|
||||||
|
className={css.itemCardNewCate}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-top: 34px;
|
margin-top: 34px;
|
||||||
> div {
|
> div.itemCardNewCate {
|
||||||
margin: 0 15px 15px 0;
|
margin: 0 15px 15px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import {
|
|||||||
sendLogPaymentEntry,
|
sendLogPaymentEntry,
|
||||||
sendLogTotalRecommend,
|
sendLogTotalRecommend,
|
||||||
} from '../../actions/logActions';
|
} from '../../actions/logActions';
|
||||||
import { popPanel, updatePanel } from '../../actions/panelActions';
|
import {
|
||||||
|
popPanel,
|
||||||
|
updatePanel,
|
||||||
|
} from '../../actions/panelActions';
|
||||||
import TBody from '../../components/TBody/TBody';
|
import TBody from '../../components/TBody/TBody';
|
||||||
import TButton from '../../components/TButton/TButton';
|
import TButton from '../../components/TButton/TButton';
|
||||||
import TButtonScroller from '../../components/TButtonScroller/TButtonScroller';
|
import TButtonScroller from '../../components/TButtonScroller/TButtonScroller';
|
||||||
@@ -615,7 +618,7 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
<TBody className={css.tbody} cbScrollTo={getScrollToBody}>
|
<TBody className={css.tbody} cbScrollTo={getScrollToBody}>
|
||||||
<THeader className={css.theader} title="CHECKOUT" onBackButton onClick={onBackClick} />
|
<THeader className={css.theader} title="CHECKOUT" onBackButton onClick={onBackClick} />
|
||||||
<div className={css.Wrap}>
|
<div className={css.Wrap}>
|
||||||
{BUYNOW_CONFIG.isMockMode() ? (
|
{/* {BUYNOW_CONFIG.isMockMode() ? (
|
||||||
<SummaryContainerMock
|
<SummaryContainerMock
|
||||||
setPlaceOrderPopup={setPlaceOrderPopup}
|
setPlaceOrderPopup={setPlaceOrderPopup}
|
||||||
empTermsData={empTermsData}
|
empTermsData={empTermsData}
|
||||||
@@ -629,7 +632,7 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
defaultPrice={panelInfo?.defaultPrice}
|
defaultPrice={panelInfo?.defaultPrice}
|
||||||
fromCartPanel={panelInfo?.fromCartPanel}
|
fromCartPanel={panelInfo?.fromCartPanel}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : ( */}
|
||||||
<SummaryContainer
|
<SummaryContainer
|
||||||
setPlaceOrderPopup={setPlaceOrderPopup}
|
setPlaceOrderPopup={setPlaceOrderPopup}
|
||||||
empTermsData={empTermsData}
|
empTermsData={empTermsData}
|
||||||
@@ -638,8 +641,8 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
currSignLoc={currSignLoc}
|
currSignLoc={currSignLoc}
|
||||||
doSendLogPaymentEntry={doSendLogPaymentEntry}
|
doSendLogPaymentEntry={doSendLogPaymentEntry}
|
||||||
/>
|
/>
|
||||||
)}
|
{/* )} */}
|
||||||
{BUYNOW_CONFIG.isMockMode() ? (
|
{/* {BUYNOW_CONFIG.isMockMode() ? (
|
||||||
<InformationContainerMock
|
<InformationContainerMock
|
||||||
toggleOrderSideBar={toggleOrderSideBar}
|
toggleOrderSideBar={toggleOrderSideBar}
|
||||||
toggleOfferSideBar={toggleOfferSideBar}
|
toggleOfferSideBar={toggleOfferSideBar}
|
||||||
@@ -647,14 +650,14 @@ export default function CheckOutPanel({ panelInfo }) {
|
|||||||
doSendLogMyInfoEdit={doSendLogMyInfoEdit}
|
doSendLogMyInfoEdit={doSendLogMyInfoEdit}
|
||||||
orderItemsCount={orderItemsCount}
|
orderItemsCount={orderItemsCount}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : ( */}
|
||||||
<InformationContainer
|
<InformationContainer
|
||||||
toggleOrderSideBar={toggleOrderSideBar}
|
toggleOrderSideBar={toggleOrderSideBar}
|
||||||
toggleOfferSideBar={toggleOfferSideBar}
|
toggleOfferSideBar={toggleOfferSideBar}
|
||||||
scrollTopBody={scrollTopBody}
|
scrollTopBody={scrollTopBody}
|
||||||
doSendLogMyInfoEdit={doSendLogMyInfoEdit}
|
doSendLogMyInfoEdit={doSendLogMyInfoEdit}
|
||||||
/>
|
/>
|
||||||
)}
|
{/* )} */}
|
||||||
</div>
|
</div>
|
||||||
</TBody>
|
</TBody>
|
||||||
</TPanel>
|
</TPanel>
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ export default memo(function OrderItemCard({
|
|||||||
const priceTotalData = useSelector(
|
const priceTotalData = useSelector(
|
||||||
(state) => state.checkout?.checkoutTotalData
|
(state) => state.checkout?.checkoutTotalData
|
||||||
);
|
);
|
||||||
console.log("###priceTotalData",priceTotalData);
|
|
||||||
|
|
||||||
const formattedPrices = useMemo(() => {
|
const formattedPrices = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
@@ -83,7 +82,7 @@ export default memo(function OrderItemCard({
|
|||||||
<p className={css.priceWrap}>
|
<p className={css.priceWrap}>
|
||||||
<span className={css.itemPrice}>
|
<span className={css.itemPrice}>
|
||||||
<span className={css.discountedPrice}>
|
<span className={css.discountedPrice}>
|
||||||
$ {(price * prodQty).toLocaleString('en-US', {
|
$ {(Number(price) * Number(prodQty)).toLocaleString('en-US', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
maximumFractionDigits: 2
|
maximumFractionDigits: 2
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -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 Spotlight from '@enact/spotlight';
|
||||||
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
import SpotlightContainerDecorator
|
||||||
|
from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
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 { popPanel } from '../../../actions/panelActions';
|
||||||
import TButton from '../../../components/TButton/TButton';
|
import TButton from '../../../components/TButton/TButton';
|
||||||
import TPopUp from '../../../components/TPopUp/TPopUp';
|
import TPopUp from '../../../components/TPopUp/TPopUp';
|
||||||
import TQRCode from '../../../components/TQRCode/TQRCode';
|
import TQRCode from '../../../components/TQRCode/TQRCode';
|
||||||
import useScrollTo from '../../../hooks/useScrollTo';
|
import useScrollTo from '../../../hooks/useScrollTo';
|
||||||
import useScrollTopByDistance from '../../../hooks/useScrollTopByDistance';
|
import useScrollTopByDistance from '../../../hooks/useScrollTopByDistance';
|
||||||
|
import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig';
|
||||||
import * as Config from '../../../utils/Config';
|
import * as Config from '../../../utils/Config';
|
||||||
import { $L, getQRCodeUrl } from '../../../utils/helperMethods';
|
import {
|
||||||
|
$L,
|
||||||
|
getQRCodeUrl,
|
||||||
|
} from '../../../utils/helperMethods';
|
||||||
import BillingAddressCard from '../components/BillingAddressCard';
|
import BillingAddressCard from '../components/BillingAddressCard';
|
||||||
import PaymentCard from '../components/PaymentCard';
|
import PaymentCard from '../components/PaymentCard';
|
||||||
import ShippingAddressCard from '../components/ShippingAddressCard';
|
import ShippingAddressCard from '../components/ShippingAddressCard';
|
||||||
import Subject from '../components/Subject';
|
import Subject from '../components/Subject';
|
||||||
import css from './InformationContainer.module.less';
|
import css from './InformationContainer.module.less';
|
||||||
import { sendLogTotalRecommend } from '../../../actions/logActions';
|
|
||||||
import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig';
|
|
||||||
|
|
||||||
const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||||
|
|
||||||
@@ -282,9 +297,12 @@ export default function InformationContainer({
|
|||||||
ADD/EDIT
|
ADD/EDIT
|
||||||
</TButton>
|
</TButton>
|
||||||
{/* BillingAddressCard disabled due to infinite render loop in Mock Mode */}
|
{/* BillingAddressCard disabled due to infinite render loop in Mock Mode */}
|
||||||
<div style={{ padding: '10px', textAlign: 'center', color: '#999' }}>
|
{/* <div style={{ padding: '10px', textAlign: 'center', color: '#999' }}>
|
||||||
Mock Billing Address
|
Mock Billing Address
|
||||||
</div>
|
</div> */}
|
||||||
|
{checkoutData?.billingAddressList && (
|
||||||
|
<BillingAddressCard list={checkoutData.billingAddressList} onFocus={handleFocus} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={css.listBox}>
|
<div className={css.listBox}>
|
||||||
<Subject title="PATMENT METHOD" />
|
<Subject title="PATMENT METHOD" />
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export default function OrderItemsSideBar({
|
|||||||
patncLogPath={item.patncLogPath}
|
patncLogPath={item.patncLogPath}
|
||||||
prdtId={item.prdtId}
|
prdtId={item.prdtId}
|
||||||
expsPrdtNo={item.expsPrdtNo}
|
expsPrdtNo={item.expsPrdtNo}
|
||||||
price={item.price >= item.originalPrice ? item.originalPrice : item.price}
|
price={item.price2 >= item.price3 ? item.price3 : item.price2}
|
||||||
currSign={item.currSign}
|
currSign={item.currSign}
|
||||||
currSignLoc={item.currSignLoc}
|
currSignLoc={item.currSignLoc}
|
||||||
shippingCharge={item.shippingCharge}
|
shippingCharge={item.shippingCharge}
|
||||||
|
|||||||
@@ -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 {
|
||||||
import { popPanel } from "../../../actions/panelActions";
|
setHidePopup,
|
||||||
import TButton from "../../../components/TButton/TButton";
|
setShowPopup,
|
||||||
import TPopUp from "../../../components/TPopUp/TPopUp";
|
} from '../../../actions/commonActions';
|
||||||
import * as Config from "../../../utils/Config";
|
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 {
|
import {
|
||||||
$L,
|
$L,
|
||||||
formatCurrencyValue,
|
formatCurrencyValue,
|
||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
} from "../../../utils/helperMethods";
|
} from '../../../utils/helperMethods';
|
||||||
import css from "./SummaryContainer.module.less";
|
import css from './SummaryContainer.module.less';
|
||||||
import { sendLogTotalRecommend } from "../../../actions/logActions";
|
|
||||||
|
|
||||||
const Container = SpotlightContainerDecorator(
|
const Container = SpotlightContainerDecorator(
|
||||||
{ enterTo: "last-focused" },
|
{ enterTo: "last-focused" },
|
||||||
@@ -51,12 +62,12 @@ export default function SummaryContainer({
|
|||||||
|
|
||||||
// Mock Mode: priceTotalData가 없으면 가짜 데이터 제공
|
// Mock Mode: priceTotalData가 없으면 가짜 데이터 제공
|
||||||
const effectivePriceTotalData = hasValidPriceTotalData ? priceTotalData : {
|
const effectivePriceTotalData = hasValidPriceTotalData ? priceTotalData : {
|
||||||
totProdPrc: 521.66,
|
totProdPrc: 0.00,
|
||||||
totDcAmt: 0,
|
totDcAmt: 0,
|
||||||
totDlvrAmt: 0,
|
totDlvrAmt: 0,
|
||||||
ordPmtNoTaxAmt: 521.66,
|
ordPmtNoTaxAmt: 0.0,
|
||||||
ordTotTaxAmt: 50,
|
ordTotTaxAmt: 0,
|
||||||
ordPmtReqAmt: 571.66
|
ordPmtReqAmt: 0.00,
|
||||||
};
|
};
|
||||||
|
|
||||||
const items = useMemo(
|
const items = useMemo(
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ export default function ProductAllSection({
|
|||||||
const [isShowQRCode, setIsShowQRCode] = useState(true);
|
const [isShowQRCode, setIsShowQRCode] = useState(true);
|
||||||
const timerRef = useRef(null);
|
const timerRef = useRef(null);
|
||||||
|
|
||||||
|
//구매 하단 토스트 노출 확인을 위한 용도
|
||||||
|
const [openToast, setOpenToast] = useState(false);
|
||||||
|
|
||||||
// 모든 timeout/timer를 추적하기 위한 ref
|
// 모든 timeout/timer를 추적하기 위한 ref
|
||||||
const timersRef = useRef([]);
|
const timersRef = useRef([]);
|
||||||
|
|
||||||
@@ -378,31 +381,36 @@ export default function ProductAllSection({
|
|||||||
prdtNm: productData?.prdtNm,
|
prdtNm: productData?.prdtNm,
|
||||||
hasProductData: !!productData,
|
hasProductData: !!productData,
|
||||||
});
|
});
|
||||||
|
if(openToast === false){
|
||||||
dispatch(
|
dispatch(
|
||||||
showToast({
|
showToast({
|
||||||
id: productData.prdtId,
|
id: productData.prdtId,
|
||||||
message: '',
|
message: '',
|
||||||
type: 'buyOption',
|
type: 'buyOption',
|
||||||
duration: 0,
|
duration: 0,
|
||||||
position: 'bottom-center',
|
position: 'bottom-center',
|
||||||
// 🚀 BuyOption에 전달할 props 데이터
|
// 🚀 BuyOption에 전달할 props 데이터
|
||||||
productInfo: productData,
|
productInfo: productData,
|
||||||
selectedPatnrId: productData?.patnrId,
|
selectedPatnrId: productData?.patnrId,
|
||||||
selectedPrdtId: productData?.prdtId,
|
selectedPrdtId: productData?.prdtId,
|
||||||
// BuyOption Toast가 닫힐 때 BUY NOW 버튼으로 포커스 복구
|
// BuyOption Toast가 닫힐 때 BUY NOW 버튼으로 포커스 복구
|
||||||
onToastClose: () => {
|
onToastClose: () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Spotlight.focus('detail-buy-now-button');
|
setOpenToast(false);
|
||||||
}, 100);
|
Spotlight.focus('detail-buy-now-button');
|
||||||
},
|
}, 100);
|
||||||
})
|
},
|
||||||
);
|
})
|
||||||
}, [dispatch, productData]);
|
);
|
||||||
|
|
||||||
|
setOpenToast(true);
|
||||||
|
}
|
||||||
|
}, [dispatch, productData, openToast]);
|
||||||
|
|
||||||
//닫히도록
|
//닫히도록
|
||||||
const handleCloseToast = useCallback(() => {
|
const handleCloseToast = useCallback(() => {
|
||||||
dispatch(clearAllToasts())
|
dispatch(clearAllToasts());
|
||||||
|
setOpenToast(false);
|
||||||
},[dispatch])
|
},[dispatch])
|
||||||
|
|
||||||
// 스크롤 컨테이너의 클릭 이벤트 추적용 로깅
|
// 스크롤 컨테이너의 클릭 이벤트 추적용 로깅
|
||||||
|
|||||||
@@ -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 { Job } from '@enact/core/util';
|
||||||
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
import SpotlightContainerDecorator
|
||||||
|
from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
|
|
||||||
import { clearThemeDetail } from '../../../../actions/homeActions';
|
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 { finishVideoPreview } from '../../../../actions/playActions';
|
||||||
import THeader from '../../../../components/THeader/THeader';
|
import THeader from '../../../../components/THeader/THeader';
|
||||||
import TItemCard from '../../../../components/TItemCard/TItemCard';
|
import TItemCardNew from '../../../../components/TItemCard/TItemCard.new';
|
||||||
import TVerticalPagenator from '../../../../components/TVerticalPagenator/TVerticalPagenator';
|
import TVerticalPagenator
|
||||||
import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList';
|
from '../../../../components/TVerticalPagenator/TVerticalPagenator';
|
||||||
|
import TVirtualGridList
|
||||||
|
from '../../../../components/TVirtualGridList/TVirtualGridList';
|
||||||
import useScrollTo from '../../../../hooks/useScrollTo';
|
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 { $L } from '../../../../utils/helperMethods';
|
||||||
import css from './YouMayAlsoLike.module.less';
|
import css from './YouMayAlsoLike.module.less';
|
||||||
|
|
||||||
@@ -136,6 +156,7 @@ export default function YouMayAlsoLike({
|
|||||||
patncNm,
|
patncNm,
|
||||||
brndNm,
|
brndNm,
|
||||||
lgCatCd,
|
lgCatCd,
|
||||||
|
euEnrgLblInfos,
|
||||||
} = product;
|
} = product;
|
||||||
|
|
||||||
const handleItemClick = () => {
|
const handleItemClick = () => {
|
||||||
@@ -166,8 +187,9 @@ export default function YouMayAlsoLike({
|
|||||||
cursorOpen.current.stop();
|
cursorOpen.current.stop();
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<TItemCard
|
<TItemCardNew
|
||||||
key={prdtId}
|
key={prdtId}
|
||||||
|
className={css.itemCardNew}
|
||||||
contextName={LOG_CONTEXT_NAME.YOUMAYLIKE}
|
contextName={LOG_CONTEXT_NAME.YOUMAYLIKE}
|
||||||
messageId={LOG_MESSAGE_ID.CONTENTCLICK}
|
messageId={LOG_MESSAGE_ID.CONTENTCLICK}
|
||||||
productId={prdtId}
|
productId={prdtId}
|
||||||
@@ -185,6 +207,7 @@ export default function YouMayAlsoLike({
|
|||||||
onClick={handleItemClick}
|
onClick={handleItemClick}
|
||||||
label={index * 1 + 1 + ' of ' + newYoumaylikeProductData.length}
|
label={index * 1 + 1 + ' of ' + newYoumaylikeProductData.length}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
|
euEnrgLblInfos={euEnrgLblInfos}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
// margin-top: 34px;
|
// margin-top: 34px;
|
||||||
> div {
|
> div.itemCardNew {
|
||||||
/* item card */
|
/* item card */
|
||||||
margin: 0 15px 15px 0;
|
margin: 0 15px 15px 0;
|
||||||
.size(@w:360px,@h:494px);
|
.size(@w:360px,@h:494px);
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
> div:nth-child(2) {
|
> div:nth-child(2) {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
/* desc wrapper */
|
/* desc wrapper */
|
||||||
> div > h3 {
|
> div > div > h3 {
|
||||||
/* title */
|
/* title */
|
||||||
color: rgba(234, 234, 234, 1);
|
color: rgba(234, 234, 234, 1);
|
||||||
.size(@w:100%,@h:64px);
|
.size(@w:100%,@h:64px);
|
||||||
|
|||||||
@@ -1,19 +1,59 @@
|
|||||||
import React, {
|
import React, {
|
||||||
useCallback,
|
useCallback,
|
||||||
useMemo,
|
useMemo,
|
||||||
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
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 usePriceInfo from '../../../../hooks/usePriceInfo';
|
||||||
|
import * as Config from '../../../../utils/Config';
|
||||||
import { $L } from '../../../../utils/helperMethods';
|
import { $L } from '../../../../utils/helperMethods';
|
||||||
|
import { SpotlightIds } from '../../../../utils/SpotlightIds';
|
||||||
import BuyNowPriceDisplay from './BuyNowPriceDisplay/BuyNowPriceDisplay';
|
import BuyNowPriceDisplay from './BuyNowPriceDisplay/BuyNowPriceDisplay';
|
||||||
import css from './ProductPriceDisplay.module.less';
|
import css from './ProductPriceDisplay.module.less';
|
||||||
import ShopByMobilePriceDisplay
|
import ShopByMobilePriceDisplay
|
||||||
from './ShopByMobilePriceDisplay/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 }) {
|
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(
|
const webOSVersion = useSelector(
|
||||||
(state) => state.common.appStatus.webOSVersion
|
(state) => state.common.appStatus.webOSVersion
|
||||||
);
|
);
|
||||||
@@ -27,6 +67,7 @@ export default function ProductPriceDisplay({ productType, productInfo }) {
|
|||||||
patnrName,
|
patnrName,
|
||||||
installmentMonths,
|
installmentMonths,
|
||||||
orderPhnNo,
|
orderPhnNo,
|
||||||
|
euEnrgLblInfos,
|
||||||
} = productInfo;
|
} = productInfo;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -65,6 +106,67 @@ export default function ProductPriceDisplay({ productType, productInfo }) {
|
|||||||
);
|
);
|
||||||
}, [productType, productInfo?.pmtSuptYn, webOSVersion]);
|
}, [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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{productType && productInfo && (
|
{productType && productInfo && (
|
||||||
@@ -91,8 +193,125 @@ export default function ProductPriceDisplay({ productType, productInfo }) {
|
|||||||
isDiscounted={isDiscounted}
|
isDiscounted={isDiscounted}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<div className={css.enrgLbImgBox}>
|
||||||
|
{euEnrgLblInfos && (countryCode === "GB" || countryCode === "DE") && euEnrgLblInfos.map((item, index)=>{
|
||||||
|
return(
|
||||||
|
<SpottableComponent
|
||||||
|
key={index}
|
||||||
|
spotlightDisabled={Boolean(!cursorVisible)}
|
||||||
|
onClick={(e) => onEnergyClick(e, item.enrgLblUrl)}
|
||||||
|
aria-label={`Energy Efficiency ${item.enrgGrade || ""}`}
|
||||||
|
className={css.enrgLbImg}
|
||||||
|
>
|
||||||
|
<CustomImage
|
||||||
|
alt={`Energy Label ${item.enrgGrade || index + 1}`}
|
||||||
|
delay={0}
|
||||||
|
src={item.enrgLblIcnUrl}
|
||||||
|
/>
|
||||||
|
</SpottableComponent>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{(() => {
|
||||||
|
// 팝업이 표시되어야 하는 조건 검증
|
||||||
|
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 (
|
||||||
|
<TPopUp
|
||||||
|
kind="energyPopup"
|
||||||
|
title={$L("Energy Efficiency")}
|
||||||
|
hasText
|
||||||
|
open={popupVisible}
|
||||||
|
hasButton
|
||||||
|
button1Text={$L("CLOSE")}
|
||||||
|
onClose={handleClosePopup}
|
||||||
|
>
|
||||||
|
<div className={css.energyPopupContent}>
|
||||||
|
{convert ? (
|
||||||
|
<>
|
||||||
|
<div className={css.energyImagesContainer}>
|
||||||
|
{convert.convertedImage ? (
|
||||||
|
<img
|
||||||
|
alt="Energy Label"
|
||||||
|
src={convert.convertedImage}
|
||||||
|
className={css.energyImage}
|
||||||
|
/>
|
||||||
|
) : convert.error ? (
|
||||||
|
<div>
|
||||||
|
<p>{$L(STRING_CONF.ENERGY_ERROR)}</p>
|
||||||
|
<p style={{ fontSize: "0.8em", marginTop: "10px" }}>
|
||||||
|
{convert.error?.message || String(convert.error)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : convert.isConverting ? (
|
||||||
|
<div>
|
||||||
|
<p>{$L(STRING_CONF.ENERGY_LOADING)}</p>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontSize: "0.8em",
|
||||||
|
marginTop: "10px",
|
||||||
|
color: "#999",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Converting PDF to image... (attempt in progress)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<p>{$L(STRING_CONF.ENERGY_ERROR)}</p>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontSize: "0.8em",
|
||||||
|
marginTop: "10px",
|
||||||
|
color: "#999",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Unknown state - no image or error
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<p>{$L(STRING_CONF.ENERGY_ERROR)}</p>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontSize: "0.8em",
|
||||||
|
marginTop: "10px",
|
||||||
|
color: "#999",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Convert reducer state not found
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TPopUp>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; // 비율 유지하면서 컨테이너에 맞춤
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ import Spotlight from '@enact/spotlight';
|
|||||||
import SpotlightContainerDecorator
|
import SpotlightContainerDecorator
|
||||||
from '@enact/spotlight/SpotlightContainerDecorator';
|
from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
|
|
||||||
import { addToCart } from '../../../actions/cartActions';
|
import {
|
||||||
|
addToCart,
|
||||||
|
insertMyinfoCart,
|
||||||
|
} from '../../../actions/cartActions';
|
||||||
import { getMyInfoCheckoutInfo } from '../../../actions/checkoutActions';
|
import { getMyInfoCheckoutInfo } from '../../../actions/checkoutActions';
|
||||||
import {
|
import {
|
||||||
changeAppStatus,
|
changeAppStatus,
|
||||||
@@ -33,7 +36,10 @@ import {
|
|||||||
popPanel,
|
popPanel,
|
||||||
pushPanel,
|
pushPanel,
|
||||||
} from '../../../actions/panelActions';
|
} from '../../../actions/panelActions';
|
||||||
import { clearAllVideoTimers, finishVideoPreview } from '../../../actions/playActions';
|
import {
|
||||||
|
clearAllVideoTimers,
|
||||||
|
finishVideoPreview,
|
||||||
|
} from '../../../actions/playActions';
|
||||||
import {
|
import {
|
||||||
getProductOption,
|
getProductOption,
|
||||||
getProductOptionId,
|
getProductOptionId,
|
||||||
@@ -463,7 +469,7 @@ const BuyOption = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API Mode: 실제 API 호출
|
// API Mode: 실제 API 호출
|
||||||
if (!isMockMode) {
|
if (!isMockMode) {
|
||||||
// ⚠️ 필수 값 검증
|
// ⚠️ 필수 값 검증
|
||||||
if (!selectedPatnrId || !selectedPrdtId) {
|
if (!selectedPatnrId || !selectedPrdtId) {
|
||||||
console.warn('[BuyOption] ⚠️ [getProductOption] MISSING REQUIRED PARAMS', {
|
console.warn('[BuyOption] ⚠️ [getProductOption] MISSING REQUIRED PARAMS', {
|
||||||
@@ -550,7 +556,7 @@ const BuyOption = ({
|
|||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
if (response.retCode === 0) {
|
if (response.retCode === 0) {
|
||||||
// 🔍 조건 체크
|
// 🔍 조건 체크
|
||||||
const isCardInfoNull = response.data.cardInfo === null;
|
const isCardInfoNull = response.data.cardInfo === null;
|
||||||
const isBillingAddressEmpty = response.data.billingAddressList.length === 0;
|
const isBillingAddressEmpty = response.data.billingAddressList.length === 0;
|
||||||
const isShippingAddressEmpty = response.data.shippingAddressList.length === 0;
|
const isShippingAddressEmpty = response.data.shippingAddressList.length === 0;
|
||||||
@@ -623,7 +629,7 @@ const BuyOption = ({
|
|||||||
response.retDetailCode,
|
response.retDetailCode,
|
||||||
response.returnBindStrings
|
response.returnBindStrings
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
dispatch(changeAppStatus({ isLoading: false }));
|
dispatch(changeAppStatus({ isLoading: false }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1081,17 +1087,18 @@ const BuyOption = ({
|
|||||||
|
|
||||||
if (!isMock) {
|
if (!isMock) {
|
||||||
dispatch(
|
dispatch(
|
||||||
addToCart({
|
insertMyinfoCart({
|
||||||
mbrNo: userNumber,
|
mbrNo: userNumber,
|
||||||
patnrId: selectedPatnrId,
|
patnrId: selectedPatnrId,
|
||||||
prdtId: selectedPrdtId,
|
prdtId: selectedPrdtId,
|
||||||
prodQty: String(effectiveQuantity),
|
prodQty: Number(effectiveQuantity),
|
||||||
prdtOpt: {
|
prdtOpt: [{
|
||||||
prodOptCdCval: optionForUse?.prodOptCdCval || '',
|
|
||||||
prodOptCval: optionLabel,
|
|
||||||
prodOptSno: productOptionInfos?.[0]?.prodOptSno || '',
|
prodOptSno: productOptionInfos?.[0]?.prodOptSno || '',
|
||||||
|
prodOptCdCval: optionForUse?.prodOptCdCval || '',
|
||||||
prodOptTpCdCval: productOptionInfos?.[0]?.prodOptTpCdCval || '',
|
prodOptTpCdCval: productOptionInfos?.[0]?.prodOptTpCdCval || '',
|
||||||
},
|
prodOptCval: optionLabel,
|
||||||
|
}],
|
||||||
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1405,7 +1412,7 @@ const BuyOption = ({
|
|||||||
{/* 동적 옵션 렌더링 */}
|
{/* 동적 옵션 렌더링 */}
|
||||||
{productOptionInfos &&
|
{productOptionInfos &&
|
||||||
productOptionInfos?.length > 0 &&
|
productOptionInfos?.length > 0 &&
|
||||||
(productInfo?.optProdYn === 'Y' || hasMockOptions) && (
|
productInfo?.optProdYn === 'Y' && (
|
||||||
<>
|
<>
|
||||||
{/* 첫번째 옵션 (여러 옵션이 있을 때만) */}
|
{/* 첫번째 옵션 (여러 옵션이 있을 때만) */}
|
||||||
{productOptionInfos?.length > 1 && (
|
{productOptionInfos?.length > 1 && (
|
||||||
|
|||||||
@@ -68,17 +68,60 @@ const BestSeller = ({
|
|||||||
const { cursorVisible } = useSelector((state) => state.common.appStatus);
|
const { cursorVisible } = useSelector((state) => state.common.appStatus);
|
||||||
|
|
||||||
const bestSellerDatas = useSelector(
|
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 [drawChk, setDrawChk] = useState(false);
|
||||||
const [firstChk, setFirstChk] = useState(0);
|
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(() => {
|
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);
|
setDrawChk(true);
|
||||||
}, [bestSellerDatas]);
|
}, [bestSellerNewDatas]);
|
||||||
|
|
||||||
const handleCardClick = useCallback(
|
const handleCardClick = useCallback(
|
||||||
(patnrId, prdtId) => () => {
|
(patnrId, prdtId) => () => {
|
||||||
@@ -176,22 +219,7 @@ const BestSeller = ({
|
|||||||
handleShelfFocus();
|
handleShelfFocus();
|
||||||
}
|
}
|
||||||
}, [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 (
|
return (
|
||||||
<Container
|
<Container
|
||||||
@@ -213,8 +241,8 @@ const BestSeller = ({
|
|||||||
cbScrollTo={getScrollTo}
|
cbScrollTo={getScrollTo}
|
||||||
noScrollByWheel
|
noScrollByWheel
|
||||||
>
|
>
|
||||||
{bestSellerNewData &&
|
{bestItemNewData &&
|
||||||
bestSellerNewData.map(
|
bestItemNewData.map(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
prdtId,
|
prdtId,
|
||||||
@@ -226,8 +254,8 @@ const BestSeller = ({
|
|||||||
offerInfo,
|
offerInfo,
|
||||||
brndNm,
|
brndNm,
|
||||||
patncNm,
|
patncNm,
|
||||||
catNm,
|
//catNm, 없음
|
||||||
//foryou,
|
foryou,
|
||||||
euEnrgLblInfos,
|
euEnrgLblInfos,
|
||||||
},
|
},
|
||||||
itemIndex
|
itemIndex
|
||||||
@@ -251,7 +279,7 @@ const BestSeller = ({
|
|||||||
shelfTitle={shelfTitle}
|
shelfTitle={shelfTitle}
|
||||||
patnerName={patncNm}
|
patnerName={patncNm}
|
||||||
brandName={brndNm}
|
brandName={brndNm}
|
||||||
catNm={catNm}
|
// catNm={catNm}
|
||||||
imageAlt={prdtId}
|
imageAlt={prdtId}
|
||||||
imageSource={imgUrl}
|
imageSource={imgUrl}
|
||||||
priceInfo={priceInfo}
|
priceInfo={priceInfo}
|
||||||
@@ -265,11 +293,11 @@ const BestSeller = ({
|
|||||||
offerInfo={offerInfo}
|
offerInfo={offerInfo}
|
||||||
spotlightId={"bestsellerItem" + itemIndex}
|
spotlightId={"bestsellerItem" + itemIndex}
|
||||||
firstLabel={rankText}
|
firstLabel={rankText}
|
||||||
label={itemIndex * 1 + 1 + " of " + bestSellerNewData.length}
|
label={itemIndex * 1 + 1 + " of " + bestItemNewData.length}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
euEnrgLblInfos={euEnrgLblInfos}
|
euEnrgLblInfos={euEnrgLblInfos}
|
||||||
>
|
>
|
||||||
{/* {foryou === true && <Tag text={"For You"} />} */}
|
{foryou === true && <Tag text={"For You"} />}
|
||||||
</TItemCardNew>
|
</TItemCardNew>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -290,4 +318,4 @@ const BestSeller = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BestSeller;
|
export default BestSeller;
|
||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
setOptionalTermsUserDecision,
|
setOptionalTermsUserDecision,
|
||||||
updateOptionalTermsAgreement,
|
updateOptionalTermsAgreement,
|
||||||
} from '../../../actions/commonActions';
|
} from '../../../actions/commonActions';
|
||||||
import { getJustForYouInfo } from '../../../actions/forYouActions';
|
import { justForYou } from '../../../actions/forYouActions';
|
||||||
import {
|
import {
|
||||||
fetchCurrentUserHomeTerms,
|
fetchCurrentUserHomeTerms,
|
||||||
setDefaultFocus,
|
setDefaultFocus,
|
||||||
@@ -39,11 +39,11 @@ import {
|
|||||||
pushPanel,
|
pushPanel,
|
||||||
} from '../../../actions/panelActions';
|
} from '../../../actions/panelActions';
|
||||||
import {
|
import {
|
||||||
|
clearAllVideoTimers,
|
||||||
releasePlayControl,
|
releasePlayControl,
|
||||||
requestPlayControl,
|
requestPlayControl,
|
||||||
startVideoPlayer,
|
startVideoPlayer,
|
||||||
startVideoPlayerNew,
|
startVideoPlayerNew,
|
||||||
clearAllVideoTimers,
|
|
||||||
} from '../../../actions/playActions';
|
} from '../../../actions/playActions';
|
||||||
import CustomImage from '../../../components/CustomImage/CustomImage';
|
import CustomImage from '../../../components/CustomImage/CustomImage';
|
||||||
// import TButtonScroller from "../../../components/TButtonScroller/TButtonScroller";
|
// import TButtonScroller from "../../../components/TButtonScroller/TButtonScroller";
|
||||||
@@ -82,8 +82,8 @@ export default function HomeBanner({
|
|||||||
handleShelfFocus,
|
handleShelfFocus,
|
||||||
}) {
|
}) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getJustForYouInfo());
|
dispatch(justForYou());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
const homeTopDisplayInfo = useSelector(
|
const homeTopDisplayInfo = useSelector(
|
||||||
(state) => state.home.homeTopDisplayInfo
|
(state) => state.home.homeTopDisplayInfo
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export default function RollingUnit({
|
|||||||
const nowMenu = useSelector((state) => state.common.menu.nowMenu);
|
const nowMenu = useSelector((state) => state.common.menu.nowMenu);
|
||||||
const entryMenu = useSelector((state) => state.common.menu.entryMenu);
|
const entryMenu = useSelector((state) => state.common.menu.entryMenu);
|
||||||
const introTermsAgree = useSelector(
|
const introTermsAgree = useSelector(
|
||||||
(state) => state.common.termsFlag.optionalTerms
|
(state) => state.common.optionalTermsAgree
|
||||||
);
|
);
|
||||||
const homeCategory = useSelector(
|
const homeCategory = useSelector(
|
||||||
(state) => state.home.menuData?.data?.homeCategory
|
(state) => state.home.menuData?.data?.homeCategory
|
||||||
@@ -120,7 +120,7 @@ export default function RollingUnit({
|
|||||||
// 컴포넌트 상단에서 필터링
|
// 컴포넌트 상단에서 필터링
|
||||||
const filteredRollingData = useMemo(() => {
|
const filteredRollingData = useMemo(() => {
|
||||||
return rollingData.filter(
|
return rollingData.filter(
|
||||||
(item) => introTermsAgree === "Y" || item.shptmLnkTpCd !== "DSP00510"
|
(item) => introTermsAgree === true || item.shptmLnkTpCd !== "DSP00510"
|
||||||
);
|
);
|
||||||
}, [rollingData, introTermsAgree]);
|
}, [rollingData, introTermsAgree]);
|
||||||
|
|
||||||
|
|||||||
@@ -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 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 Spotlight from '@enact/spotlight';
|
||||||
import {
|
import {
|
||||||
@@ -23,20 +33,31 @@ import {
|
|||||||
getHomeMainContents,
|
getHomeMainContents,
|
||||||
updateHomeInfo,
|
updateHomeInfo,
|
||||||
} from '../../actions/homeActions';
|
} from '../../actions/homeActions';
|
||||||
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions';
|
import {
|
||||||
import { getSubCategory, getTop20Show } from '../../actions/mainActions';
|
sendLogGNB,
|
||||||
|
sendLogTotalRecommend,
|
||||||
|
} from '../../actions/logActions';
|
||||||
|
import {
|
||||||
|
getSubCategory,
|
||||||
|
getTop20Show,
|
||||||
|
} from '../../actions/mainActions';
|
||||||
import { getHomeOnSaleInfo } from '../../actions/onSaleActions';
|
import { getHomeOnSaleInfo } from '../../actions/onSaleActions';
|
||||||
import { finishVideoPreview, shrinkVideoTo1px, expandVideoFrom1px } from '../../actions/playActions';
|
|
||||||
import { updatePanel } from '../../actions/panelActions';
|
import { updatePanel } from '../../actions/panelActions';
|
||||||
|
import {
|
||||||
|
expandVideoFrom1px,
|
||||||
|
finishVideoPreview,
|
||||||
|
shrinkVideoTo1px,
|
||||||
|
} from '../../actions/playActions';
|
||||||
import { getBestSeller } from '../../actions/productActions';
|
import { getBestSeller } from '../../actions/productActions';
|
||||||
import TBody from '../../components/TBody/TBody';
|
import TBody from '../../components/TBody/TBody';
|
||||||
import TButton, { TYPES } from '../../components/TButton/TButton';
|
import TButton, { TYPES } from '../../components/TButton/TButton';
|
||||||
import TPanel from '../../components/TPanel/TPanel';
|
import TPanel from '../../components/TPanel/TPanel';
|
||||||
import TPopUp from '../../components/TPopUp/TPopUp';
|
import TPopUp from '../../components/TPopUp/TPopUp';
|
||||||
import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator';
|
import TVerticalPagenator
|
||||||
|
from '../../components/TVerticalPagenator/TVerticalPagenator';
|
||||||
import useDebugKey from '../../hooks/useDebugKey';
|
import useDebugKey from '../../hooks/useDebugKey';
|
||||||
import usePrevious from '../../hooks/usePrevious';
|
|
||||||
import { useFocusHistory } from '../../hooks/useFocusHistory/useFocusHistory';
|
import { useFocusHistory } from '../../hooks/useFocusHistory/useFocusHistory';
|
||||||
|
import usePrevious from '../../hooks/usePrevious';
|
||||||
import { useVideoPlay } from '../../hooks/useVideoPlay/useVideoPlay';
|
import { useVideoPlay } from '../../hooks/useVideoPlay/useVideoPlay';
|
||||||
import { useVideoMove } from '../../hooks/useVideoTransition/useVideoMove';
|
import { useVideoMove } from '../../hooks/useVideoTransition/useVideoMove';
|
||||||
import {
|
import {
|
||||||
@@ -55,7 +76,7 @@ import css from '../HomePanel/HomePanel.module.less';
|
|||||||
import PopularShow from '../HomePanel/PopularShow/PopularShow';
|
import PopularShow from '../HomePanel/PopularShow/PopularShow';
|
||||||
import SubCategory from '../HomePanel/SubCategory/SubCategory';
|
import SubCategory from '../HomePanel/SubCategory/SubCategory';
|
||||||
import EventPopUpBanner from './EventPopUpBanner/EventPopUpBanner';
|
import EventPopUpBanner from './EventPopUpBanner/EventPopUpBanner';
|
||||||
import { applyMiddleware } from 'redux';
|
import PickedForYou from './PickedForYou/PickedForYou';
|
||||||
|
|
||||||
export const TEMPLATE_CODE_CONF = {
|
export const TEMPLATE_CODE_CONF = {
|
||||||
TOP: 'DSP00101',
|
TOP: 'DSP00101',
|
||||||
@@ -63,6 +84,7 @@ export const TEMPLATE_CODE_CONF = {
|
|||||||
ON_SALE: 'DSP00103',
|
ON_SALE: 'DSP00103',
|
||||||
POPULAR_SHOW: 'DSP00104',
|
POPULAR_SHOW: 'DSP00104',
|
||||||
BEST_SELLER: 'DSP00105',
|
BEST_SELLER: 'DSP00105',
|
||||||
|
PICK_FOR_YOU: 'DSP00106',
|
||||||
};
|
};
|
||||||
|
|
||||||
const HomePanel = ({ isOnTop }) => {
|
const HomePanel = ({ isOnTop }) => {
|
||||||
@@ -251,6 +273,9 @@ const HomePanel = ({ isOnTop }) => {
|
|||||||
case TEMPLATE_CODE_CONF.BEST_SELLER:
|
case TEMPLATE_CODE_CONF.BEST_SELLER:
|
||||||
nowMenu = LOG_MENU.HOME_BEST_SELLER;
|
nowMenu = LOG_MENU.HOME_BEST_SELLER;
|
||||||
break;
|
break;
|
||||||
|
case TEMPLATE_CODE_CONF.PICK_FOR_YOU:
|
||||||
|
nowMenu = LOG_MENU.HOME_PICKED_FOR_YOU;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
nowMenu = LOG_MENU.HOME_TOP;
|
nowMenu = LOG_MENU.HOME_TOP;
|
||||||
break;
|
break;
|
||||||
@@ -384,6 +409,24 @@ const HomePanel = ({ isOnTop }) => {
|
|||||||
);
|
);
|
||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
|
case TEMPLATE_CODE_CONF.PICK_FOR_YOU: {
|
||||||
|
if (bestSellerDatas && bestSellerDatas.length > 0) {
|
||||||
|
return (
|
||||||
|
<PickedForYou
|
||||||
|
key={el.shptmApphmDspyOptCd}
|
||||||
|
spotlightId={el.shptmApphmDspyOptCd}
|
||||||
|
handleShelfFocus={handleItemFocus(
|
||||||
|
el.shptmApphmDspyOptCd,
|
||||||
|
el.expsOrd,
|
||||||
|
el.shptmApphmDspyOptNm
|
||||||
|
)}
|
||||||
|
handleItemFocus={handleItemFocus(el.shptmApphmDspyOptCd)}
|
||||||
|
shelfLocation={el.expsOrd}
|
||||||
|
shelfTitle={el.shptmApphmDspyOptNm}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
{loadingComplete && sortedHomeLayoutInfo && sortedHomeLayoutInfo.length > 0 && (
|
{loadingComplete && sortedHomeLayoutInfo && sortedHomeLayoutInfo.length > 0 && (
|
||||||
@@ -593,6 +636,7 @@ const HomePanel = ({ isOnTop }) => {
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
tabType: 'CAT00102',
|
tabType: 'CAT00102',
|
||||||
filterType: 'CAT00202',
|
filterType: 'CAT00202',
|
||||||
|
recommendIncFlag: 'Y',
|
||||||
},
|
},
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,12 +16,9 @@ import {
|
|||||||
} from '@enact/spotlight/SpotlightContainerDecorator';
|
} from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
|
|
||||||
import {
|
import { pushPanel } from '../../../actions/panelActions';
|
||||||
pushPanel,
|
|
||||||
updatePanel,
|
|
||||||
} from '../../../actions/panelActions';
|
|
||||||
import SectionTitle from '../../../components/SectionTitle/SectionTitle';
|
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 TScroller from '../../../components/TScroller/TScroller';
|
||||||
import useScrollReset from '../../../hooks/useScrollReset';
|
import useScrollReset from '../../../hooks/useScrollReset';
|
||||||
import useScrollTo from '../../../hooks/useScrollTo';
|
import useScrollTo from '../../../hooks/useScrollTo';
|
||||||
@@ -30,10 +27,7 @@ import {
|
|||||||
LOG_MESSAGE_ID,
|
LOG_MESSAGE_ID,
|
||||||
panel_names,
|
panel_names,
|
||||||
} from '../../../utils/Config';
|
} from '../../../utils/Config';
|
||||||
import {
|
import { $L } from '../../../utils/helperMethods';
|
||||||
$L,
|
|
||||||
scaleW,
|
|
||||||
} from '../../../utils/helperMethods';
|
|
||||||
import { SpotlightIds } from '../../../utils/SpotlightIds';
|
import { SpotlightIds } from '../../../utils/SpotlightIds';
|
||||||
import css from './PickedForYou.module.less';
|
import css from './PickedForYou.module.less';
|
||||||
|
|
||||||
@@ -52,7 +46,7 @@ const PickedForYou = ({
|
|||||||
shelfLocation,
|
shelfLocation,
|
||||||
shelfTitle,
|
shelfTitle,
|
||||||
}) => {
|
}) => {
|
||||||
console.log("###Test pjh 여기지 ?");
|
|
||||||
const { getScrollTo, scrollLeft } = useScrollTo();
|
const { getScrollTo, scrollLeft } = useScrollTo();
|
||||||
const { handleScrollReset, handleStopScrolling } = useScrollReset(
|
const { handleScrollReset, handleStopScrolling } = useScrollReset(
|
||||||
scrollLeft,
|
scrollLeft,
|
||||||
@@ -63,18 +57,28 @@ const PickedForYou = ({
|
|||||||
|
|
||||||
const { cursorVisible } = useSelector((state) => state.common.appStatus);
|
const { cursorVisible } = useSelector((state) => state.common.appStatus);
|
||||||
|
|
||||||
const justForYouDatas = useSelector(
|
const justForYouDatasNew = useSelector(
|
||||||
(state) => state.product.bestSellerData?.bestSeller
|
(state) => state.foryou?.recommendInfo?.recommendProduct
|
||||||
);
|
)
|
||||||
|
|
||||||
const [drawChk, setDrawChk] = useState(false);
|
const [drawChk, setDrawChk] = useState(false);
|
||||||
const [firstChk, setFirstChk] = useState(0);
|
const [firstChk, setFirstChk] = useState(0);
|
||||||
|
|
||||||
|
const [pickedForYou, setPickedForYou] = useState(null);
|
||||||
|
|
||||||
const orderStyle = useMemo(() => ({ order: order }), [order]);
|
const orderStyle = useMemo(() => ({ order: order }), [order]);
|
||||||
|
useEffect(()=>{
|
||||||
|
setPickedForYou(
|
||||||
|
justForYouDatasNew?.filter(
|
||||||
|
(item) => item.recommendTpCd === "PICKEDFORYOU"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},[justForYouDatasNew])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDrawChk(true);
|
setDrawChk(true);
|
||||||
}, [justForYouDatas]);
|
}, [justForYouDatasNew]);
|
||||||
|
|
||||||
const handleCardClick = useCallback(
|
const handleCardClick = useCallback(
|
||||||
(patnrId, prdtId) => () => {
|
(patnrId, prdtId) => () => {
|
||||||
@@ -193,25 +197,26 @@ const PickedForYou = ({
|
|||||||
cbScrollTo={getScrollTo}
|
cbScrollTo={getScrollTo}
|
||||||
noScrollByWheel
|
noScrollByWheel
|
||||||
>
|
>
|
||||||
{justForYouDatas &&
|
{pickedForYou &&
|
||||||
justForYouDatas.map(
|
pickedForYou?.[0] &&
|
||||||
|
pickedForYou?.[0].productInfos.map(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
prdtId,
|
prdtId,
|
||||||
imgUrl,
|
imgUrl,
|
||||||
priceInfo,
|
priceInfo,
|
||||||
prdtNm,
|
prdtNm,
|
||||||
rankOrd,
|
|
||||||
patnrId,
|
patnrId,
|
||||||
offerInfo,
|
offerInfo,
|
||||||
brndNm,
|
brndNm,
|
||||||
patncNm,
|
patncNm,
|
||||||
catNm,
|
catNm,
|
||||||
|
euEnrgLblInfos
|
||||||
},
|
},
|
||||||
itemIndex
|
itemIndex
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<TItemCard
|
<TItemCardNew
|
||||||
key={"subItem" + itemIndex}
|
key={"subItem" + itemIndex}
|
||||||
contextName={LOG_CONTEXT_NAME.HOME}
|
contextName={LOG_CONTEXT_NAME.HOME}
|
||||||
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
|
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
|
||||||
@@ -225,16 +230,16 @@ const PickedForYou = ({
|
|||||||
imageAlt={prdtId}
|
imageAlt={prdtId}
|
||||||
imageSource={imgUrl}
|
imageSource={imgUrl}
|
||||||
priceInfo={priceInfo}
|
priceInfo={priceInfo}
|
||||||
productName={prdtNm}
|
productName={prdtNm}
|
||||||
isBestSeller={true}
|
|
||||||
productId={prdtId}
|
productId={prdtId}
|
||||||
onFocus={handleFocus(itemIndex)}
|
onFocus={handleFocus(itemIndex)}
|
||||||
onBlur={handleBlur(itemIndex)}
|
onBlur={handleBlur(itemIndex)}
|
||||||
onClick={handleCardClick(patnrId, prdtId)}
|
onClick={handleCardClick(patnrId, prdtId)}
|
||||||
offerInfo={offerInfo}
|
offerInfo={offerInfo}
|
||||||
spotlightId={"bestsellerItem" + itemIndex}
|
spotlightId={"bestsellerItem" + itemIndex}
|
||||||
label={itemIndex * 1 + 1 + " of " + justForYouDatas.length}
|
label={itemIndex * 1 + 1 + " of " + pickedForYou?.[0].productInfos.length}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
|
euEnrgLblInfos={euEnrgLblInfos}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,17 +71,57 @@ const PopularShow = ({
|
|||||||
const { cursorVisible } = useSelector((state) => state.common.appStatus);
|
const { cursorVisible } = useSelector((state) => state.common.appStatus);
|
||||||
|
|
||||||
const topInfos = useSelector((state) => state.main.top20ShowData.topInfos);
|
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 orderStyle = useMemo(() => ({ order: order }), [order]);
|
||||||
|
const [drawChk, setDrawChk] = useState(false);
|
||||||
const [firstChk, setFirstChk] = useState(0);
|
const [firstChk, setFirstChk] = useState(0);
|
||||||
|
|
||||||
|
const [showInfos, setShowInfos] = useState(null);
|
||||||
|
const [showNewInfos, setShowNewInfos] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDrawChk(true);
|
setDrawChk(true);
|
||||||
}, [topInfos]);
|
}, [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(
|
const handleCardClick = useCallback(
|
||||||
(patnrId, showId, catCd, showUrl) => () => {
|
(patnrId, showId, catCd, showUrl) => () => {
|
||||||
dispatch(
|
dispatch(
|
||||||
@@ -187,23 +227,7 @@ const PopularShow = ({
|
|||||||
if (handleShelfFocus) {
|
if (handleShelfFocus) {
|
||||||
handleShelfFocus();
|
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]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
@@ -225,8 +249,8 @@ const PopularShow = ({
|
|||||||
cbScrollTo={getScrollTo}
|
cbScrollTo={getScrollTo}
|
||||||
noScrollByWheel
|
noScrollByWheel
|
||||||
>
|
>
|
||||||
{topInfosNewData &&
|
{showNewInfos &&
|
||||||
topInfosNewData.map(
|
showNewInfos.map(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
showId,
|
showId,
|
||||||
@@ -240,7 +264,7 @@ const PopularShow = ({
|
|||||||
patncNm,
|
patncNm,
|
||||||
catCd,
|
catCd,
|
||||||
showUrl,
|
showUrl,
|
||||||
//foryou,
|
foryou,
|
||||||
},
|
},
|
||||||
itemIndex
|
itemIndex
|
||||||
) => {
|
) => {
|
||||||
@@ -258,9 +282,11 @@ const PopularShow = ({
|
|||||||
contentId={showId}
|
contentId={showId}
|
||||||
contentTitle={showNm}
|
contentTitle={showNm}
|
||||||
imageSource={
|
imageSource={
|
||||||
|
(thumbnailUrl && thumbnailUrl960) ?
|
||||||
thumbnailUrl !== thumbnailUrl960
|
thumbnailUrl !== thumbnailUrl960
|
||||||
? thumbnailUrl960
|
? thumbnailUrl960
|
||||||
: thumbnailUrl
|
: thumbnailUrl
|
||||||
|
: thumbnailUrl
|
||||||
}
|
}
|
||||||
imageAlt={showNm}
|
imageAlt={showNm}
|
||||||
productName={showNm}
|
productName={showNm}
|
||||||
@@ -277,10 +303,10 @@ const PopularShow = ({
|
|||||||
onBlur={handleBlur(itemIndex)}
|
onBlur={handleBlur(itemIndex)}
|
||||||
onClick={handleCardClick(patnrId, showId, catCd, showUrl)}
|
onClick={handleCardClick(patnrId, showId, catCd, showUrl)}
|
||||||
firstLabel={patncNm + " "}
|
firstLabel={patncNm + " "}
|
||||||
label={itemIndex * 1 + 1 + " of " + topInfos.length}
|
label={itemIndex * 1 + 1 + " of " + showNewInfos.length}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
>
|
>
|
||||||
{/* {foryou === true && <Tag text={"For You"} />} */}
|
{foryou === true && <Tag text={"For You"} />}
|
||||||
</TItemCardNew>
|
</TItemCardNew>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
import { setContainerLastFocusedElement } from '@enact/spotlight/src/container';
|
import { setContainerLastFocusedElement } from '@enact/spotlight/src/container';
|
||||||
|
|
||||||
import { getRecentlySawItem } from '../../../actions/forYouActions';
|
|
||||||
import { sendLogCuration } from '../../../actions/logActions';
|
import { sendLogCuration } from '../../../actions/logActions';
|
||||||
import { getSubCategory } from '../../../actions/mainActions';
|
import { getSubCategory } from '../../../actions/mainActions';
|
||||||
import { pushPanel } from '../../../actions/panelActions';
|
import { pushPanel } from '../../../actions/panelActions';
|
||||||
@@ -71,6 +70,10 @@ export default memo(function SubCategory({
|
|||||||
(state) => state.main.subCategoryData?.categoryItemInfos
|
(state) => state.main.subCategoryData?.categoryItemInfos
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const foruItemInfos = useSelector(
|
||||||
|
(state) => state.main.recommendProduct[0]?.productInfos
|
||||||
|
);
|
||||||
|
|
||||||
const nowMenu = useSelector((state) => state.common.menu.nowMenu);
|
const nowMenu = useSelector((state) => state.common.menu.nowMenu);
|
||||||
|
|
||||||
const [currentLgCatCd, setCurrentLgCatCd] = useState(catCd ? catCd : null);
|
const [currentLgCatCd, setCurrentLgCatCd] = useState(catCd ? catCd : null);
|
||||||
@@ -110,6 +113,7 @@ export default memo(function SubCategory({
|
|||||||
pageSize: "10",
|
pageSize: "10",
|
||||||
tabType: "CAT00102",
|
tabType: "CAT00102",
|
||||||
filterType: "CAT00202",
|
filterType: "CAT00202",
|
||||||
|
recommendIncFlag: 'Y',
|
||||||
},
|
},
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
@@ -117,7 +121,7 @@ export default memo(function SubCategory({
|
|||||||
}
|
}
|
||||||
setDrawChk(true);
|
setDrawChk(true);
|
||||||
}
|
}
|
||||||
}, [currentLgCatCd, dispatch]);
|
}, [currentLgCatCd, dispatch, firstChk]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!nowMenuRef.current || !nowMenuRef.current.startsWith("Home")) {
|
if (!nowMenuRef.current || !nowMenuRef.current.startsWith("Home")) {
|
||||||
@@ -134,7 +138,7 @@ export default memo(function SubCategory({
|
|||||||
|
|
||||||
dispatch(sendLogCuration(params));
|
dispatch(sendLogCuration(params));
|
||||||
}
|
}
|
||||||
}, [categoryInfos, currentLgCatCd, currentLgCatNm]);
|
}, [categoryInfos, currentLgCatCd, currentLgCatNm, dispatch, nowMenuRef]);
|
||||||
|
|
||||||
const handleCategoryNav = useCallback(
|
const handleCategoryNav = useCallback(
|
||||||
(lgCatCd, lgCatNm) => {
|
(lgCatCd, lgCatNm) => {
|
||||||
@@ -149,7 +153,7 @@ export default memo(function SubCategory({
|
|||||||
|
|
||||||
setContainerLastFocusedElement(null, [SpotlightIds.HOME_CATEGORY_NAV]);
|
setContainerLastFocusedElement(null, [SpotlightIds.HOME_CATEGORY_NAV]);
|
||||||
},
|
},
|
||||||
[currentLgCatCd]
|
[currentLgCatCd, handleScrollReset]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFocus = useCallback(
|
const handleFocus = useCallback(
|
||||||
@@ -160,7 +164,7 @@ export default memo(function SubCategory({
|
|||||||
handleScrollReset();
|
handleScrollReset();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[_handleItemFocus]
|
[_handleItemFocus, handleScrollReset]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleBlur = useCallback(
|
const handleBlur = useCallback(
|
||||||
@@ -169,7 +173,7 @@ export default memo(function SubCategory({
|
|||||||
handleStopScrolling();
|
handleStopScrolling();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[]
|
[handleStopScrolling]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCardClick = useCallback(
|
const handleCardClick = useCallback(
|
||||||
@@ -181,7 +185,7 @@ export default memo(function SubCategory({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[]
|
[dispatch, spotlightId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleScrollRight = useCallback((e) => {
|
const handleScrollRight = useCallback((e) => {
|
||||||
@@ -189,7 +193,7 @@ export default memo(function SubCategory({
|
|||||||
const x = container.scrollWidth - container.clientWidth;
|
const x = container.scrollWidth - container.clientWidth;
|
||||||
|
|
||||||
setTimeout(() => scrollLeft({ x, animate: true }));
|
setTimeout(() => scrollLeft({ x, animate: true }));
|
||||||
}, []);
|
}, [scrollLeft]);
|
||||||
|
|
||||||
const handleMoreCardClick = useCallback((e) => {
|
const handleMoreCardClick = useCallback((e) => {
|
||||||
const lgCatCd = e.currentTarget?.getAttribute("data-catcd-num");
|
const lgCatCd = e.currentTarget?.getAttribute("data-catcd-num");
|
||||||
@@ -208,7 +212,7 @@ export default memo(function SubCategory({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [dispatch]);
|
||||||
|
|
||||||
const _handleItemFocus = useCallback(() => {
|
const _handleItemFocus = useCallback(() => {
|
||||||
if (handleItemFocus) {
|
if (handleItemFocus) {
|
||||||
@@ -222,27 +226,30 @@ export default memo(function SubCategory({
|
|||||||
}
|
}
|
||||||
}, [handleShelfFocus]);
|
}, [handleShelfFocus]);
|
||||||
|
|
||||||
const _randomProduct = useCallback(() => {
|
|
||||||
const randomChk = Math.round(Math.random()) === 0 ? false : true;
|
|
||||||
return randomChk;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCategoryItemNewData(
|
if (!foruItemInfos || foruItemInfos.length === 0) {
|
||||||
categoryItemInfos?.subCatItemList?.map((item) => ({
|
const baseData = categoryItemInfos?.subCatItemList?.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
foryou: _randomProduct(),
|
foryou: false,
|
||||||
}))
|
})) || [];
|
||||||
);
|
setCategoryItemNewData(baseData);
|
||||||
}, [categoryItemInfos?.subCatItemList]);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
const recommendedData = foruItemInfos?.map((item) => ({
|
||||||
dispatch(
|
...item,
|
||||||
getRecentlySawItem(
|
foryou: true,
|
||||||
categoryItemNewData.filter((item) => item.foryou === true)
|
})) || [];
|
||||||
)
|
|
||||||
);
|
const recommendedPrdtIds = new Set(recommendedData.map(item => item.prdtId));
|
||||||
}, [categoryItemNewData, dispatch]);
|
|
||||||
|
const baseData = categoryItemInfos?.subCatItemList?.map((item) => ({
|
||||||
|
...item,
|
||||||
|
foryou: recommendedPrdtIds.has(item.prdtId),
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
setCategoryItemNewData([...baseData]);
|
||||||
|
}, [categoryItemInfos?.subCatItemList, foruItemInfos]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
@@ -267,59 +274,6 @@ export default memo(function SubCategory({
|
|||||||
cbScrollTo={getScrollTo}
|
cbScrollTo={getScrollTo}
|
||||||
noScrollByWheel
|
noScrollByWheel
|
||||||
>
|
>
|
||||||
{/* {categoryItemInfos &&
|
|
||||||
categoryItemInfos?.subCatItemList.map(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
prdtId,
|
|
||||||
imgUrl,
|
|
||||||
priceInfo,
|
|
||||||
prdtNm,
|
|
||||||
patnrId,
|
|
||||||
offerInfo,
|
|
||||||
brndNm,
|
|
||||||
patncNm,
|
|
||||||
},
|
|
||||||
itemIndex
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<TItemCardNew
|
|
||||||
key={"subItem" + itemIndex}
|
|
||||||
contextName={LOG_CONTEXT_NAME.HOME}
|
|
||||||
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
|
|
||||||
catNm={categoryItemInfos.catNm}
|
|
||||||
order={itemIndex + 1}
|
|
||||||
shelfId={spotlightId}
|
|
||||||
shelfLocation={shelfLocation}
|
|
||||||
shelfTitle={shelfTitle}
|
|
||||||
brandName={brndNm}
|
|
||||||
patnerName={patncNm}
|
|
||||||
imageAlt={prdtId}
|
|
||||||
imageSource={imgUrl}
|
|
||||||
priceInfo={priceInfo}
|
|
||||||
productName={prdtNm}
|
|
||||||
productId={prdtId}
|
|
||||||
onFocus={handleFocus(itemIndex)}
|
|
||||||
onBlur={handleBlur(itemIndex)}
|
|
||||||
onClick={handleCardClick(patnrId, prdtId)}
|
|
||||||
offerInfo={offerInfo}
|
|
||||||
data-catcd-num={currentLgCatCd}
|
|
||||||
data-catcd-nm={currentLgCatNm}
|
|
||||||
label={
|
|
||||||
itemIndex * 1 +
|
|
||||||
1 +
|
|
||||||
" of " +
|
|
||||||
categoryItemInfos?.subCatItemList.length
|
|
||||||
}
|
|
||||||
lastLabel=" go to detail, button"
|
|
||||||
>
|
|
||||||
|
|
||||||
<Tag text={"For You"} />
|
|
||||||
|
|
||||||
</TItemCardNew>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)} 원본 보관*/}
|
|
||||||
{categoryItemNewData &&
|
{categoryItemNewData &&
|
||||||
categoryItemNewData.map(
|
categoryItemNewData.map(
|
||||||
(
|
(
|
||||||
@@ -332,7 +286,8 @@ export default memo(function SubCategory({
|
|||||||
offerInfo,
|
offerInfo,
|
||||||
brndNm,
|
brndNm,
|
||||||
patncNm,
|
patncNm,
|
||||||
//foryou,
|
foryou,
|
||||||
|
euEnrgLblInfos,
|
||||||
},
|
},
|
||||||
itemIndex
|
itemIndex
|
||||||
) => {
|
) => {
|
||||||
@@ -341,7 +296,7 @@ export default memo(function SubCategory({
|
|||||||
key={"subItem" + itemIndex}
|
key={"subItem" + itemIndex}
|
||||||
contextName={LOG_CONTEXT_NAME.HOME}
|
contextName={LOG_CONTEXT_NAME.HOME}
|
||||||
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
|
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
|
||||||
catNm={categoryItemInfos.catNm}
|
catNm={categoryItemInfos?.catNm}
|
||||||
order={itemIndex + 1}
|
order={itemIndex + 1}
|
||||||
shelfId={spotlightId}
|
shelfId={spotlightId}
|
||||||
shelfLocation={shelfLocation}
|
shelfLocation={shelfLocation}
|
||||||
@@ -363,11 +318,12 @@ export default memo(function SubCategory({
|
|||||||
itemIndex * 1 +
|
itemIndex * 1 +
|
||||||
1 +
|
1 +
|
||||||
" of " +
|
" of " +
|
||||||
categoryItemInfos?.subCatItemList.length
|
(categoryItemNewData?.length || 0)
|
||||||
}
|
}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
|
euEnrgLblInfos={euEnrgLblInfos}
|
||||||
>
|
>
|
||||||
{/* {foryou === true && <Tag text={"For You"} />} */}
|
{foryou === true && <Tag text={"For You"} />}
|
||||||
</TItemCardNew>
|
</TItemCardNew>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -389,4 +345,4 @@ export default memo(function SubCategory({
|
|||||||
</ContainerBasic>
|
</ContainerBasic>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -47,11 +47,11 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
|||||||
|
|
||||||
const cbChangePageRef = useRef(null);
|
const cbChangePageRef = useRef(null);
|
||||||
const shelfInfos = useSelector(
|
const shelfInfos = useSelector(
|
||||||
(state) => state.foryou?.justForYouInfo?.shelfInfos
|
(state) => state.foryou?.recommendInfo?.recommendProduct
|
||||||
);
|
);
|
||||||
|
|
||||||
const justForYouInfo = useSelector(
|
const justForYouInfo = useSelector(
|
||||||
(state) => state.foryou?.justForYouInfo?.justForYouInfo
|
(state) => state.foryou?.recommendInfo?.justForYouInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
const onClick = useCallback(() => {
|
const onClick = useCallback(() => {
|
||||||
@@ -80,25 +80,19 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const product = productInfos[index];
|
const product = productInfos[index];
|
||||||
const {
|
const {
|
||||||
contentId,
|
prdtNm,
|
||||||
title,
|
imgUrl,
|
||||||
thumbnail,
|
priceInfo,
|
||||||
price,
|
patncNm,
|
||||||
dcPrice,
|
patnrId,
|
||||||
partnerName,
|
prdtId,
|
||||||
partnerLogo,
|
|
||||||
} = product;
|
} = product;
|
||||||
|
|
||||||
const handleItemClick = () => {
|
const handleItemClick = () => {
|
||||||
// Extract product ID from contentId if needed
|
|
||||||
const tokens = contentId.split("_");
|
|
||||||
const patnrId = tokens?.[4] || "";
|
|
||||||
const prdtId = tokens?.[5] || "";
|
|
||||||
dispatch(
|
dispatch(
|
||||||
pushPanel({
|
pushPanel({
|
||||||
name: panel_names.DETAIL_PANEL,
|
name: panel_names.DETAIL_PANEL,
|
||||||
// panelInfo: { prdtId: contentId },
|
|
||||||
panelInfo: {
|
panelInfo: {
|
||||||
patnrId: patnrId,
|
patnrId: patnrId,
|
||||||
prdtId: prdtId,
|
prdtId: prdtId,
|
||||||
@@ -109,16 +103,14 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TItemCardNew
|
<TItemCardNew
|
||||||
key={contentId}
|
key={prdtId}
|
||||||
patnerName={partnerName}
|
patnerName={patncNm}
|
||||||
imageAlt={title}
|
imageAlt={prdtNm}
|
||||||
imageSource={thumbnail}
|
imageSource={imgUrl}
|
||||||
label={`${index + 1} of ${productInfos.length}`}
|
label={`${index + 1} of ${productInfos.length}`}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
dcPrice={dcPrice}
|
priceInfo={priceInfo}
|
||||||
originPrice={price}
|
productName={prdtNm}
|
||||||
productName={title}
|
|
||||||
productId={contentId}
|
|
||||||
onClick={handleItemClick}
|
onClick={handleItemClick}
|
||||||
spotlightId={`spotlightId-${shelfId}-${shelfExpsOrd}-${index}`}
|
spotlightId={`spotlightId-${shelfId}-${shelfExpsOrd}-${index}`}
|
||||||
{...rest}
|
{...rest}
|
||||||
@@ -169,7 +161,7 @@ const JustForYouTestPanel = ({ panelInfo, ...rest }) => {
|
|||||||
key={shelf.shelfId}
|
key={shelf.shelfId}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
css.itemsContainer,
|
css.itemsContainer,
|
||||||
shelfIndex === 0 && css.itemsContinerFirst
|
shelfIndex === 1 && css.itemsContinerFirst
|
||||||
)}
|
)}
|
||||||
spotlightId={`justForYouList_${shelf.shelfExpsOrd}`}
|
spotlightId={`justForYouList_${shelf.shelfExpsOrd}`}
|
||||||
data-wheel-point
|
data-wheel-point
|
||||||
|
|||||||
@@ -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 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 Spotlight from '@enact/spotlight';
|
||||||
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
import SpotlightContainerDecorator
|
||||||
|
from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
|
|
||||||
import downBtnImg from '../../../assets/images/btn/search_btn_down_arrow.png';
|
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 CustomImage from '../../components/CustomImage/CustomImage';
|
||||||
import TButtonTab, { LIST_TYPE } from '../../components/TButtonTab/TButtonTab';
|
import TButtonTab, { LIST_TYPE } from '../../components/TButtonTab/TButtonTab';
|
||||||
import TDropDown from '../../components/TDropDown/TDropDown';
|
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 { panel_names } from '../../utils/Config';
|
||||||
import { $L } from '../../utils/helperMethods';
|
import { $L } from '../../utils/helperMethods';
|
||||||
import { SpotlightIds } from '../../utils/SpotlightIds';
|
import { SpotlightIds } from '../../utils/SpotlightIds';
|
||||||
@@ -24,8 +36,6 @@ import HowAboutTheseSmall from './HowAboutThese/HowAboutThese.small';
|
|||||||
import css from './SearchResults.new.v2.module.less';
|
import css from './SearchResults.new.v2.module.less';
|
||||||
import ItemCard from './SearchResultsNew/ItemCard';
|
import ItemCard from './SearchResultsNew/ItemCard';
|
||||||
import ShowCard from './SearchResultsNew/ShowCard';
|
import ShowCard from './SearchResultsNew/ShowCard';
|
||||||
import Dropdown from '@enact/sandstone/Dropdown';
|
|
||||||
|
|
||||||
|
|
||||||
const ITEMS_PER_PAGE = 10;
|
const ITEMS_PER_PAGE = 10;
|
||||||
|
|
||||||
@@ -926,7 +936,7 @@ const SearchResultsNew = ({
|
|||||||
No matches, Showing suggestions
|
No matches, Showing suggestions
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{hasShopperHouseItems && (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
className={classNames(
|
className={classNames(
|
||||||
css.dropdown,
|
css.dropdown,
|
||||||
@@ -938,7 +948,7 @@ const SearchResultsNew = ({
|
|||||||
>
|
>
|
||||||
{filterMethods}
|
{filterMethods}
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
)}
|
||||||
</TabContainer>
|
</TabContainer>
|
||||||
|
|
||||||
{/* 아이템/쇼 컨텐츠 */}
|
{/* 아이템/쇼 컨텐츠 */}
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import { useDispatch } from 'react-redux';
|
|||||||
|
|
||||||
import Spotlight from '@enact/spotlight';
|
import Spotlight from '@enact/spotlight';
|
||||||
|
|
||||||
import { pushPanel, updatePanel } from '../../../actions/panelActions';
|
import {
|
||||||
|
pushPanel,
|
||||||
|
updatePanel,
|
||||||
|
} from '../../../actions/panelActions';
|
||||||
import { navigateToDetailPanel } from '../../../actions/panelNavigationActions';
|
import { navigateToDetailPanel } from '../../../actions/panelNavigationActions';
|
||||||
import TItemCardNew from '../../../components/TItemCard/TItemCard.new';
|
import TItemCardNew from '../../../components/TItemCard/TItemCard.new';
|
||||||
import TScroller from '../../../components/TScroller/TScroller';
|
import TScroller from '../../../components/TScroller/TScroller';
|
||||||
@@ -62,7 +65,7 @@ const ItemCard = ({ onClick, itemInfo, searchQuery }) => {
|
|||||||
<>
|
<>
|
||||||
<TScroller className={css.container} spotlightId={SpotlightIds.SEARCH_ITEM}>
|
<TScroller className={css.container} spotlightId={SpotlightIds.SEARCH_ITEM}>
|
||||||
{itemInfo.map((item, index) => {
|
{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 tokens = contentId && contentId.split('_');
|
||||||
const patnrId = tokens?.[4] || '';
|
const patnrId = tokens?.[4] || '';
|
||||||
const prdtId = tokens?.[5] || '';
|
const prdtId = tokens?.[5] || '';
|
||||||
@@ -83,6 +86,7 @@ const ItemCard = ({ onClick, itemInfo, searchQuery }) => {
|
|||||||
{...(index === 0 ? { 'data-spotlight-up': 'searchtabContainer' } : {})}
|
{...(index === 0 ? { 'data-spotlight-up': 'searchtabContainer' } : {})}
|
||||||
label={index * 1 + 1 + ' of ' + itemInfo.length + 1}
|
label={index * 1 + 1 + ' of ' + itemInfo.length + 1}
|
||||||
lastLabel=" go to detail, button"
|
lastLabel=" go to detail, button"
|
||||||
|
euEnrgLblInfos={euEnrgLblInfos}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in New Issue
Block a user