[251019] fix: Background Video

🕐 커밋 시간: 2025. 10. 19. 21:30:53

📊 변경 통계:
  • 총 파일: 10개
  • 추가: +86줄
  • 삭제: -42줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/mainActions.js
  ~ com.twin.app.shoptime/src/actions/playActions.js
  ~ com.twin.app.shoptime/src/reducers/mainReducer.js
  ~ com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductContentSection/ProductVideo/ProductVideo.v2.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx
  ~ com.twin.app.shoptime/src/views/UserReview/ShowUserReviews.jsx
  ~ com.twin.app.shoptime/src/views/UserReview/UserReviewPanel.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/actions/mainActions.js (javascript):
    🔄 Modified: clearSubCategory()
  📄 com.twin.app.shoptime/src/actions/playActions.js (javascript):
     Deleted: resumeModalVideo()
  📄 com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx (javascript):
     Added: extractProductMeta()
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx (javascript):
    🔄 Modified: Spottable()
  📄 com.twin.app.shoptime/src/views/UserReview/ShowUserReviews.jsx (javascript):
     Added: ShowUserReviews()
     Deleted: ShowUserReviews()

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
This commit is contained in:
2025-10-19 21:30:58 +09:00
parent 500bf50d5a
commit c44866f2d1
10 changed files with 175 additions and 177 deletions

View File

@@ -1,25 +1,17 @@
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 { import { CATEGORY_DATA_MAX_RESULTS_LIMIT, LOG_CONTEXT_NAME, LOG_MESSAGE_ID } from '../utils/Config';
CATEGORY_DATA_MAX_RESULTS_LIMIT, import * as HelperMethods from '../utils/helperMethods';
LOG_CONTEXT_NAME, import { types } from './actionTypes';
LOG_MESSAGE_ID, import { addReservation, changeAppStatus, deleteReservation } from './commonActions';
} from "../utils/Config";
import * as HelperMethods from "../utils/helperMethods";
import { types } from "./actionTypes";
import {
addReservation,
changeAppStatus,
deleteReservation,
} from "./commonActions";
//IF-LGSP-007 //IF-LGSP-007
export const getMainLiveShow = (props) => (dispatch, getState) => { export const getMainLiveShow = (props) => (dispatch, getState) => {
const vodIncFlag = props?.vodIncFlag; const vodIncFlag = props?.vodIncFlag;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("@@ getMainLiveShow onSuccess", response.data); console.log('@@ getMainLiveShow onSuccess', response.data);
dispatch({ dispatch({
type: types.GET_MAIN_LIVE_SHOW, type: types.GET_MAIN_LIVE_SHOW,
@@ -28,38 +20,20 @@ export const getMainLiveShow = (props) => (dispatch, getState) => {
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("@@ getMainLiveShow onFail", error); console.error('@@ getMainLiveShow onFail', error);
}; };
TAxios( TAxios(dispatch, getState, 'get', URLS.GET_MAIN_LIVE_SHOW, { vodIncFlag }, {}, onSuccess, onFail);
dispatch,
getState,
"get",
URLS.GET_MAIN_LIVE_SHOW,
{ vodIncFlag },
{},
onSuccess,
onFail
);
}; };
// Live 알람 설정/해제 IF-LGSP-012 // Live 알람 설정/해제 IF-LGSP-012
export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => { export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
const { const { alamDispFlag, chanId, endDt, patnrId, patncNm, showId, showNm, strtDt } = props;
alamDispFlag,
chanId,
endDt,
patnrId,
patncNm,
showId,
showNm,
strtDt,
} = props;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("setMainLiveUpcomingAlarm onSuccess", response.data); console.log('setMainLiveUpcomingAlarm onSuccess', response.data);
if (alamDispFlag === "Y") { if (alamDispFlag === 'Y') {
const convertedStrtDt = convertUtcToLocal(strtDt); const convertedStrtDt = convertUtcToLocal(strtDt);
const data = { const data = {
@@ -72,13 +46,13 @@ export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
second: convertedStrtDt.getSeconds(), second: convertedStrtDt.getSeconds(),
}, },
params: { params: {
message: `[${patncNm}] ${showNm}\n${HelperMethods.$L("Watch Now!")}`, message: `[${patncNm}] ${showNm}\n${HelperMethods.$L('Watch Now!')}`,
buttons: [ buttons: [
{ {
label: HelperMethods.$L("yes"), label: HelperMethods.$L('yes'),
}, },
{ {
label: HelperMethods.$L("no"), label: HelperMethods.$L('no'),
}, },
], ],
launch: { launch: {
@@ -92,19 +66,19 @@ export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
dispatch(addReservation(data)); dispatch(addReservation(data));
} }
// //
else if (alamDispFlag === "N") { else if (alamDispFlag === 'N') {
dispatch(deleteReservation(showId)); dispatch(deleteReservation(showId));
} }
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("setMainLiveUpcomingAlarm onFail", error); console.error('setMainLiveUpcomingAlarm onFail', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"post", 'post',
URLS.SET_MAIN_LIVE_UPCOMING_ALARM, URLS.SET_MAIN_LIVE_UPCOMING_ALARM,
{}, {},
{ alamDispFlag, endDt, patnrId, showId, strtDt }, { alamDispFlag, endDt, patnrId, showId, strtDt },
@@ -117,10 +91,10 @@ export const setMainLiveUpcomingAlarm = (props) => (dispatch, getState) => {
export const getMainCategoryDetail = (props) => (dispatch, getState) => { export const getMainCategoryDetail = (props) => (dispatch, getState) => {
const { patnrId, prdtId, liveReqFlag } = props; const { patnrId, prdtId, liveReqFlag } = props;
dispatch(changeAppStatus({ showLoadingPanel: { show: true, type: "wait" } })); dispatch(changeAppStatus({ showLoadingPanel: { show: true, type: 'wait' } }));
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getMainCategoryDetail onSuccess ", response.data); console.log('getMainCategoryDetail onSuccess ', response.data);
dispatch({ dispatch({
type: types.GET_PRODUCT_DETAIL, type: types.GET_PRODUCT_DETAIL,
@@ -131,14 +105,14 @@ export const getMainCategoryDetail = (props) => (dispatch, getState) => {
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getMainCategoryDetail onFail", error); console.error('getMainCategoryDetail onFail', error);
dispatch(changeAppStatus({ showLoadingPanel: { show: false } })); dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_PRODUCT_DETAIL, URLS.GET_PRODUCT_DETAIL,
{ patnrId, prdtId, liveReqFlag }, { patnrId, prdtId, liveReqFlag },
{}, {},
@@ -151,7 +125,7 @@ export const getMainCategoryDetail = (props) => (dispatch, getState) => {
export const getMainCategoryShowDetail = (props) => (dispatch, getState) => { export const getMainCategoryShowDetail = (props) => (dispatch, getState) => {
const { patnrId, showId, curationId } = props; const { patnrId, showId, curationId } = props;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getMainCategoryShowDetail onSuccess ", response.data); console.log('getMainCategoryShowDetail onSuccess ', response.data);
dispatch({ dispatch({
type: types.GET_MAIN_CATEGORY_SHOW_DETAIL, type: types.GET_MAIN_CATEGORY_SHOW_DETAIL,
@@ -160,13 +134,13 @@ export const getMainCategoryShowDetail = (props) => (dispatch, getState) => {
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getMainCategoryShowDetail onFail", error); console.error('getMainCategoryShowDetail onFail', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_MAIN_CATEGORY_SHOW_DETAIL, URLS.GET_MAIN_CATEGORY_SHOW_DETAIL,
{ patnrId, showId, curationId }, { patnrId, showId, curationId },
{}, {},
@@ -189,7 +163,7 @@ export const getSubCategory =
lastSubCategoryParams && lastSubCategoryParams &&
JSON.stringify(lastSubCategoryParams) === JSON.stringify(params) JSON.stringify(lastSubCategoryParams) === JSON.stringify(params)
) { ) {
console.log("getSubCategory ignore patch"); console.log('getSubCategory ignore patch');
return; return;
} }
lastSubCategoryParams = { ...params }; lastSubCategoryParams = { ...params };
@@ -200,7 +174,7 @@ export const getSubCategory =
let currentKey = key; let currentKey = key;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getSubCategory onSuccess ", response.data); console.log('getSubCategory onSuccess ', response.data);
if (pageNo === 1) { if (pageNo === 1) {
getSubCategoryKey = new Date(); getSubCategoryKey = new Date();
@@ -227,7 +201,7 @@ export const getSubCategory =
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getSubCategory onFail", error); console.error('getSubCategory onFail', error);
if (pageNo === 1) { if (pageNo === 1) {
lastSubCategoryParams = {}; lastSubCategoryParams = {};
} }
@@ -236,7 +210,7 @@ export const getSubCategory =
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_SUB_CATEGORY, URLS.GET_SUB_CATEGORY,
{ lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType }, { lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType },
{}, {},
@@ -245,33 +219,27 @@ export const getSubCategory =
); );
}; };
export const continueGetSubCategory = export const continueGetSubCategory = (key, pageNo) => (dispatch, getState) => {
(key, pageNo) => if (!lastSubCategoryParams) {
(dispatch, getState) => { console.warn('No previous category parameters found');
if (!lastSubCategoryParams) { return;
console.warn("No previous category parameters found"); }
return;
}
const subCategoryData = getState().main.subCategoryData; const subCategoryData = getState().main.subCategoryData;
const targetData = const targetData =
subCategoryData[key]?.subCatItemList || subCategoryData[key]?.subCatItemList || subCategoryData[key]?.subCatShowList || [];
subCategoryData[key]?.subCatShowList || const totalCount = subCategoryData[key]?.total ?? 0;
[]; const startIndex = CATEGORY_DATA_MAX_RESULTS_LIMIT * (pageNo - 1);
const totalCount = subCategoryData[key]?.total ?? 0; if (
const startIndex = CATEGORY_DATA_MAX_RESULTS_LIMIT * (pageNo - 1); (startIndex <= 1 && !targetData) ||
if ( startIndex < targetData.length ||
(startIndex <= 1 && !targetData) || totalCount - 1 <= startIndex
startIndex < targetData.length || ) {
(totalCount -1) <= startIndex //ignore query
) { return;
//ignore query }
return; dispatch(getSubCategory({ ...lastSubCategoryParams }, pageNo, getSubCategoryKey));
} };
dispatch(
getSubCategory({ ...lastSubCategoryParams }, pageNo, getSubCategoryKey)
);
};
const clearSubCategory = () => ({ const clearSubCategory = () => ({
type: types.CLEAR_SUB_CATEGORY, type: types.CLEAR_SUB_CATEGORY,
@@ -280,7 +248,7 @@ const clearSubCategory = () => ({
// TOP20 영상 목록 조회 IF-LGSP-069 // TOP20 영상 목록 조회 IF-LGSP-069
export const getTop20Show = () => (dispatch, getState) => { export const getTop20Show = () => (dispatch, getState) => {
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getTop20Show onSuccess ", response.data); console.log('getTop20Show onSuccess ', response.data);
dispatch({ dispatch({
type: types.GET_TOP_20_SHOW, type: types.GET_TOP_20_SHOW,
@@ -290,20 +258,11 @@ export const getTop20Show = () => (dispatch, getState) => {
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getTop20Show onFail", error); console.error('getTop20Show onFail', error);
dispatch(changeAppStatus({ showLoadingPanel: { show: false } })); dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
}; };
TAxios( TAxios(dispatch, getState, 'get', URLS.GET_TOP20_SHOW, {}, {}, onSuccess, onFail);
dispatch,
getState,
"get",
URLS.GET_TOP20_SHOW,
{},
{},
onSuccess,
onFail
);
}; };
// 유메이라이크 아이템 리스트 IF-LGSP-201 // 유메이라이크 아이템 리스트 IF-LGSP-201
@@ -345,13 +304,13 @@ export const getMainYouMayLike =
// errorResponse: error?.response, // errorResponse: error?.response,
// errorData: error?.response?.data // errorData: error?.response?.data
// }); // });
console.error("getMainYouMayLike onFail", error); console.error('getMainYouMayLike onFail', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_YOUMAYLIKE, URLS.GET_YOUMAYLIKE,
{ lgCatCd, exclCurationId, exclPatnrId, exclPrdtId, catDpTh3, catDpTh4 }, { lgCatCd, exclCurationId, exclPatnrId, exclPrdtId, catDpTh3, catDpTh4 },
{}, {},
@@ -365,20 +324,20 @@ export const getMyFavoriteFlag = (params) => (dispatch, getState) => {
const { patnrId, prdtId } = params; const { patnrId, prdtId } = params;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getMyFavoriteFlag onSuccess ", response.data); console.log('getMyFavoriteFlag onSuccess ', response.data);
dispatch({ dispatch({
type: types.GET_MY_FAVORITE_FLAG, type: types.GET_MY_FAVORITE_FLAG,
payload: response.data.data, payload: response.data.data,
}); });
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getMyFavoriteFlag onFail", error); console.error('getMyFavoriteFlag onFail', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_MY_FAVORITE_FLAG, URLS.GET_MY_FAVORITE_FLAG,
{ patnrId, prdtId }, { patnrId, prdtId },
{}, {},
@@ -391,20 +350,20 @@ export const setMainLikeCategory = (params) => (dispatch, getState) => {
const { patnrId, prdtId } = params; const { patnrId, prdtId } = params;
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("setMainLikeCategory onSuccess ", response.data); console.log('setMainLikeCategory onSuccess ', response.data);
dispatch({ dispatch({
type: types.SET_MAIN_LIKE_CATEGORY, type: types.SET_MAIN_LIKE_CATEGORY,
payload: response.data.data, payload: response.data.data,
}); });
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("setMainLikeCategory onFail", error); console.error('setMainLikeCategory onFail', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"post", 'post',
URLS.SET_MAIN_LIKE_CATEGORY, URLS.SET_MAIN_LIKE_CATEGORY,
{}, {},
{ patnrId, prdtId }, { patnrId, prdtId },
@@ -418,10 +377,15 @@ export const getHomeFullVideoInfo =
({ lgCatCd }) => ({ lgCatCd }) =>
(dispatch, getState) => { (dispatch, getState) => {
const onSuccess = (response) => { const onSuccess = (response) => {
console.log( console.log('getHomeFullVideoInfo onSuccess', response.data.data.showInfos);
"getHomeFullVideoInfo onSuccess",
response.data.data.showInfos // ✨ DEBUG: youmaylikeInfos 데이터 확인
); console.log('[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({ dispatch({
type: types.GET_HOME_FULL_VIDEO_INFO, type: types.GET_HOME_FULL_VIDEO_INFO,
@@ -430,13 +394,13 @@ export const getHomeFullVideoInfo =
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getHomeFullVideoInfo onSuccess", error); console.error('getHomeFullVideoInfo onSuccess', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_HOME_FULL_VIDEO_INFO, URLS.GET_HOME_FULL_VIDEO_INFO,
{ lgCatCd }, { lgCatCd },
{}, {},
@@ -450,7 +414,7 @@ export const getMainLiveShowNowProduct =
({ patnrId, showId, lstChgDt }) => ({ patnrId, showId, lstChgDt }) =>
(dispatch, getState) => { (dispatch, getState) => {
const onSuccess = (response) => { const onSuccess = (response) => {
console.log("getMainLiveShowNowProduct onSuccess", response.data); console.log('getMainLiveShowNowProduct onSuccess', response.data);
dispatch({ dispatch({
type: types.GET_MAIN_LIVE_SHOW_NOW_PRODUCT, type: types.GET_MAIN_LIVE_SHOW_NOW_PRODUCT,
@@ -459,13 +423,13 @@ export const getMainLiveShowNowProduct =
}; };
const onFail = (error) => { const onFail = (error) => {
console.error("getMainLiveShowNowProduct onFail", error); console.error('getMainLiveShowNowProduct onFail', error);
}; };
TAxios( TAxios(
dispatch, dispatch,
getState, getState,
"get", 'get',
URLS.GET_MAIN_LIVE_SHOW_NOW_PRODUCT, URLS.GET_MAIN_LIVE_SHOW_NOW_PRODUCT,
{ patnrId, showId, lstChgDt }, { patnrId, showId, lstChgDt },
{}, {},

View File

@@ -139,20 +139,12 @@ export const resumeModalVideo = () => (dispatch, getState) => {
export const pauseFullscreenVideo = () => (dispatch, getState) => { export const pauseFullscreenVideo = () => (dispatch, getState) => {
const panels = getState().panels.panels; const panels = getState().panels.panels;
// console.log('[BgVideo] pauseFullscreenVideo called - panels:', {
// panelsCount: panels?.length,
// panels: panels?.map(p => ({ name: p.name, modal: p.panelInfo?.modal, isPaused: p.panelInfo?.isPaused }))
// });
// 전체화면 PlayerPanel 찾기 (modal이 false인 패널) // 전체화면 PlayerPanel 찾기 (modal이 false인 패널)
const fullscreenPlayerPanel = panels.find( const fullscreenPlayerPanel = panels.find(
(panel) => panel.name === panel_names.PLAYER_PANEL && !panel.panelInfo?.modal (panel) => panel.name === panel_names.PLAYER_PANEL && !panel.panelInfo?.modal
); );
// console.log('[BgVideo] pauseFullscreenVideo - fullscreenPlayerPanel found:', !!fullscreenPlayerPanel);
if (fullscreenPlayerPanel) { if (fullscreenPlayerPanel) {
// console.log('[BgVideo] pauseFullscreenVideo - dispatching updatePanel with isPaused: true');
dispatch( dispatch(
updatePanel({ updatePanel({
name: panel_names.PLAYER_PANEL, name: panel_names.PLAYER_PANEL,
@@ -162,8 +154,6 @@ export const pauseFullscreenVideo = () => (dispatch, getState) => {
}, },
}) })
); );
} else {
console.log('[BgVideo] pauseFullscreenVideo - No fullscreen PlayerPanel found, skipping');
} }
}; };

View File

@@ -1,11 +1,11 @@
import { types } from "../actions/actionTypes"; import { types } from '../actions/actionTypes';
import { CATEGORY_DATA_MAX_RESULTS_LIMIT } from "../utils/Config"; import { CATEGORY_DATA_MAX_RESULTS_LIMIT } from '../utils/Config';
const initialState = { const initialState = {
subCategoryData: {}, subCategoryData: {},
top20ShowData: {}, top20ShowData: {},
productData: null, productData: null,
fullVideolgCatCd: "", fullVideolgCatCd: '',
fullVideoData: {}, fullVideoData: {},
showDetailInfo: [], showDetailInfo: [],
showNowInfo: null, showNowInfo: null,
@@ -23,9 +23,9 @@ export const mainReducer = (state = initialState, action) => {
switch (action.type) { switch (action.type) {
case types.GET_SUB_CATEGORY: { case types.GET_SUB_CATEGORY: {
const dataType = action.payload.categoryShowInfos const dataType = action.payload.categoryShowInfos
? "categoryShowInfos" ? 'categoryShowInfos'
: action.payload.categoryItemInfos : action.payload.categoryItemInfos
? "categoryItemInfos" ? 'categoryItemInfos'
: null; : null;
if (!dataType) { if (!dataType) {
@@ -44,9 +44,9 @@ export const mainReducer = (state = initialState, action) => {
} }
const subKey = action.payload[dataType]?.subCatShowList const subKey = action.payload[dataType]?.subCatShowList
? "subCatShowList" ? 'subCatShowList'
: action.payload[dataType]?.subCatItemList : action.payload[dataType]?.subCatItemList
? "subCatItemList" ? 'subCatItemList'
: null; : null;
if (!subKey) { if (!subKey) {
@@ -151,6 +151,13 @@ export const mainReducer = (state = initialState, action) => {
} }
case types.GET_HOME_FULL_VIDEO_INFO: { case types.GET_HOME_FULL_VIDEO_INFO: {
const { data, lgCatCd } = action.payload; const { data, lgCatCd } = action.payload;
// ✨ DEBUG: Reducer에서 youmaylikeInfos 저장 확인
console.log('[DEBUG] Reducer - GET_HOME_FULL_VIDEO_INFO:', {
youmaylikeInfos_length: data.youmaylikeInfos?.length,
youmaylikeInfos: data.youmaylikeInfos,
});
return { return {
...state, ...state,
fullVideolgCatCd: lgCatCd, fullVideolgCatCd: lgCatCd,
@@ -184,9 +191,10 @@ export const mainReducer = (state = initialState, action) => {
}; };
} }
case types.CLEAR_SHOPNOW_INFO: case types.CLEAR_SHOPNOW_INFO:
console.log('[DEBUG] Reducer - CLEAR_SHOPNOW_INFO called - youmaylikeInfos will be null');
return { return {
...state, ...state,
fullVideolgCatCd: "", fullVideolgCatCd: '',
showDetailInfo: [], showDetailInfo: [],
showNowInfo: null, showNowInfo: null,
fullVideoData: null, fullVideoData: null,

View File

@@ -73,11 +73,18 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
[panelInfo] [panelInfo]
); );
const panelBgImgNo = useMemo(() => fp.pipe(() => panelInfo, fp.get('bgImgNo'))(), [panelInfo]); const panelBgImgNo = useMemo(() => fp.pipe(() => panelInfo, fp.get('bgImgNo'))(), [panelInfo]);
// PlayerPanel에서 진입했는지 여부를 panelInfo에서 추출
const panelLaunchedFromPlayer = useMemo( const panelLaunchedFromPlayer = useMemo(
() => fp.pipe(() => panelInfo, fp.get('launchedFromPlayer'))(), () => fp.pipe(() => panelInfo, fp.get('launchedFromPlayer'))(),
[panelInfo] [panelInfo]
); );
const panelLaunchedFromUserReviewPanel = useMemo(
() => fp.pipe(() => panelInfo, fp.get('launchedFromUserReviewPanel'), fp.defaultTo(false))(),
[panelInfo]
);
const panelBgVideoInfo = useMemo(
() => fp.pipe(() => panelInfo, fp.get('bgVideoInfo'), fp.defaultTo(null))(),
[panelInfo]
);
const productPmtSuptYn = useMemo( const productPmtSuptYn = useMemo(
() => fp.pipe(() => productData, fp.get('pmtSuptYn'))(), () => fp.pipe(() => productData, fp.get('pmtSuptYn'))(),
[productData] [productData]
@@ -712,6 +719,9 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
themeProductInfo={themeProductInfo} themeProductInfo={themeProductInfo}
onReady={handleProductAllSectionReady} onReady={handleProductAllSectionReady}
isOnRender={renderStates.canRender} isOnRender={renderStates.canRender}
launchedFromPlayer={panelLaunchedFromPlayer}
launchedFromUserReviewPanel={panelLaunchedFromUserReviewPanel}
bgVideoInfo={panelBgVideoInfo}
/> />
); );
} }

View File

@@ -16,6 +16,7 @@ import arrowDown from '../../../../assets/images/icons/ic_arrow_down_3x_new.png'
import indicatorDefaultImage from '../../../../assets/images/img-thumb-empty-144@3x.png'; import indicatorDefaultImage from '../../../../assets/images/img-thumb-empty-144@3x.png';
// import { pushPanel } from '../../../actions/panelActions'; // import { pushPanel } from '../../../actions/panelActions';
import { minimizeModalMedia } from '../../../actions/mediaActions'; import { minimizeModalMedia } from '../../../actions/mediaActions';
import { pauseFullscreenVideo } from '../../../actions/playActions';
import { resetShowAllReviews } from '../../../actions/productActions'; import { resetShowAllReviews } from '../../../actions/productActions';
import { showToast } from '../../../actions/toastActions'; import { showToast } from '../../../actions/toastActions';
// ProductInfoSection imports // ProductInfoSection imports
@@ -124,6 +125,7 @@ export default function ProductAllSection({
productType, productType,
productInfo, productInfo,
panelInfo, panelInfo,
launchedFromPlayer,
selectedIndex, selectedIndex,
selectedPatnrId, selectedPatnrId,
selectedPrdtId, selectedPrdtId,
@@ -133,6 +135,8 @@ export default function ProductAllSection({
themeProductInfo, themeProductInfo,
onReady, onReady,
isOnRender, isOnRender,
launchedFromUserReviewPanel,
bgVideoInfo,
}) { }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
@@ -829,7 +833,7 @@ export default function ProductAllSection({
}} }}
/> />
{/* <ViewAllReviewsButton /> */} {/* <ViewAllReviewsButton /> */}
<ShowUserReviews /> <ShowUserReviews hasVideo={hasVideo} launchedFromPlayer={launchedFromPlayer} />
</div> </div>
)} )}
</div> </div>

View File

@@ -288,11 +288,9 @@ export default function ProductVideoV2({
useEffect(() => { useEffect(() => {
if (autoPlay && canPlayVideo && !isPlaying) { if (autoPlay && canPlayVideo && !isPlaying) {
autoPlayTimerRef.current = setTimeout(() => { autoPlayTimerRef.current = setTimeout(() => {
// console.log('[BgVideo] ProductVideoV2 - AutoPlay starting');
setIsPlaying(true); setIsPlaying(true);
// 백그라운드 전체화면 비디오 일시정지 // 백그라운드 전체화면 비디오 일시정지
// console.log('[BgVideo] ProductVideoV2 - Pausing background fullscreen video (autoPlay)');
dispatch(pauseFullscreenVideo()); dispatch(pauseFullscreenVideo());
}, 500); }, 500);
} }

View File

@@ -356,26 +356,13 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
// 새로운 useEffect 추가 (라인 328 이후) // 새로운 useEffect 추가 (라인 328 이후)
useEffect(() => { useEffect(() => {
// console.log('[BgVideo] PlayerPanel useEffect - panelInfo:', {
// modal: panelInfo?.modal,
// isPaused: panelInfo?.isPaused,
// hasVideoPlayer: !!videoPlayer.current
// });
// modal 여부와 관계없이 videoPlayer가 있고 isPaused 값이 명시적일 때 제어 // modal 여부와 관계없이 videoPlayer가 있고 isPaused 값이 명시적일 때 제어
if (videoPlayer.current && panelInfo?.isPaused !== undefined) { if (videoPlayer.current && panelInfo?.isPaused !== undefined) {
if (panelInfo.isPaused === true) { if (panelInfo.isPaused === true) {
// console.log('[BgVideo] PlayerPanel - Executing pause via videoPlayer.current');
videoPlayer.current.pause(); videoPlayer.current.pause();
} else if (panelInfo.isPaused === false) { } else if (panelInfo.isPaused === false) {
// console.log('[BgVideo] PlayerPanel - Executing play via videoPlayer.current');
videoPlayer.current.play(); videoPlayer.current.play();
} }
} else {
console.log('[BgVideo] PlayerPanel - Skipping video control:', {
hasVideoPlayer: !!videoPlayer.current,
isPausedValue: panelInfo?.isPaused,
});
} }
}, [panelInfo?.isPaused]); }, [panelInfo?.isPaused]);

View File

@@ -42,6 +42,18 @@ export default function TabContainerV2({
}) { }) {
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos); const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
// ✨ DEBUG: youmaylikeInfos 데이터 로그
useEffect(() => {
console.log('[DEBUG] TabContainerV2 - youmaylikeInfos:', {
exists: !!youmaylikeInfos,
length: youmaylikeInfos?.length,
data: youmaylikeInfos,
shopNowInfo_length: shopNowInfo?.length,
shouldShowYouMayAlso:
shopNowInfo && shopNowInfo.length < 3 && youmaylikeInfos && youmaylikeInfos.length > 0,
});
}, [youmaylikeInfos, shopNowInfo]);
const tabList = [ const tabList = [
$L('SHOP NOW'), $L('SHOP NOW'),
panelInfo?.shptmBanrTpNm === 'LIVE' ? $L('LIVE CHANNEL') : $L('FEATURED SHOWS'), panelInfo?.shptmBanrTpNm === 'LIVE' ? $L('LIVE CHANNEL') : $L('FEATURED SHOWS'),

View File

@@ -1,14 +1,14 @@
import React, { useCallback, useEffect } from "react"; import React, { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from 'react-redux';
import Spottable from "@enact/spotlight/Spottable"; import Spottable from '@enact/spotlight/Spottable';
import Spotlight from "@enact/spotlight"; import Spotlight from '@enact/spotlight';
import { pushPanel } from "../../actions/panelActions"; import { pushPanel } from '../../actions/panelActions';
import { panel_names } from "../../utils/Config"; import { panel_names } from '../../utils/Config';
import css from "./ShowUserReviews.module.less"; import css from './ShowUserReviews.module.less';
const SpottableComponent = Spottable("div"); const SpottableComponent = Spottable('div');
const ShowUserReviews = () => { const ShowUserReviews = ({ hasVideo, launchedFromPlayer }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const reviewListData = useSelector( const reviewListData = useSelector(
@@ -18,24 +18,24 @@ const ShowUserReviews = () => {
const productData = useSelector((state) => state.main.productData || {}); const productData = useSelector((state) => state.main.productData || {});
const handleShowUserReviewsClick = useCallback(() => { const handleShowUserReviewsClick = useCallback(() => {
console.log(`[ProductId] Show User Reviews clicked - opening UserReviewPanel`, {
productDataPrdtId: productData.prdtId,
hasProductData: !!productData,
reviewData: reviewData,
reviewDetailTotRvwCnt: reviewData.reviewDetail?.totRvwCnt,
reviewListLength: reviewListData?.length,
productData: productData
});
dispatch( dispatch(
pushPanel({ pushPanel({
name: panel_names.USER_REVIEW_PANEL, name: panel_names.USER_REVIEW_PANEL,
panelInfo: { panelInfo: {
prdtId: productData.prdtId, prdtId: productData.prdtId,
productImage: productData.imgUrls600?.[0] || productData.imgUrls?.[0] || productData.thumbnailUrl || 'https://placehold.co/150x150', productImage:
productData.imgUrls600?.[0] ||
productData.imgUrls?.[0] ||
productData.thumbnailUrl ||
'https://placehold.co/150x150',
brandLogo: productData.patncLogoPath || 'https://placehold.co/50x50', brandLogo: productData.patncLogoPath || 'https://placehold.co/50x50',
productName: productData.prdtNm || '상품명 정보가 없습니다', productName: productData.prdtNm || '상품명 정보가 없습니다',
avgRating: reviewData.reviewDetail?.avgRvwScr || 5, avgRating: reviewData.reviewDetail?.avgRvwScr || 5,
reviewCount: reviewData.reviewDetail?.totRvwCnt || reviewListData?.length || 0 reviewCount: reviewData.reviewDetail?.totRvwCnt || reviewListData?.length || 0,
bgVideoInfo: {
hasVideo: hasVideo,
launchedFromPlayer: launchedFromPlayer ?? false,
},
}, },
}) })
); );
@@ -43,25 +43,27 @@ const ShowUserReviews = () => {
const handleKeyDown = useCallback((event) => { const handleKeyDown = useCallback((event) => {
if (event.key === 'ArrowUp') { if (event.key === 'ArrowUp') {
console.log("[ShowUserReviews] ArrowUp key pressed - attempting to focus last review"); console.log('[ShowUserReviews] ArrowUp key pressed - attempting to focus last review');
const container = document.querySelector('[data-spotlight-id="user-reviews-container"]'); const container = document.querySelector('[data-spotlight-id="user-reviews-container"]');
const savedScrollTop = container?.scrollTop || 0; const savedScrollTop = container?.scrollTop || 0;
setTimeout(() => { setTimeout(() => {
const lastReviewElement = document.querySelector('[data-spotlight-id="user-review-at-last"]'); const lastReviewElement = document.querySelector(
'[data-spotlight-id="user-review-at-last"]'
);
if (lastReviewElement) { if (lastReviewElement) {
console.log("[ShowUserReviews] Found last review element, focusing..."); console.log('[ShowUserReviews] Found last review element, focusing...');
Spotlight.focus(lastReviewElement); Spotlight.focus(lastReviewElement);
if (container) container.scrollTop = savedScrollTop; if (container) container.scrollTop = savedScrollTop;
} else { } else {
console.log("[ShowUserReviews] Last review element not found, trying alternative..."); console.log('[ShowUserReviews] Last review element not found, trying alternative...');
const reviewElements = document.querySelectorAll('[data-spotlight-id^="user-review-"]'); const reviewElements = document.querySelectorAll('[data-spotlight-id^="user-review-"]');
if (reviewElements.length > 0) { if (reviewElements.length > 0) {
const lastElement = reviewElements[reviewElements.length - 1]; const lastElement = reviewElements[reviewElements.length - 1];
console.log("[ShowUserReviews] Focusing last review element (alternative method)"); console.log('[ShowUserReviews] Focusing last review element (alternative method)');
Spotlight.focus(lastElement); Spotlight.focus(lastElement);
if (container) container.scrollTop = savedScrollTop; if (container) container.scrollTop = savedScrollTop;
@@ -72,10 +74,10 @@ const ShowUserReviews = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
console.log("[ShowUserReviews] Component mounted/updated", { console.log('[ShowUserReviews] Component mounted/updated', {
hasReviewData: !!reviewListData, hasReviewData: !!reviewListData,
reviewCount: reviewListData?.length || 0, reviewCount: reviewListData?.length || 0,
spotlightUpTarget: "user-review-at-last" spotlightUpTarget: 'user-review-at-last',
}); });
}, [reviewListData]); }, [reviewListData]);
@@ -98,4 +100,4 @@ const ShowUserReviews = () => {
); );
}; };
export default ShowUserReviews; export default ShowUserReviews;

View File

@@ -3,11 +3,12 @@ import React, { useCallback, useEffect, useState } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { popPanel } from '../../actions/panelActions'; import { popPanel, updatePanel } from '../../actions/panelActions';
import TBody from '../../components/TBody/TBody'; import TBody from '../../components/TBody/TBody';
import TPanel from '../../components/TPanel/TPanel'; import TPanel from '../../components/TPanel/TPanel';
import useReviews from '../../hooks/useReviews/useReviews'; import useReviews from '../../hooks/useReviews/useReviews';
import fp from '../../utils/fp'; import fp from '../../utils/fp';
import { panel_names } from '../../utils/Config';
import StarRating from '../DetailPanel/components/StarRating'; import StarRating from '../DetailPanel/components/StarRating';
import FilterItemButton from './components/FilterItemButton'; import FilterItemButton from './components/FilterItemButton';
import UserReviewsList from './components/UserReviewsList'; import UserReviewsList from './components/UserReviewsList';
@@ -53,10 +54,12 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
const productId = fp.pipe(() => panelInfo, fp.get('prdtId'), fp.defaultTo(null))(); const productId = fp.pipe(() => panelInfo, fp.get('prdtId'), fp.defaultTo(null))();
const bgVideoInfo = fp.pipe(() => panelInfo, fp.get('bgVideoInfo'), fp.defaultTo(null))();
const productName = fp.pipe( const productName = fp.pipe(
() => panelInfo, () => panelInfo,
fp.get('productName'), fp.get('productName'),
fp.defaultTo('?<3F><EFBFBD>??<3F>보가 ?<3F>습?<3F>') fp.defaultTo('There is product infos')
)(); )();
const handleNextPage = useCallback(() => { const handleNextPage = useCallback(() => {
@@ -110,7 +113,6 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
const handleCinnamonClick = useCallback(() => console.log('Cinnamon clicked'), []); const handleCinnamonClick = useCallback(() => console.log('Cinnamon clicked'), []);
const handleQualityClick = useCallback(() => console.log('Quality clicked'), []); const handleQualityClick = useCallback(() => console.log('Quality clicked'), []);
// 감정 ?<3F><EFBFBD>??<3F>들?<3F>들 - 별점 ?<3F>터?<3F> ?<3F>일??방식
const handleSentimentFilter = useCallback( const handleSentimentFilter = useCallback(
(sentiment) => { (sentiment) => {
applySentimentFilter(sentiment === 'all' ? null : sentiment); applySentimentFilter(sentiment === 'all' ? null : sentiment);
@@ -134,8 +136,29 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
}, [clearAllFilters]); }, [clearAllFilters]);
const handleBackButton = useCallback(() => { const handleBackButton = useCallback(() => {
if (bgVideoInfo && bgVideoInfo.hasVideo) {
dispatch(
updatePanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
isPaused: true, // 일시정지 상태 유지!
},
})
);
}
dispatch(
updatePanel({
name: panel_names.DETAIL_PANEL,
panelInfo: {
bgVideoInfo: bgVideoInfo,
launchedFromUserReviewPanel: true,
},
})
);
// UserReviewPanel을 pop
dispatch(popPanel()); dispatch(popPanel());
}, [dispatch]); }, [dispatch, bgVideoInfo]);
return ( return (
<TPanel <TPanel