Files
shoptime/com.twin.app.shoptime/src/actions/mainActions.js
optrader b95628de24 [251124] fix: Log정리-4
🕐 커밋 시간: 2025. 11. 24. 12:19:40

📊 변경 통계:
  • 총 파일: 6개
  • 추가: +283줄
  • 삭제: -255줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/mainActions.js
  ~ com.twin.app.shoptime/src/reducers/mainReducer.js
  ~ com.twin.app.shoptime/src/reducers/searchReducer.js
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchPanel.new.v2.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/VoiceInputOverlay/VoiceInputOverlay.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/actions/mainActions.js (javascript):
    🔄 Modified: clearSubCategory()
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx (javascript):
    🔄 Modified: Spottable()
  📄 com.twin.app.shoptime/src/views/SearchPanel/VoiceInputOverlay/VoiceInputOverlay.jsx (javascript):
     Added: Spottable()
    🔄 Modified: clearAllTimers()

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
2025-11-24 12:19:40 +09:00

502 lines
13 KiB
JavaScript

import { URLS } from '../api/apiConfig';
import { TAxios, TAxiosAdvancedPromise } from '../api/TAxios';
import { convertUtcToLocal } from '../components/MediaPlayer/util';
import { CATEGORY_DATA_MAX_RESULTS_LIMIT, LOG_CONTEXT_NAME, LOG_MESSAGE_ID } from '../utils/Config';
import * as HelperMethods from '../utils/helperMethods';
import { types } from './actionTypes';
import { addReservation, changeAppStatus, deleteReservation } from './commonActions';
import { createDebugHelpers } from '../utils/debug';
// 디버그 헬퍼 설정
const DEBUG_MODE = false;
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
//IF-LGSP-007
export const getMainLiveShow = (props) => (dispatch, getState) => {
const vodIncFlag = props?.vodIncFlag;
const onSuccess = (response) => {
dlog('@@ getMainLiveShow onSuccess', response.data);
dispatch({
type: types.GET_MAIN_LIVE_SHOW,
payload: response.data.data,
});
};
const onFail = (error) => {
derror('@@ getMainLiveShow onFail', error);
};
TAxios(dispatch, getState, 'get', URLS.GET_MAIN_LIVE_SHOW, { vodIncFlag }, {}, onSuccess, onFail);
};
// Live 알람 설정/해제 IF-LGSP-012
export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
const { alamDispFlag, chanId, endDt, patnrId, patncNm, showId, showNm, strtDt } = props;
const onSuccess = (response) => {
dlog('setMainLiveUpcomingAlarm onSuccess', response.data);
if (alamDispFlag === 'Y') {
const convertedStrtDt = convertUtcToLocal(strtDt);
const data = {
startTime: {
year: convertedStrtDt.getFullYear(),
month: convertedStrtDt.getMonth() + 1,
day: convertedStrtDt.getDate(),
hour: convertedStrtDt.getHours(),
minute: convertedStrtDt.getMinutes(),
second: convertedStrtDt.getSeconds(),
},
params: {
message: `[${patncNm}] ${showNm}\n${HelperMethods.$L('Watch Now!')}`,
buttons: [
{
label: HelperMethods.$L('yes'),
},
{
label: HelperMethods.$L('no'),
},
],
launch: {
contentTarget: `V3_8002_Tv_FB_${patnrId}`,
},
showId: showId,
chanId: chanId,
},
};
dispatch(addReservation(data));
}
//
else if (alamDispFlag === 'N') {
dispatch(deleteReservation(showId));
}
};
const onFail = (error) => {
derror('setMainLiveUpcomingAlarm onFail', error);
};
TAxios(
dispatch,
getState,
'post',
URLS.SET_MAIN_LIVE_UPCOMING_ALARM,
{},
{ alamDispFlag, endDt, patnrId, showId, strtDt },
onSuccess,
onFail
);
};
// 디테일상품 조회 LF-LGSP-015
export const getMainCategoryDetail = (props) => (dispatch, getState) => {
const { patnrId, prdtId, liveReqFlag } = props;
dispatch(changeAppStatus({ showLoadingPanel: { show: true, type: 'wait' } }));
const onSuccess = (response) => {
dlog('getMainCategoryDetail onSuccess ', response.data);
dispatch({
type: types.GET_PRODUCT_DETAIL,
payload: response.data.data,
});
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};
const onFail = (error) => {
derror('getMainCategoryDetail onFail', error);
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};
TAxios(
dispatch,
getState,
'get',
URLS.GET_PRODUCT_DETAIL,
{ patnrId, prdtId, liveReqFlag },
{},
onSuccess,
onFail
);
};
// 영상 상세 보기 조회 LF-LGSP-047
export const getMainCategoryShowDetail = (props) => (dispatch, getState) => {
const { patnrId, showId, curationId } = props;
const onSuccess = (response) => {
dlog('getMainCategoryShowDetail onSuccess ', response.data);
dispatch({
type: types.GET_MAIN_CATEGORY_SHOW_DETAIL,
payload: response.data.data,
});
};
const onFail = (error) => {
derror('getMainCategoryShowDetail onFail', error);
};
TAxios(
dispatch,
getState,
'get',
URLS.GET_MAIN_CATEGORY_SHOW_DETAIL,
{ patnrId, showId, curationId },
{},
onSuccess,
onFail
);
};
// 서브카테고리 조회 IF-LGSP-051
let getSubCategoryKey = null;
let lastSubCategoryParams = {};
const SUB_CATEGORY_RETRY_LIMIT = 3;
const SUB_CATEGORY_RETRY_DELAY_MS = 400;
export const getSubCategory =
(params, pageNo = 1, key = null, clear = false, retryCount = 0) =>
(dispatch, getState) => {
const { lgCatCd, patnrIdList, tabType, filterType, recommendIncFlag } = params;
let pageSize = params.pageSize || CATEGORY_DATA_MAX_RESULTS_LIMIT;
if (pageNo === 1) {
if (
lastSubCategoryParams &&
JSON.stringify(lastSubCategoryParams) === JSON.stringify(params)
) {
dlog('getSubCategory ignore patch');
return;
}
lastSubCategoryParams = { ...params };
if (clear) {
dispatch(clearSubCategory());
}
}
let currentKey = key;
const onSuccess = (response) => {
dlog('getSubCategory onSuccess ', response.data);
if (pageNo === 1) {
getSubCategoryKey = new Date();
currentKey = getSubCategoryKey;
// ✅ recommendProduct 분리
const { recommendProduct, ...restData } = response.data.data;
dispatch({
type: types.GET_SUB_CATEGORY,
payload: {
...restData,
recommendProduct,
},
categoryParams: {
lgCatCd,
patnrIdList,
tabType,
filterType,
recommendIncFlag,
pageSize,
},
});
} else if (getSubCategoryKey === currentKey) {
const { recommendProduct, ...restData } = response.data.data;
dispatch({
type: types.GET_SUB_CATEGORY,
payload: {
...restData,
recommendProduct,
},
append: true,
startIndex: (pageNo - 1) * pageSize,
});
}
};
const onFail = (error) => {
const nextRetryCount = retryCount + 1;
const canRetry = nextRetryCount < SUB_CATEGORY_RETRY_LIMIT;
if (canRetry) {
dwarn('getSubCategory retry', {
lgCatCd,
pageNo,
retryCount: nextRetryCount,
});
setTimeout(() => {
dispatch(getSubCategory(params, pageNo, currentKey, clear, nextRetryCount));
}, SUB_CATEGORY_RETRY_DELAY_MS * nextRetryCount);
return;
}
derror('getSubCategory onFail', error);
if (pageNo === 1) {
lastSubCategoryParams = {};
}
};
TAxios(
dispatch,
getState,
'get',
URLS.GET_SUB_CATEGORY,
{ lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType, recommendIncFlag },
{},
onSuccess,
onFail
);
};
export const continueGetSubCategory = (key, pageNo) => (dispatch, getState) => {
if (!lastSubCategoryParams) {
// <<<<<<< HEAD
dwarn('No previous category parameters found');
// =======
// console.warn("No previous category parameters found");
// >>>>>>> gitlab/develop
return;
}
const subCategoryData = getState().main.subCategoryData;
const targetData =
// <<<<<<< HEAD
subCategoryData[key]?.subCatItemList || subCategoryData[key]?.subCatShowList || [];
// =======
// subCategoryData[key]?.subCatItemList ||
// subCategoryData[key]?.subCatShowList ||
// [];
// >>>>>>> gitlab/develop
const totalCount = subCategoryData[key]?.total ?? 0;
const startIndex = CATEGORY_DATA_MAX_RESULTS_LIMIT * (pageNo - 1);
if (
(startIndex <= 1 && !targetData) ||
startIndex < targetData.length ||
totalCount - 1 <= startIndex
) {
//ignore query
return;
}
// <<<<<<< HEAD
dispatch(getSubCategory({ ...lastSubCategoryParams }, pageNo, getSubCategoryKey));
// =======
// dispatch(
// getSubCategory({ ...lastSubCategoryParams }, pageNo, getSubCategoryKey)
// );
// >>>>>>> gitlab/develop
};
const clearSubCategory = () => ({
type: types.CLEAR_SUB_CATEGORY,
});
// TOP20 영상 목록 조회 IF-LGSP-069
export const getTop20Show = () => (dispatch, getState) => {
const onSuccess = (response) => {
dlog('getTop20Show onSuccess ', response.data);
dispatch({
type: types.GET_TOP_20_SHOW,
payload: response.data.data,
});
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};
const onFail = (error) => {
derror('getTop20Show onFail', error);
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};
TAxios(dispatch, getState, 'get', URLS.GET_TOP20_SHOW, {}, {}, onSuccess, onFail);
};
// 유메이라이크 아이템 리스트 IF-LGSP-201
export const getMainYouMayLike =
({ lgCatCd, exclCurationId, exclPatnrId, exclPrdtId, catDpTh3, catDpTh4 }) =>
(dispatch, getState) => {
// console.log('[YouMayLike] API 요청 시작:', {
// lgCatCd,
// exclCurationId,
// exclPatnrId,
// exclPrdtId,
// catDpTh3,
// catDpTh4
// });
const onSuccess = (response) => {
// console.log('[YouMayLike] API 응답 성공 (onSuccess):', {
// fullResponse: response.data,
// dataField: response.data.data,
// hasYoumaylike: !!(response.data.data && response.data.data.youmaylike),
// youmaylikeLength: response.data.data?.youmaylike?.length || 0,
// youmaylikeData: response.data.data?.youmaylike
// });
// console.log('[YouMayLike] Redux dispatch 전 - payload:', response.data.data);
dispatch({
type: types.GET_YOUMAYLIKE,
payload: response.data.data,
});
// console.log('[YouMayLike] Redux dispatch 완료');
};
const onFail = (error) => {
// console.error('[YouMayLike] API 요청 실패 (onFail):', {
// error: error,
// errorMessage: error?.message,
// errorResponse: error?.response,
// errorData: error?.response?.data
// });
console.error('getMainYouMayLike onFail', error);
};
TAxios(
dispatch,
getState,
'get',
URLS.GET_YOUMAYLIKE,
// <<<<<<< HEAD
{ lgCatCd, exclCurationId, exclPatnrId, exclPrdtId, catDpTh3, catDpTh4 },
// =======
// { lgCatCd, catDpTh3, catDpTh4, exclCurationId, exclPatnrId, exclPrdtId },
// >>>>>>> gitlab/develop
{},
onSuccess,
onFail
);
};
// 찜 여부 확인 IF-LGSP-075
export const getMyFavoriteFlag = (params) => (dispatch, getState) => {
const { patnrId, prdtId } = params;
const onSuccess = (response) => {
dlog('getMyFavoriteFlag onSuccess ', response.data);
dispatch({
type: types.GET_MY_FAVORITE_FLAG,
payload: response.data.data,
});
};
const onFail = (error) => {
derror('getMyFavoriteFlag onFail', error);
};
TAxios(
dispatch,
getState,
'get',
URLS.GET_MY_FAVORITE_FLAG,
{ patnrId, prdtId },
{},
onSuccess,
onFail
);
};
// 상품 찜하기 IF-LGSP-014
export const setMainLikeCategory = (params) => (dispatch, getState) => {
const { patnrId, prdtId } = params;
const onSuccess = (response) => {
dlog('setMainLikeCategory onSuccess ', response.data);
dispatch({
type: types.SET_MAIN_LIKE_CATEGORY,
payload: response.data.data,
});
};
const onFail = (error) => {
console.error('setMainLikeCategory onFail', error);
};
TAxios(
dispatch,
getState,
'post',
URLS.SET_MAIN_LIKE_CATEGORY,
{},
{ patnrId, prdtId },
onSuccess,
onFail
);
};
// HOME Live Full 영상 상세 보기 정보 조회 IF-LGSP-302
export const getHomeFullVideoInfo =
({ lgCatCd }) =>
(dispatch, getState) => {
const onSuccess = (response) => {
dlog('getHomeFullVideoInfo onSuccess', response.data.data.showInfos);
// ✨ DEBUG: youmaylikeInfos 데이터 확인
dlog('[DEBUG] GET_HOME_FULL_VIDEO_INFO - API Response:', {
youmaylikeInfos: response.data.data.youmaylikeInfos,
youmaylikeInfos_length: response.data.data.youmaylikeInfos?.length,
liveChannelInfos_length: response.data.data.liveChannelInfos?.length,
featuredShowsInfos_length: response.data.data.featuredShowsInfos?.length,
});
dispatch({
type: types.GET_HOME_FULL_VIDEO_INFO,
payload: { data: response.data.data, lgCatCd },
});
};
const onFail = (error) => {
derror('getHomeFullVideoInfo onSuccess', error);
};
TAxios(
dispatch,
getState,
'get',
URLS.GET_HOME_FULL_VIDEO_INFO,
{ lgCatCd },
{},
onSuccess,
onFail
);
};
// 메인화면 Live 현재 방송 상품 조회 IF-LGSP-046
export const getMainLiveShowNowProduct =
({ patnrId, showId, lstChgDt }) =>
(dispatch, getState) => {
return TAxiosAdvancedPromise(
dispatch,
getState,
'get',
URLS.GET_MAIN_LIVE_SHOW_NOW_PRODUCT,
{ patnrId, showId, lstChgDt },
{},
{
retries: 2, // 3회까지 재시도 (처음 시도 + 2회 재시도)
retryDelay: 500, // 500ms 간격으로 재시도
throwOnError: false, // 에러를 throw하지 않고 객체로 반환
}
).then((result) => {
if (result.success && result.data?.data) {
dispatch({
type: types.GET_MAIN_LIVE_SHOW_NOW_PRODUCT,
payload: result.data.data,
});
} else {
console.error('getMainLiveShowNowProduct onFail', result.error);
}
return result;
});
};
export const clearShopNowInfo = () => {
return {
type: types.CLEAR_SHOPNOW_INFO,
};
};