Compare commits
16 Commits
f47c1ecdf7
...
develop_si
| Author | SHA1 | Date | |
|---|---|---|---|
| cdf0d3de04 | |||
| 9ff6064bc9 | |||
| cfee554bf6 | |||
| a5fbb21d43 | |||
| 57cc6dbf20 | |||
| 74d2b827b0 | |||
| 9439630bad | |||
|
|
0a2ef0e68b | ||
| 96cbd1f67e | |||
| e8464b98b6 | |||
| 4904c6fb58 | |||
|
|
1c9db184fa | ||
| 3add749c07 | |||
| 3c3662f791 | |||
| 42eda7e0bb | |||
| d795182d4c |
2
com.twin.app.shoptime/.gitignore
vendored
2
com.twin.app.shoptime/.gitignore
vendored
@@ -22,3 +22,5 @@ nul
|
|||||||
OPTIMAL.md
|
OPTIMAL.md
|
||||||
.docs
|
.docs
|
||||||
|
|
||||||
|
GEMINI.md
|
||||||
|
|
||||||
|
|||||||
BIN
com.twin.app.shoptime/assets/images/featuredBrands/image-bg.png
Normal file
BIN
com.twin.app.shoptime/assets/images/featuredBrands/image-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
15
com.twin.app.shoptime/assets/images/featuredBrands/nbcu.svg
Normal file
15
com.twin.app.shoptime/assets/images/featuredBrands/nbcu.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 100 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 346 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 186 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
@@ -18,7 +18,6 @@ import { ThemeDecorator } from '@enact/sandstone/ThemeDecorator';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
changeAppStatus,
|
changeAppStatus,
|
||||||
changeLocalSettings,
|
|
||||||
// cancelFocusElement,
|
// cancelFocusElement,
|
||||||
// focusElement,
|
// focusElement,
|
||||||
// setExitApp,
|
// setExitApp,
|
||||||
@@ -45,7 +44,7 @@ import { pushPanel } from '../actions/panelActions';
|
|||||||
import { enqueuePanelHistory } from '../actions/panelHistoryActions';
|
import { enqueuePanelHistory } from '../actions/panelHistoryActions';
|
||||||
import NotSupportedVersion from '../components/NotSupportedVersion/NotSupportedVersion';
|
import NotSupportedVersion from '../components/NotSupportedVersion/NotSupportedVersion';
|
||||||
import ToastContainer from '../components/TToast/ToastContainer';
|
import ToastContainer from '../components/TToast/ToastContainer';
|
||||||
import GlobalPopup from '../components/GlobalPopup/GlobalPopup';
|
|
||||||
import usePrevious from '../hooks/usePrevious';
|
import usePrevious from '../hooks/usePrevious';
|
||||||
import { lunaTest } from '../lunaSend/lunaTest';
|
import { lunaTest } from '../lunaSend/lunaTest';
|
||||||
import { store } from '../store/store';
|
import { store } from '../store/store';
|
||||||
@@ -280,7 +279,7 @@ const originFocus = Spotlight.focus;
|
|||||||
const originMove = Spotlight.move;
|
const originMove = Spotlight.move;
|
||||||
const originSilentlyFocus = Spotlight.silentlyFocus;
|
const originSilentlyFocus = Spotlight.silentlyFocus;
|
||||||
let lastLoggedSpotlightId = null;
|
let lastLoggedSpotlightId = null;
|
||||||
let lastLoggedBlurSpotlightId = null;
|
let lastLoggedBlurSpotlightId = null; // eslint-disable-line no-unused-vars
|
||||||
let focusLoggingSuppressed = 0;
|
let focusLoggingSuppressed = 0;
|
||||||
|
|
||||||
const resolveSpotlightIdFromNode = (node) => {
|
const resolveSpotlightIdFromNode = (node) => {
|
||||||
@@ -407,28 +406,7 @@ Spotlight.silentlyFocus = function (...args) {
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveSpotlightIdFromEvent = (event) => {
|
|
||||||
if (!event) return undefined;
|
|
||||||
const { detail, target } = event;
|
|
||||||
|
|
||||||
if (detail) {
|
|
||||||
if (detail.spotlightId) {
|
|
||||||
return detail.spotlightId;
|
|
||||||
}
|
|
||||||
if (detail.id) {
|
|
||||||
return detail.id;
|
|
||||||
}
|
|
||||||
if (detail.target && detail.target.dataset && detail.target.dataset.spotlightId) {
|
|
||||||
return detail.target.dataset.spotlightId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target && target.dataset && target.dataset.spotlightId) {
|
|
||||||
return target.dataset.spotlightId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spotlight Focus 추적 로그 [251115]
|
// Spotlight Focus 추적 로그 [251115]
|
||||||
// DOM 이벤트 리스너로 대체
|
// DOM 이벤트 리스너로 대체
|
||||||
@@ -448,7 +426,7 @@ const resolveSpotlightIdFromEvent = (event) => {
|
|||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
function AppBase(props) {
|
function AppBase(_props /* eslint-disable-line no-unused-vars */) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const httpHeader = useSelector((state) => state.common.httpHeader);
|
const httpHeader = useSelector((state) => state.common.httpHeader);
|
||||||
const httpHeaderRef = useRef(httpHeader);
|
const httpHeaderRef = useRef(httpHeader);
|
||||||
@@ -650,7 +628,7 @@ function AppBase(props) {
|
|||||||
clearLaunchParams();
|
clearLaunchParams();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRelaunchEvent = useCallback(() => {
|
const handleRelaunchEvent = useCallback(() => {
|
||||||
@@ -704,7 +682,7 @@ function AppBase(props) {
|
|||||||
if (typeof window === 'object' && window.PalmSystem) {
|
if (typeof window === 'object' && window.PalmSystem) {
|
||||||
window.PalmSystem.activate();
|
window.PalmSystem.activate();
|
||||||
}
|
}
|
||||||
}, [initService, introTermsAgreeRef, dispatch]);
|
}, [initService, introTermsAgreeRef]);
|
||||||
|
|
||||||
const visibilityChanged = useCallback(() => {
|
const visibilityChanged = useCallback(() => {
|
||||||
// console.log('document is hidden', document.hidden);
|
// console.log('document is hidden', document.hidden);
|
||||||
@@ -748,7 +726,7 @@ function AppBase(props) {
|
|||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const keyDownEvent = (event) => {
|
const keyDownEvent = (_event /* eslint-disable-line no-unused-vars */) => {
|
||||||
dispatch(changeAppStatus({ cursorVisible: false }));
|
dispatch(changeAppStatus({ cursorVisible: false }));
|
||||||
Spotlight.setPointerMode(false);
|
Spotlight.setPointerMode(false);
|
||||||
};
|
};
|
||||||
@@ -757,7 +735,7 @@ function AppBase(props) {
|
|||||||
let lastMoveTime = 0;
|
let lastMoveTime = 0;
|
||||||
const THROTTLE_MS = 100;
|
const THROTTLE_MS = 100;
|
||||||
|
|
||||||
const mouseMoveEvent = (event) => {
|
const mouseMoveEvent = (_event /* eslint-disable-line no-unused-vars */) => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now - lastMoveTime < THROTTLE_MS) {
|
if (now - lastMoveTime < THROTTLE_MS) {
|
||||||
// throttle 기간 내에는 hideCursor만 재시작
|
// throttle 기간 내에는 hideCursor만 재시작
|
||||||
@@ -810,9 +788,7 @@ function AppBase(props) {
|
|||||||
let userDataChanged = false;
|
let userDataChanged = false;
|
||||||
if (JSON.stringify(loginUserDataRef.current) !== JSON.stringify(loginUserData)) {
|
if (JSON.stringify(loginUserDataRef.current) !== JSON.stringify(loginUserData)) {
|
||||||
userDataChanged = true;
|
userDataChanged = true;
|
||||||
}
|
} else if (userDataChanged || httpHeaderRef.current === null) {
|
||||||
if (!httpHeader || !deviceId) {
|
|
||||||
} else if (userDataChanged || httpHeaderRef.current === null) {
|
|
||||||
//계정정보 변경시 또는 초기 로딩시
|
//계정정보 변경시 또는 초기 로딩시
|
||||||
if (!httpHeader) {
|
if (!httpHeader) {
|
||||||
dispatch(
|
dispatch(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useDispatch } from "react-redux";
|
|
||||||
import { updateHomeInfo } from "../actions/homeActions";
|
import { updateHomeInfo } from "../actions/homeActions";
|
||||||
import { pushPanel } from "../actions/panelActions";
|
import { pushPanel } from "../actions/panelActions";
|
||||||
import {
|
import {
|
||||||
@@ -11,7 +11,7 @@ import { SpotlightIds } from "../utils/SpotlightIds";
|
|||||||
import { sendLogTotalRecommend } from "../actions/logActions";
|
import { sendLogTotalRecommend } from "../actions/logActions";
|
||||||
|
|
||||||
//V2_진입경로코드_진입경로명_MT_노출순번
|
//V2_진입경로코드_진입경로명_MT_노출순번
|
||||||
export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
export const handleDeepLink = (contentTarget) => (dispatch, _getState) => {
|
||||||
console.log("[handleDeepLink] ~ contentTarget: ", contentTarget);
|
console.log("[handleDeepLink] ~ contentTarget: ", contentTarget);
|
||||||
let linkTpCd; // 진입경로코드
|
let linkTpCd; // 진입경로코드
|
||||||
let linkTpNm; // 진입경로명
|
let linkTpNm; // 진입경로명
|
||||||
@@ -21,7 +21,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
let curationId; // 큐레이션아이디
|
let curationId; // 큐레이션아이디
|
||||||
let showId; // 방송아이디
|
let showId; // 방송아이디
|
||||||
let chanId; // 채널아이디
|
let chanId; // 채널아이디
|
||||||
let expsOrd; // 노출순번
|
|
||||||
let grNumber; // 그룹번호
|
let grNumber; // 그룹번호
|
||||||
let evntId; // 이벤트아이디
|
let evntId; // 이벤트아이디
|
||||||
let lgCatCd; // LG카테고리Code
|
let lgCatCd; // LG카테고리Code
|
||||||
@@ -65,7 +64,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
// V3_진입경로코드_진입경로명_PD_파트너아이디_상품아이디_노출순번_큐레이션아이디
|
// V3_진입경로코드_진입경로명_PD_파트너아이디_상품아이디_노출순번_큐레이션아이디
|
||||||
patnrId = tokens[4]; // 파트너아이디
|
patnrId = tokens[4]; // 파트너아이디
|
||||||
prdtId = tokens[5]; // 상품아이디
|
prdtId = tokens[5]; // 상품아이디
|
||||||
expsOrd = tokens[6]; // 노출순번
|
|
||||||
curationId = tokens[7]; // 큐레이션아이디
|
curationId = tokens[7]; // 큐레이션아이디
|
||||||
panelName = panel_names.DETAIL_PANEL;
|
panelName = panel_names.DETAIL_PANEL;
|
||||||
deeplinkPanel = "Product Detaoil";
|
deeplinkPanel = "Product Detaoil";
|
||||||
@@ -81,7 +79,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
// V3_진입경로코드_진입경로명_LS_파트너아이디_채널아이디_노출순번_큐레이션아이디
|
// V3_진입경로코드_진입경로명_LS_파트너아이디_채널아이디_노출순번_큐레이션아이디
|
||||||
patnrId = tokens[4]; // 파트너아이디
|
patnrId = tokens[4]; // 파트너아이디
|
||||||
chanId = tokens[5]; // 채널아이디
|
chanId = tokens[5]; // 채널아이디
|
||||||
expsOrd = tokens[6]; // 노출순번
|
|
||||||
curationId = tokens[7]; // 큐레이션아이디
|
curationId = tokens[7]; // 큐레이션아이디
|
||||||
panelName = panel_names.PLAYER_PANEL;
|
panelName = panel_names.PLAYER_PANEL;
|
||||||
deeplinkPanel = "Live Show";
|
deeplinkPanel = "Live Show";
|
||||||
@@ -98,7 +95,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
// V3_진입경로코드_진입경로명_VS_파트너아이디_방송아이디_노출순번_큐레이션아이디
|
// V3_진입경로코드_진입경로명_VS_파트너아이디_방송아이디_노출순번_큐레이션아이디
|
||||||
patnrId = tokens[4]; // 파트너아이디
|
patnrId = tokens[4]; // 파트너아이디
|
||||||
showId = tokens[5]; // 방송아이디
|
showId = tokens[5]; // 방송아이디
|
||||||
expsOrd = tokens[6]; // 노출순번
|
|
||||||
curationId = tokens[7]; // 큐레이션아이디
|
curationId = tokens[7]; // 큐레이션아이디
|
||||||
panelName = panel_names.PLAYER_PANEL;
|
panelName = panel_names.PLAYER_PANEL;
|
||||||
deeplinkPanel = "VOD Show";
|
deeplinkPanel = "VOD Show";
|
||||||
@@ -119,7 +115,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
patnrId = tokens[4]; // 파트너아이디
|
patnrId = tokens[4]; // 파트너아이디
|
||||||
curationId = tokens[5]; // 큐레이션아이디\
|
curationId = tokens[5]; // 큐레이션아이디\
|
||||||
prdtId = tokens[6]; // 상품아이디
|
prdtId = tokens[6]; // 상품아이디
|
||||||
expsOrd = tokens[7]; // 노출순번
|
|
||||||
grNumber = tokens[8]; // 그룹번호
|
grNumber = tokens[8]; // 그룹번호
|
||||||
panelName = panel_names.DETAIL_PANEL;
|
panelName = panel_names.DETAIL_PANEL;
|
||||||
deeplinkPanel = "Theme Detail";
|
deeplinkPanel = "Theme Detail";
|
||||||
@@ -140,7 +135,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
|
|
||||||
patnrId = tokens[4]; // 파트너아이디
|
patnrId = tokens[4]; // 파트너아이디
|
||||||
curationId = tokens[5]; // 큐레이션아이디
|
curationId = tokens[5]; // 큐레이션아이디
|
||||||
expsOrd = tokens[6]; // 노출순번
|
|
||||||
panelName = panel_names.DETAIL_PANEL;
|
panelName = panel_names.DETAIL_PANEL;
|
||||||
deeplinkPanel = "Hotel Detail";
|
deeplinkPanel = "Hotel Detail";
|
||||||
panelInfo = {
|
panelInfo = {
|
||||||
@@ -157,7 +151,6 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
|
|||||||
|
|
||||||
patnrId = tokens[4]; // 파트너아이디
|
patnrId = tokens[4]; // 파트너아이디
|
||||||
curationId = tokens[5]; // 큐레이션아이디
|
curationId = tokens[5]; // 큐레이션아이디
|
||||||
expsOrd = tokens[6]; // 노출순번
|
|
||||||
panelName = panel_names.HOT_PICKS_PANEL;
|
panelName = panel_names.HOT_PICKS_PANEL;
|
||||||
deeplinkPanel = "Hot Picks";
|
deeplinkPanel = "Hot Picks";
|
||||||
panelInfo = {
|
panelInfo = {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
export const addMainIndex = (index) => ({
|
export const addMainIndex = (index) => ({
|
||||||
type: types.ADD_MAIN_INDEX,
|
type: types.ADD_MAIN_INDEX,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// IF-LGSP-328 : 회원 Billing Address 조회
|
// IF-LGSP-328 : 회원 Billing Address 조회
|
||||||
export const getMyInfoBillingSearch = (props) => (dispatch, getState) => {
|
export const getMyInfoBillingSearch = (props) => (dispatch, getState) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// Featured Brands 정보 조회 IF-LGSP-304
|
// Featured Brands 정보 조회 IF-LGSP-304
|
||||||
export const getBrandList = () => (dispatch, getState) => {
|
export const getBrandList = () => (dispatch, getState) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// 회원 주문 취소/반품/교환 사유 조회 (IF-LGSP-347)
|
// 회원 주문 취소/반품/교환 사유 조회 (IF-LGSP-347)
|
||||||
export const getMyinfoOrderCancelColumnsSearch = (params, callback) => (dispatch, getState) => {
|
export const getMyinfoOrderCancelColumnsSearch = (params, callback) => (dispatch, getState) => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// 회원의 등록 카드 정보 조회 IF-LGSP-332
|
// 회원의 등록 카드 정보 조회 IF-LGSP-332
|
||||||
export const getMyInfoCardSearch = (props) => (dispatch, getState) => {
|
export const getMyInfoCardSearch = (props) => (dispatch, getState) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// 회원 체크아웃 정보 조회 IF-LGSP-345
|
// 회원 체크아웃 정보 조회 IF-LGSP-345
|
||||||
export const getMyInfoCheckoutInfo = (props, callback) => (dispatch, getState) => {
|
export const getMyInfoCheckoutInfo = (props, callback) => (dispatch, getState) => {
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import Spotlight from '@enact/spotlight';
|
|||||||
import appinfo from '../../webos-meta/appinfo.json';
|
import appinfo from '../../webos-meta/appinfo.json';
|
||||||
import appinfo35 from '../../webos-meta/appinfo35.json';
|
import appinfo35 from '../../webos-meta/appinfo35.json';
|
||||||
import appinfo79 from '../../webos-meta/appinfo79.json';
|
import appinfo79 from '../../webos-meta/appinfo79.json';
|
||||||
import { handleBypassLink } from '../App/bypassLinkHandler';
|
|
||||||
import * as lunaSend from '../lunaSend';
|
import * as lunaSend from '../lunaSend';
|
||||||
import { initialLocalSettings } from '../reducers/localSettingsReducer';
|
|
||||||
import * as Config from '../utils/Config';
|
import * as Config from '../utils/Config';
|
||||||
import * as HelperMethods from '../utils/helperMethods';
|
import * as HelperMethods from '../utils/helperMethods';
|
||||||
import { types } from './actionTypes';
|
import { types } from './actionTypes';
|
||||||
@@ -17,7 +15,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
// =======
|
// =======
|
||||||
// import appinfo from "../../webos-meta/appinfo.json";
|
// import appinfo from "../../webos-meta/appinfo.json";
|
||||||
// import appinfo35 from "../../webos-meta/appinfo35.json";
|
// import appinfo35 from "../../webos-meta/appinfo35.json";
|
||||||
@@ -94,7 +92,7 @@ export const toggleOptionalTermsConfirm = (selected) => ({
|
|||||||
payload: selected,
|
payload: selected,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setExitApp = () => (dispatch, getState) => {
|
export const setExitApp = () => (dispatch) => {
|
||||||
dispatch({ type: types.SET_EXIT_APP });
|
dispatch({ type: types.SET_EXIT_APP });
|
||||||
|
|
||||||
dlog('Exiting App...');
|
dlog('Exiting App...');
|
||||||
@@ -116,7 +114,7 @@ export const loadingComplete = (status) => ({
|
|||||||
payload: status,
|
payload: status,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const alertToast = (payload) => (dispatch, getState) => {
|
export const alertToast = (payload) => (dispatch) => {
|
||||||
if (typeof window === 'object' && !window.PalmSystem) {
|
if (typeof window === 'object' && !window.PalmSystem) {
|
||||||
dispatch(changeAppStatus({ toast: true, toastText: payload }));
|
dispatch(changeAppStatus({ toast: true, toastText: payload }));
|
||||||
} else {
|
} else {
|
||||||
@@ -124,13 +122,13 @@ export const alertToast = (payload) => (dispatch, getState) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSystemSettings = () => (dispatch, getState) => {
|
export const getSystemSettings = () => (dispatch) => {
|
||||||
dlog('getSystemSettings ');
|
dlog('getSystemSettings ');
|
||||||
lunaSend.getSystemSettings(
|
lunaSend.getSystemSettings(
|
||||||
{ category: 'caption', keys: ['captionEnable'] },
|
{ category: 'caption', keys: ['captionEnable'] },
|
||||||
{
|
{
|
||||||
onSuccess: (res) => {},
|
onSuccess: () => {},
|
||||||
onFailure: (err) => {},
|
onFailure: () => {},
|
||||||
onComplete: (res) => {
|
onComplete: (res) => {
|
||||||
dlog('getSystemSettings onComplete', res);
|
dlog('getSystemSettings onComplete', res);
|
||||||
if (res && res.settings) {
|
if (res && res.settings) {
|
||||||
@@ -148,7 +146,7 @@ export const getSystemSettings = () => (dispatch, getState) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getHttpHeaderForServiceRequest = (onComplete) => (dispatch, getState) => {
|
export const getHttpHeaderForServiceRequest = () => (dispatch, getState) => {
|
||||||
dlog('getHttpHeaderForServiceRequest ');
|
dlog('getHttpHeaderForServiceRequest ');
|
||||||
const { serverType, ricCodeSetting, languageSetting } = getState().localSettings;
|
const { serverType, ricCodeSetting, languageSetting } = getState().localSettings;
|
||||||
lunaSend.getHttpHeaderForServiceRequest({
|
lunaSend.getHttpHeaderForServiceRequest({
|
||||||
@@ -267,10 +265,9 @@ export const getHttpHeaderForServiceRequest = (onComplete) => (dispatch, getStat
|
|||||||
const mbrNo = res['X-User-Number'];
|
const mbrNo = res['X-User-Number'];
|
||||||
|
|
||||||
lunaSend.getLoginUserData(parameters, {
|
lunaSend.getLoginUserData(parameters, {
|
||||||
onSuccess: (res) => {
|
onSuccess: (loginRes) => {
|
||||||
const userId = res.id ?? '';
|
const userId = loginRes.id ?? '';
|
||||||
const userNumber = res.lastSignInUserNo;
|
const profileNick = loginRes.profileNick || userId.split('@')[0];
|
||||||
const profileNick = res.profileNick || userId.split('@')[0];
|
|
||||||
dispatch(
|
dispatch(
|
||||||
getLoginUserData({
|
getLoginUserData({
|
||||||
userId,
|
userId,
|
||||||
@@ -288,7 +285,7 @@ export const getHttpHeaderForServiceRequest = (onComplete) => (dispatch, getStat
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDeviceId = (onComplete) => (dispatch, getState) => {
|
export const getDeviceId = (onComplete) => (dispatch) => {
|
||||||
lunaSend.getDeviceId(
|
lunaSend.getDeviceId(
|
||||||
{ idType: ['LGUDID'] },
|
{ idType: ['LGUDID'] },
|
||||||
{
|
{
|
||||||
@@ -466,7 +463,7 @@ export const setFocus = (spotlightId) => ({
|
|||||||
payload: spotlightId,
|
payload: spotlightId,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const focusElement = (spotlightId) => (dispatch, getState) => {
|
export const focusElement = (spotlightId) => (dispatch) => {
|
||||||
dispatch(setFocus(spotlightId));
|
dispatch(setFocus(spotlightId));
|
||||||
|
|
||||||
if (typeof window === 'object') {
|
if (typeof window === 'object') {
|
||||||
@@ -488,7 +485,7 @@ export const cancelFocusElement = () => () => {
|
|||||||
let broadcastTimer = null;
|
let broadcastTimer = null;
|
||||||
export const sendBroadCast =
|
export const sendBroadCast =
|
||||||
({ type, moreInfo }) =>
|
({ type, moreInfo }) =>
|
||||||
(dispatch, getState) => {
|
(dispatch) => {
|
||||||
clearTimeout(broadcastTimer);
|
clearTimeout(broadcastTimer);
|
||||||
dispatch(changeBroadcastEvent({ type, moreInfo }));
|
dispatch(changeBroadcastEvent({ type, moreInfo }));
|
||||||
broadcastTimer = setTimeout(() => {
|
broadcastTimer = setTimeout(() => {
|
||||||
@@ -545,7 +542,7 @@ export const addReservation = (data) => (dispatch) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteReservationCallback = (scheduleIdList) => (dispatch) => {
|
export const deleteReservationCallback = (scheduleIdList) => () => {
|
||||||
lunaSend.deleteReservationCallback(scheduleIdList, {
|
lunaSend.deleteReservationCallback(scheduleIdList, {
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
// dispatch(alertToast("success" + JSON.stringify(res)));
|
// dispatch(alertToast("success" + JSON.stringify(res)));
|
||||||
@@ -636,8 +633,8 @@ export const showError =
|
|||||||
export const deleteOldDb8Datas = () => (dispatch) => {
|
export const deleteOldDb8Datas = () => (dispatch) => {
|
||||||
for (let i = 1; i < 10; i++) {
|
for (let i = 1; i < 10; i++) {
|
||||||
lunaSend.deleteOldDb8(i, {
|
lunaSend.deleteOldDb8(i, {
|
||||||
onSuccess: (res) => {},
|
onSuccess: () => {},
|
||||||
onFailure: (err) => {},
|
onFailure: () => {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dispatch(changeLocalSettings({ oldDb8Deleted: true }));
|
dispatch(changeLocalSettings({ oldDb8Deleted: true }));
|
||||||
@@ -683,7 +680,7 @@ let updateNetworkStateJob = new Job((dispatch, connected) => {
|
|||||||
dispatch(changeAppStatus({ isInternetConnected: connected }));
|
dispatch(changeAppStatus({ isInternetConnected: connected }));
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getConnectionStatus = () => (dispatch, getState) => {
|
export const getConnectionStatus = () => (dispatch) => {
|
||||||
lunaSend.getConnectionStatus({
|
lunaSend.getConnectionStatus({
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
dlog('lunasend getConnectionStatus', res);
|
dlog('lunasend getConnectionStatus', res);
|
||||||
@@ -712,7 +709,7 @@ export const getConnectionStatus = () => (dispatch, getState) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// macAddress
|
// macAddress
|
||||||
export const getConnectionInfo = () => (dispatch, getState) => {
|
export const getConnectionInfo = () => (dispatch) => {
|
||||||
lunaSend.getConnectionInfo({
|
lunaSend.getConnectionInfo({
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
dlog('lunasend getConnectionStatus', res);
|
dlog('lunasend getConnectionStatus', res);
|
||||||
@@ -734,7 +731,7 @@ export const getConnectionInfo = () => (dispatch, getState) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const disableNotification = () => (dispatch, getState) => {
|
export const disableNotification = () => {
|
||||||
lunaSend.disableNotification({
|
lunaSend.disableNotification({
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
dlog('lunasend disable notification success', res);
|
dlog('lunasend disable notification success', res);
|
||||||
@@ -748,7 +745,7 @@ export const disableNotification = () => (dispatch, getState) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const enableNotification = () => (dispatch, getState) => {
|
export const enableNotification = () => {
|
||||||
lunaSend.enableNotification({
|
lunaSend.enableNotification({
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
dlog('lunasend enable notification success', res);
|
dlog('lunasend enable notification success', res);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const convertPdfToImage =
|
|||||||
const timeoutError = new Error(
|
const timeoutError = new Error(
|
||||||
`Conversion timeout after ${timeout}ms (attempt ${attempts})`
|
`Conversion timeout after ${timeout}ms (attempt ${attempts})`
|
||||||
);
|
);
|
||||||
dwarn(`⏱️ [EnergyLabel] Timeout on attempt ${attempts}:`, timeoutError.message);
|
void dwarn(`⏱️ [EnergyLabel] Timeout on attempt ${attempts}:`, timeoutError.message);
|
||||||
|
|
||||||
// 재시도 가능한 경우
|
// 재시도 가능한 경우
|
||||||
if (attempts < maxRetries + 1) {
|
if (attempts < maxRetries + 1) {
|
||||||
@@ -39,7 +39,7 @@ export const convertPdfToImage =
|
|||||||
attemptConversion();
|
attemptConversion();
|
||||||
} else {
|
} else {
|
||||||
// 최종 실패
|
// 최종 실패
|
||||||
derror(`❌ [EnergyLabel] Final failure after ${attempts} attempts:`, pdfUrl);
|
void derror(`❌ [EnergyLabel] Final failure after ${attempts} attempts:`, pdfUrl);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CONVERT_PDF_TO_IMAGE_FAILURE,
|
type: types.CONVERT_PDF_TO_IMAGE_FAILURE,
|
||||||
payload: { pdfUrl, error: timeoutError },
|
payload: { pdfUrl, error: timeoutError },
|
||||||
@@ -64,17 +64,14 @@ export const convertPdfToImage =
|
|||||||
|
|
||||||
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}`);
|
||||||
dwarn(`⚠️ [EnergyLabel] API returned error on attempt ${attempts}:`, retCode);
|
void dwarn(`⚠️ [EnergyLabel] API returned error on attempt ${attempts}:`, retCode);
|
||||||
|
|
||||||
// retCode 에러도 재시도
|
// retCode 에러도 재시도
|
||||||
if (attempts < maxRetries + 1) {
|
if (attempts < maxRetries + 1) {
|
||||||
dlog(`🔄 [EnergyLabel] Retrying due to API error... (${attempts}/${maxRetries + 1})`);
|
void dlog(`🔄 [EnergyLabel] Retrying due to API error... (${attempts}/${maxRetries + 1})`);
|
||||||
attemptConversion();
|
attemptConversion();
|
||||||
} else {
|
} else {
|
||||||
derror(
|
void derror(`❌ [EnergyLabel] Final failure after ${attempts} attempts (API error):`, pdfUrl);
|
||||||
`❌ [EnergyLabel] Final failure after ${attempts} attempts (API error):`,
|
|
||||||
pdfUrl
|
|
||||||
);
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CONVERT_PDF_TO_IMAGE_FAILURE,
|
type: types.CONVERT_PDF_TO_IMAGE_FAILURE,
|
||||||
payload: { pdfUrl, error },
|
payload: { pdfUrl, error },
|
||||||
@@ -111,7 +108,7 @@ export const convertPdfToImage =
|
|||||||
imageUrl = URL.createObjectURL(blob);
|
imageUrl = URL.createObjectURL(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
dlog(`✅ [EnergyLabel] Conversion successful on attempt ${attempts}:`, pdfUrl);
|
void dlog(`✅ [EnergyLabel] Conversion successful on attempt ${attempts}:`, pdfUrl);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CONVERT_PDF_TO_IMAGE_SUCCESS,
|
type: types.CONVERT_PDF_TO_IMAGE_SUCCESS,
|
||||||
payload: { pdfUrl, imageUrl },
|
payload: { pdfUrl, imageUrl },
|
||||||
@@ -119,16 +116,16 @@ export const convertPdfToImage =
|
|||||||
|
|
||||||
callback && callback(null, imageUrl);
|
callback && callback(null, imageUrl);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
derror(`❌ [EnergyLabel] Image creation failed on attempt ${attempts}:`, error);
|
void derror(`❌ [EnergyLabel] Image creation failed on attempt ${attempts}:`, error);
|
||||||
|
|
||||||
// 이미지 생성 실패도 재시도
|
// 이미지 생성 실패도 재시도
|
||||||
if (attempts < maxRetries + 1) {
|
if (attempts < maxRetries + 1) {
|
||||||
dlog(
|
void dlog(
|
||||||
`🔄 [EnergyLabel] Retrying due to image creation error... (${attempts}/${maxRetries + 1})`
|
`🔄 [EnergyLabel] Retrying due to image creation error... (${attempts}/${maxRetries + 1})`
|
||||||
);
|
);
|
||||||
attemptConversion();
|
attemptConversion();
|
||||||
} else {
|
} else {
|
||||||
derror(
|
void derror(
|
||||||
`❌ [EnergyLabel] Final failure after ${attempts} attempts (image error):`,
|
`❌ [EnergyLabel] Final failure after ${attempts} attempts (image error):`,
|
||||||
pdfUrl
|
pdfUrl
|
||||||
);
|
);
|
||||||
@@ -147,14 +144,14 @@ export const convertPdfToImage =
|
|||||||
timeoutId = null;
|
timeoutId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwarn(`⚠️ [EnergyLabel] Network error on attempt ${attempts}:`, error.message);
|
void dwarn(`⚠️ [EnergyLabel] Network error on attempt ${attempts}:`, error.message);
|
||||||
|
|
||||||
// 네트워크 에러도 재시도
|
// 네트워크 에러도 재시도
|
||||||
if (attempts < maxRetries + 1) {
|
if (attempts < maxRetries + 1) {
|
||||||
dlog(`🔄 [EnergyLabel] Retrying due to network error... (${attempts}/${maxRetries + 1})`);
|
void dlog(`🔄 [EnergyLabel] Retrying due to network error... (${attempts}/${maxRetries + 1})`);
|
||||||
attemptConversion();
|
attemptConversion();
|
||||||
} else {
|
} else {
|
||||||
derror(
|
void derror(
|
||||||
`❌ [EnergyLabel] Final failure after ${attempts} attempts (network error):`,
|
`❌ [EnergyLabel] Final failure after ${attempts} attempts (network error):`,
|
||||||
pdfUrl
|
pdfUrl
|
||||||
);
|
);
|
||||||
@@ -188,7 +185,7 @@ export const convertPdfToImage =
|
|||||||
* @param {Array<string>} pdfUrls - 변환할 PDF URL 배열
|
* @param {Array<string>} pdfUrls - 변환할 PDF URL 배열
|
||||||
* @param {function} callback - 완료 후 실행할 콜백 (errors, results)
|
* @param {function} callback - 완료 후 실행할 콜백 (errors, results)
|
||||||
*/
|
*/
|
||||||
export const convertMultiplePdfs = (pdfUrls, callback) => async (dispatch, getState) => {
|
export const convertMultiplePdfs = (pdfUrls, callback) => async (dispatch) => {
|
||||||
if (!pdfUrls || pdfUrls.length === 0) {
|
if (!pdfUrls || pdfUrls.length === 0) {
|
||||||
callback && callback(null, []);
|
callback && callback(null, []);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { createDebugHelpers } from '../utils/debug';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// IF-LGSP-339 : 회원 다운로드 쿠폰 정보 조회
|
// IF-LGSP-339 : 회원 다운로드 쿠폰 정보 조회
|
||||||
export const getProductCouponInfo = (props) => (dispatch, getState) => {
|
export const getProductCouponInfo = (props) => (dispatch, getState) => {
|
||||||
|
|||||||
@@ -348,8 +348,14 @@ export const TAxiosAdvancedPromise = (
|
|||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
console.error(`TAxiosPromise error on attempt ${attempts} for ${baseUrl}:`, error);
|
console.error(`TAxiosPromise error on attempt ${attempts} for ${baseUrl}:`, error);
|
||||||
|
|
||||||
|
// Check if the error is due to token expiration
|
||||||
|
// TAxios already handles token refresh and queueing for these codes (401, 402, 501)
|
||||||
|
// So we should NOT retry immediately in this loop, but let TAxios handle it.
|
||||||
|
const retCode = error?.data?.retCode;
|
||||||
|
const isTokenError = retCode === 401 || retCode === 402 || retCode === 501;
|
||||||
|
|
||||||
// 재시도 로직
|
// 재시도 로직
|
||||||
if (attempts < maxAttempts) {
|
if (attempts < maxAttempts && !isTokenError) {
|
||||||
console.log(`Retrying in ${retryDelay}ms... (${attempts}/${maxAttempts})`);
|
console.log(`Retrying in ${retryDelay}ms... (${attempts}/${maxAttempts})`);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
attemptRequest();
|
attemptRequest();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
margin-left: 130px;
|
margin-left: 130px;
|
||||||
margin-right: 130px;
|
margin-right: 130px;
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
width: 1540px;
|
|
||||||
height: 6px;
|
height: 6px;
|
||||||
|
|
||||||
&.videoVertical {
|
&.videoVertical {
|
||||||
@@ -31,10 +30,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mediaSlider {
|
.mediaSlider {
|
||||||
margin: 0 @slider-padding-h;
|
margin: 0 0 0 @slider-padding-h;
|
||||||
padding: @slider-padding-v 0;
|
padding: @slider-padding-v 0;
|
||||||
height: @sand-mediaplayer-slider-height;
|
height: @sand-mediaplayer-slider-height;
|
||||||
right: 154px;
|
right: 154px;
|
||||||
|
width: 1466px;
|
||||||
// Add a tap area that extends to the edges of the screen, to make the slider more accessible
|
// Add a tap area that extends to the edges of the screen, to make the slider more accessible
|
||||||
&::before {
|
&::before {
|
||||||
content: "";
|
content: "";
|
||||||
|
|||||||
@@ -7,22 +7,28 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
font-family: @baseFont;
|
font-family: @baseFont;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: 22px;
|
right: 90px;
|
||||||
right: 30px;
|
bottom: -5px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
letter-spacing: -1px;
|
||||||
.separator {
|
.separator {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 110px;
|
right: 105px;
|
||||||
|
bottom: -5px;
|
||||||
}
|
}
|
||||||
.currentTime {
|
.currentTime {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 140px;
|
right: 130px;
|
||||||
|
bottom: -5px;
|
||||||
|
}
|
||||||
|
.totalTime {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -5px;
|
||||||
|
right:0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,8 +172,23 @@ export default function TabLayout({ topPanelName, onTabActivated, panelInfo }) {
|
|||||||
break;
|
break;
|
||||||
//브랜드
|
//브랜드
|
||||||
case 10300:
|
case 10300:
|
||||||
result =
|
result = [
|
||||||
data?.shortFeaturedBrands?.map((item) => ({
|
// NBCU 브랜드 (하드코딩)
|
||||||
|
{
|
||||||
|
icons: FeaturedBrandIcon,
|
||||||
|
id: 'nbcu-brand',
|
||||||
|
path: 'assets/images/featuredBrands/nbcu.svg',
|
||||||
|
patncNm: 'NBCU',
|
||||||
|
spotlightId: 'spotlight_featuredbrand_nbcu',
|
||||||
|
target: [
|
||||||
|
{
|
||||||
|
name: panel_names.FEATURED_BRANDS_PANEL,
|
||||||
|
panelInfo: { from: 'gnb', patnrId: 'NBCU' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// API에서 가져온 기존 브랜드들
|
||||||
|
...(data?.shortFeaturedBrands?.map((item) => ({
|
||||||
icons: FeaturedBrandIcon,
|
icons: FeaturedBrandIcon,
|
||||||
id: item.patnrId,
|
id: item.patnrId,
|
||||||
path: item.patncLogoPath,
|
path: item.patncLogoPath,
|
||||||
@@ -185,7 +200,8 @@ export default function TabLayout({ topPanelName, onTabActivated, panelInfo }) {
|
|||||||
panelInfo: { from: 'gnb', patnrId: item.patnrId },
|
panelInfo: { from: 'gnb', patnrId: item.patnrId },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})) || [];
|
})) || []),
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
case 10600:
|
case 10600:
|
||||||
@@ -304,6 +320,7 @@ export default function TabLayout({ topPanelName, onTabActivated, panelInfo }) {
|
|||||||
title: item.title,
|
title: item.title,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
patncNm: item.patncNm,
|
patncNm: item.patncNm,
|
||||||
|
icons: item.icons,
|
||||||
target: item.target,
|
target: item.target,
|
||||||
spotlightId: `secondDepth-${item.id}`,
|
spotlightId: `secondDepth-${item.id}`,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { scaleW } from "../../../utils/helperMethods";
|
||||||
|
import useConvertThemeColor from "./useConvertThemeColor";
|
||||||
|
|
||||||
|
const NbcuIcon = ({ iconType = "normal" }) => {
|
||||||
|
const themeColor = useConvertThemeColor({ iconType });
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={scaleW(48)}
|
||||||
|
height={scaleW(48)}
|
||||||
|
viewBox="0 0 48 48"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle cx="24" cy="24" r="22" fill={themeColor} opacity="0.1" stroke={themeColor} strokeWidth="0.5" />
|
||||||
|
<text
|
||||||
|
x="24"
|
||||||
|
y="32"
|
||||||
|
textAnchor="middle"
|
||||||
|
fill={themeColor}
|
||||||
|
fontSize="18"
|
||||||
|
fontWeight="bold"
|
||||||
|
fontFamily="Arial, sans-serif"
|
||||||
|
>
|
||||||
|
NBC
|
||||||
|
</text>
|
||||||
|
<text
|
||||||
|
x="24"
|
||||||
|
y="40"
|
||||||
|
textAnchor="middle"
|
||||||
|
fill={themeColor}
|
||||||
|
fontSize="10"
|
||||||
|
fontFamily="Arial, sans-serif"
|
||||||
|
>
|
||||||
|
U
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NbcuIcon;
|
||||||
@@ -776,6 +776,7 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
this.sliderKnobProportion = 0;
|
this.sliderKnobProportion = 0;
|
||||||
this.mediaControlsSpotlightId = props.spotlightId + '_mediaControls';
|
this.mediaControlsSpotlightId = props.spotlightId + '_mediaControls';
|
||||||
this.jumpButtonPressed = null;
|
this.jumpButtonPressed = null;
|
||||||
|
this.focusTimer = null;
|
||||||
|
|
||||||
// Re-render-necessary State
|
// Re-render-necessary State
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -1038,6 +1039,7 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
this.stopDelayedTitleHide();
|
this.stopDelayedTitleHide();
|
||||||
this.stopDelayedFeedbackHide();
|
this.stopDelayedFeedbackHide();
|
||||||
this.stopDelayedMiniFeedbackHide();
|
this.stopDelayedMiniFeedbackHide();
|
||||||
|
if (this.focusTimer) clearTimeout(this.focusTimer);
|
||||||
this.announceJob.stop();
|
this.announceJob.stop();
|
||||||
this.renderBottomControl.stop();
|
this.renderBottomControl.stop();
|
||||||
this.slider5WayPressJob.stop();
|
this.slider5WayPressJob.stop();
|
||||||
@@ -2603,11 +2605,11 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
this.showControls();
|
this.showControls();
|
||||||
|
|
||||||
if (this.state.lastFocusedTarget) {
|
if (this.state.lastFocusedTarget) {
|
||||||
setTimeout(() => {
|
this.focusTimer = setTimeout(() => {
|
||||||
Spotlight.focus(this.state.lastFocusedTarget);
|
Spotlight.focus(this.state.lastFocusedTarget);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
this.focusTimer = setTimeout(() => {
|
||||||
Spotlight.focus(SpotlightIds.PLAYER_TAB_BUTTON);
|
Spotlight.focus(SpotlightIds.PLAYER_TAB_BUTTON);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -692,10 +692,10 @@
|
|||||||
// display: flex;
|
// display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: 60px;
|
|
||||||
margin-right: 59px;
|
|
||||||
height: 70px;
|
height: 70px;
|
||||||
bottom: -20px;
|
width:1800px;
|
||||||
|
margin-left:60px;
|
||||||
|
bottom:92px;
|
||||||
> *:first-child {
|
> *:first-child {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,19 @@ import {
|
|||||||
getProductCouponSearch,
|
getProductCouponSearch,
|
||||||
getProductCouponTotDownload,
|
getProductCouponTotDownload,
|
||||||
} from '../../../actions/couponActions.js';
|
} from '../../../actions/couponActions.js';
|
||||||
|
import {
|
||||||
|
sendLogDetail,
|
||||||
|
sendLogGNB,
|
||||||
|
sendLogProductDetail,
|
||||||
|
sendLogShopByMobile,
|
||||||
|
sendLogTotalRecommend,
|
||||||
|
} from '../../../actions/logActions';
|
||||||
// import { pushPanel } from '../../../actions/panelActions';
|
// import { pushPanel } from '../../../actions/panelActions';
|
||||||
import {
|
import {
|
||||||
minimizeModalMedia,
|
minimizeModalMedia,
|
||||||
restoreModalMedia,
|
restoreModalMedia,
|
||||||
} from '../../../actions/mediaActions';
|
} from '../../../actions/mediaActions';
|
||||||
|
import { updatePanel } from '../../../actions/panelActions';
|
||||||
import { pauseFullscreenVideo } from '../../../actions/playActions';
|
import { pauseFullscreenVideo } from '../../../actions/playActions';
|
||||||
import { resetShowAllReviews } from '../../../actions/productActions';
|
import { resetShowAllReviews } from '../../../actions/productActions';
|
||||||
import {
|
import {
|
||||||
@@ -59,7 +67,12 @@ import TVirtualGridList
|
|||||||
import useReviews from '../../../hooks/useReviews/useReviews';
|
import useReviews from '../../../hooks/useReviews/useReviews';
|
||||||
import useScrollTo from '../../../hooks/useScrollTo';
|
import useScrollTo from '../../../hooks/useScrollTo';
|
||||||
import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig';
|
import { BUYNOW_CONFIG } from '../../../utils/BuyNowConfig';
|
||||||
import { panel_names } from '../../../utils/Config';
|
import {
|
||||||
|
LOG_CONTEXT_NAME,
|
||||||
|
LOG_MESSAGE_ID,
|
||||||
|
LOG_TP_NO,
|
||||||
|
panel_names,
|
||||||
|
} from '../../../utils/Config';
|
||||||
import * as Config from '../../../utils/Config.js';
|
import * as Config from '../../../utils/Config.js';
|
||||||
import {
|
import {
|
||||||
andThen,
|
andThen,
|
||||||
@@ -76,7 +89,10 @@ import {
|
|||||||
tap,
|
tap,
|
||||||
when,
|
when,
|
||||||
} from '../../../utils/fp';
|
} from '../../../utils/fp';
|
||||||
import { $L } from '../../../utils/helperMethods';
|
import {
|
||||||
|
$L,
|
||||||
|
formatGMTString,
|
||||||
|
} from '../../../utils/helperMethods';
|
||||||
import { SpotlightIds } from '../../../utils/SpotlightIds';
|
import { SpotlightIds } from '../../../utils/SpotlightIds';
|
||||||
import ShowUserReviews from '../../UserReview/ShowUserReviews';
|
import ShowUserReviews from '../../UserReview/ShowUserReviews';
|
||||||
// import CustomScrollbar from '../components/CustomScrollbar/CustomScrollbar';
|
// import CustomScrollbar from '../components/CustomScrollbar/CustomScrollbar';
|
||||||
@@ -242,6 +258,7 @@ export default function ProductAllSection({
|
|||||||
// Redux 상태
|
// Redux 상태
|
||||||
const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion);
|
const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion);
|
||||||
const groupInfos = useSelector((state) => state.product.groupInfo);
|
const groupInfos = useSelector((state) => state.product.groupInfo);
|
||||||
|
const nowMenu = useSelector((state) => state.common.menu.nowMenu);
|
||||||
|
|
||||||
// YouMayLike 데이터는 API 응답 시간이 걸리므로 직접 구독
|
// YouMayLike 데이터는 API 응답 시간이 걸리므로 직접 구독
|
||||||
const youmaylikeData = useSelector((state) => state.main.youmaylikeData);
|
const youmaylikeData = useSelector((state) => state.main.youmaylikeData);
|
||||||
@@ -263,6 +280,18 @@ export default function ProductAllSection({
|
|||||||
const [isShowQRCode, setIsShowQRCode] = useState(true);
|
const [isShowQRCode, setIsShowQRCode] = useState(true);
|
||||||
const timerRef = useRef(null);
|
const timerRef = useRef(null);
|
||||||
|
|
||||||
|
// sendLogGNB용 entryMenu
|
||||||
|
const entryMenuRef = useRef(null);
|
||||||
|
|
||||||
|
// 출처 정보 통합 (향후 확장성 대비)
|
||||||
|
// YouMayLike 상품이 아닐 경우 fromPanel을 초기화하여 오기 방지
|
||||||
|
const fromPanel = useMemo(() => ({
|
||||||
|
fromYouMayLike: panelInfo?.fromPanel?.fromYouMayLike || false,
|
||||||
|
// 향후 다른 출처 플래그들 추가 가능
|
||||||
|
// fromRecommendation: panelInfo?.fromPanel?.fromRecommendation || false,
|
||||||
|
// fromSearch: panelInfo?.fromPanel?.fromSearch || false,
|
||||||
|
}), [panelInfo?.fromPanel?.fromYouMayLike]);
|
||||||
|
|
||||||
//구매 하단 토스트 노출 확인을 위한 용도
|
//구매 하단 토스트 노출 확인을 위한 용도
|
||||||
const [openToast, setOpenToast] = useState(false);
|
const [openToast, setOpenToast] = useState(false);
|
||||||
|
|
||||||
@@ -652,6 +681,116 @@ export default function ProductAllSection({
|
|||||||
dispatch(resetShowAllReviews());
|
dispatch(resetShowAllReviews());
|
||||||
}, []); // 빈 dependency array = 마운트 시에만 실행
|
}, []); // 빈 dependency array = 마운트 시에만 실행
|
||||||
|
|
||||||
|
// 제품 상세 버튼 클릭 핸들러 - Source의 handleIndicatorOptions와 동일한 기능
|
||||||
|
const handleIndicatorOptions = useCallback(() => {
|
||||||
|
if (productData && Object.keys(productData).length > 0) {
|
||||||
|
// sendLogDetail - 제품 상세 버튼 클릭 로깅 (Source와 동일)
|
||||||
|
const detailLogParams = {
|
||||||
|
curationId: productData?.curationId ?? "",
|
||||||
|
curationNm: productData?.curationNm ?? "",
|
||||||
|
inDt: "",
|
||||||
|
linkTpCd: panelInfo?.linkTpCd ?? "",
|
||||||
|
logTpNo: LOG_TP_NO.DETAIL.DETAIL_BUTTON_CLICK,
|
||||||
|
patncNm: productData?.patncNm ?? "",
|
||||||
|
patnrId: productData?.patnrId ?? "",
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(sendLogDetail(detailLogParams));
|
||||||
|
|
||||||
|
// sendLogTotalRecommend - 추천 버튼 클릭 로깅 (Source와 동일)
|
||||||
|
let menuType;
|
||||||
|
if (isTravelProductVisible) {
|
||||||
|
menuType = Config.LOG_MENU.DETAIL_PAGE_TRAVEL_THEME_DETAIL;
|
||||||
|
} else if (isGroupProductVisible) {
|
||||||
|
menuType = Config.LOG_MENU.DETAIL_PAGE_GROUP_DETAIL;
|
||||||
|
} else if (isBillingProductVisible) {
|
||||||
|
menuType = Config.LOG_MENU.DETAIL_PAGE_BILLING_PRODUCT_DETAIL;
|
||||||
|
} else {
|
||||||
|
menuType = Config.LOG_MENU.DETAIL_PAGE_PRODUCT_DETAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(sendLogTotalRecommend({
|
||||||
|
menu: menuType,
|
||||||
|
buttonTitle: "DESCRIPTION",
|
||||||
|
contextName: LOG_CONTEXT_NAME.DETAILPAGE,
|
||||||
|
messageId: LOG_MESSAGE_ID.BUTTONCLICK,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, [productData, panelInfo, isBillingProductVisible, isGroupProductVisible, isTravelProductVisible]);
|
||||||
|
|
||||||
|
// sendLogGNB 로깅 - Source의 DetailPanel 컴포넌트들과 동일한 패턴
|
||||||
|
useEffect(() => {
|
||||||
|
if (!entryMenuRef.current) entryMenuRef.current = nowMenu;
|
||||||
|
|
||||||
|
// BUY NOW 버튼 활성화 상태에 따른 메뉴 결정 (Source SingleProduct vs UnableProduct 패턴)
|
||||||
|
let baseMenu;
|
||||||
|
if (isTravelProductVisible) {
|
||||||
|
baseMenu = Config.LOG_MENU.DETAIL_PAGE_TRAVEL_THEME_DETAIL;
|
||||||
|
} else if (isGroupProductVisible) {
|
||||||
|
baseMenu = Config.LOG_MENU.DETAIL_PAGE_GROUP_DETAIL;
|
||||||
|
} else if (isBillingProductVisible) {
|
||||||
|
// BUY NOW 버튼 활성화 = SingleProduct
|
||||||
|
baseMenu = Config.LOG_MENU.DETAIL_PAGE_BILLING_PRODUCT_DETAIL;
|
||||||
|
} else {
|
||||||
|
// BUY NOW 버튼 비활성화 = UnableProduct
|
||||||
|
baseMenu = Config.LOG_MENU.DETAIL_PAGE_PRODUCT_DETAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// YouMayLike에서 상품 선택 시 메뉴 변경 (Source의 isYouMayLikeOpened와 동일 패턴)
|
||||||
|
const menu = (fromPanel?.fromYouMayLike !== undefined && fromPanel?.fromYouMayLike === true)
|
||||||
|
? `${baseMenu}/${Config.LOG_MENU.DETAIL_PAGE_YOU_MAY_LIKE}`
|
||||||
|
: baseMenu;
|
||||||
|
|
||||||
|
dispatch(sendLogGNB(menu));
|
||||||
|
|
||||||
|
// sendLogGNB 전송 후 플래그 초기화 (1회 사용 후 비활성화)
|
||||||
|
if (fromPanel?.fromYouMayLike === true) {
|
||||||
|
dispatch(updatePanel({
|
||||||
|
name: panel_names.DETAIL_PANEL,
|
||||||
|
panelInfo: {
|
||||||
|
...panelInfo,
|
||||||
|
fromPanel: {
|
||||||
|
fromYouMayLike: false // 플래그 초기화
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, [fromPanel?.fromYouMayLike, isBillingProductVisible, isUnavailableProductVisible, isGroupProductVisible, isTravelProductVisible]); // BUY NOW 상태 변경 시 재실행
|
||||||
|
|
||||||
|
// sendLogProductDetail 로깅 - Source의 productData 변경 감지와 동일한 패턴
|
||||||
|
useEffect(() => {
|
||||||
|
if (productData && Object.keys(productData).length > 0) {
|
||||||
|
const params = {
|
||||||
|
befPrice: productData?.priceInfo?.split("|")[0],
|
||||||
|
curationId: productData?.curationId ?? "",
|
||||||
|
curationNm: productData?.curationNm ?? "",
|
||||||
|
entryMenu: entryMenuRef.current,
|
||||||
|
expsOrd: "1",
|
||||||
|
inDt: formatGMTString(new Date()),
|
||||||
|
lastPrice: productData?.priceInfo?.split("|")[1],
|
||||||
|
lgCatCd: productData?.catCd ?? "",
|
||||||
|
lgCatNm: productData?.catNm ?? "",
|
||||||
|
linkTpCd: panelInfo?.linkTpCd ?? "",
|
||||||
|
logTpNo: isTravelProductVisible
|
||||||
|
? Config.LOG_TP_NO.PRODUCT.TRAVEL_DETAIL
|
||||||
|
: isGroupProductVisible
|
||||||
|
? Config.LOG_TP_NO.PRODUCT.GROUP_DETAIL
|
||||||
|
: isBillingProductVisible
|
||||||
|
? Config.LOG_TP_NO.PRODUCT.BILLING_PRODUCT_DETAIL
|
||||||
|
: Config.LOG_TP_NO.PRODUCT.PRODUCT_DETAIL,
|
||||||
|
patncNm: productData?.patncNm ?? "",
|
||||||
|
patnrId: productData?.patnrId ?? "",
|
||||||
|
prdtId: productData?.prdtId ?? "",
|
||||||
|
prdtNm: productData?.prdtNm ?? "",
|
||||||
|
revwGrd: productData?.revwGrd ?? "",
|
||||||
|
rewdAplyFlag: productData.priceInfo?.split("|")[2],
|
||||||
|
tsvFlag: productData?.todaySpclFlag ?? "",
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => dispatch(sendLogProductDetail(params));
|
||||||
|
}
|
||||||
|
}, [productData, entryMenuRef.current, panelInfo?.linkTpCd, isBillingProductVisible, isGroupProductVisible, isTravelProductVisible]); // productData 변경 시 재실행
|
||||||
|
|
||||||
// [251115] 주석 처리: MediaPanel에서 이미 포커스 이동을 처리하므로
|
// [251115] 주석 처리: MediaPanel에서 이미 포커스 이동을 처리하므로
|
||||||
// ProductAllSection의 자동 포커스는 포커스 탈취를 일으킬 수 있음
|
// ProductAllSection의 자동 포커스는 포커스 탈취를 일으킬 수 있음
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
@@ -674,6 +813,35 @@ export default function ProductAllSection({
|
|||||||
// console.log('[BuyNow] Buy Now button clicked');
|
// console.log('[BuyNow] Buy Now button clicked');
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// 🚀 SingleOption.jsx의 sendLogTotalRecommend 로직 추가
|
||||||
|
if (productData && Object.keys(productData).length > 0) {
|
||||||
|
const { priceInfo, patncNm, prdtId, prdtNm, brndNm, catNm, showId, showNm } = productData;
|
||||||
|
const regularPrice = priceInfo?.split("|")[0];
|
||||||
|
const discountPrice = priceInfo?.split("|")[1];
|
||||||
|
const discountRate = priceInfo?.split("|")[4];
|
||||||
|
|
||||||
|
// Option 정보는 현재 선택된 옵션이 없으므로 기본값 사용
|
||||||
|
const prodOptCval = ""; // 실제로는 선택된 옵션 값이 들어가야 함
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
sendLogTotalRecommend({
|
||||||
|
nowMenu: nowMenu,
|
||||||
|
productId: prdtId,
|
||||||
|
productTitle: prdtNm,
|
||||||
|
partner: patncNm,
|
||||||
|
price: discountRate ? discountPrice : regularPrice,
|
||||||
|
discount: discountRate,
|
||||||
|
brand: brndNm,
|
||||||
|
productOption: prodOptCval,
|
||||||
|
category: catNm,
|
||||||
|
contextName: Config.LOG_CONTEXT_NAME.DETAILPAGE,
|
||||||
|
messageId: Config.LOG_MESSAGE_ID.BUY_NOW,
|
||||||
|
showId: showId ?? "",
|
||||||
|
showNm: showNm ?? "",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// console.log('[ProductAllSection] 🛒 BUY NOW clicked - productData:', {
|
// console.log('[ProductAllSection] 🛒 BUY NOW clicked - productData:', {
|
||||||
// prdtId: productData?.prdtId,
|
// prdtId: productData?.prdtId,
|
||||||
// patnrId: productData?.patnrId,
|
// patnrId: productData?.patnrId,
|
||||||
@@ -705,7 +873,7 @@ export default function ProductAllSection({
|
|||||||
setOpenToast(true);
|
setOpenToast(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dispatch, productData, openToast]
|
[dispatch, productData, openToast, nowMenu]
|
||||||
);
|
);
|
||||||
|
|
||||||
//닫히도록
|
//닫히도록
|
||||||
@@ -926,7 +1094,32 @@ export default function ProductAllSection({
|
|||||||
}, [hasVideo, productVideoVersion]);
|
}, [hasVideo, productVideoVersion]);
|
||||||
|
|
||||||
const handleShopByMobileOpen = useCallback(
|
const handleShopByMobileOpen = useCallback(
|
||||||
pipe(() => true, setMobileSendPopupOpen),
|
pipe(() => {
|
||||||
|
// sendLogShopByMobile - Source와 동일한 로깅 추가
|
||||||
|
if (productData && Object.keys(productData).length > 0) {
|
||||||
|
const { priceInfo, patncNm, patnrId, prdtId, prdtNm, brndNm, catNm } = productData;
|
||||||
|
const regularPrice = priceInfo?.split("|")[0];
|
||||||
|
const discountPrice = priceInfo?.split("|")[1];
|
||||||
|
const discountRate = priceInfo?.split("|")[4];
|
||||||
|
|
||||||
|
const logParams = {
|
||||||
|
prdtId,
|
||||||
|
patnrId,
|
||||||
|
prdtNm,
|
||||||
|
patncNm,
|
||||||
|
brndNm,
|
||||||
|
catNm,
|
||||||
|
regularPrice,
|
||||||
|
discountPrice,
|
||||||
|
discountRate,
|
||||||
|
shopByMobileTime: new Date().toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(sendLogShopByMobile(logParams));
|
||||||
|
}
|
||||||
|
|
||||||
|
setMobileSendPopupOpen(true); // 팝업 열기
|
||||||
|
}, setMobileSendPopupOpen),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -998,7 +1191,10 @@ export default function ProductAllSection({
|
|||||||
const handleProductDetailsClick = useCallback(() => {
|
const handleProductDetailsClick = useCallback(() => {
|
||||||
dispatch(minimizeModalMedia());
|
dispatch(minimizeModalMedia());
|
||||||
scrollToSection('scroll-marker-product-details');
|
scrollToSection('scroll-marker-product-details');
|
||||||
}, [scrollToSection, dispatch]);
|
|
||||||
|
// Source의 handleIndicatorOptions와 동일한 로깅 기능 추가
|
||||||
|
handleIndicatorOptions();
|
||||||
|
}, [scrollToSection, dispatch, handleIndicatorOptions]);
|
||||||
|
|
||||||
const handleYouMayAlsoLikeClick = useCallback(() => {
|
const handleYouMayAlsoLikeClick = useCallback(() => {
|
||||||
dispatch(minimizeModalMedia());
|
dispatch(minimizeModalMedia());
|
||||||
@@ -1592,6 +1788,7 @@ export default function ProductAllSection({
|
|||||||
onScrollToImages={handleScrollToImagesV1}
|
onScrollToImages={handleScrollToImagesV1}
|
||||||
onFocus={() => {}}
|
onFocus={() => {}}
|
||||||
data-spotlight-id="product-video-player-container"
|
data-spotlight-id="product-video-player-container"
|
||||||
|
disclaimer={productData.disclaimer}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ProductVideoV2
|
<ProductVideoV2
|
||||||
|
|||||||
@@ -215,3 +215,32 @@
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
width: 100%;
|
||||||
|
height: 54px;
|
||||||
|
background: #000000;
|
||||||
|
.flex(@justifyCenter:flex-start);
|
||||||
|
padding: 6px 18px 18px 18px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 0 0 12px 12px;
|
||||||
|
|
||||||
|
.marquee {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
margin: 10px 12px 0 0;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
line-height: normal;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-align: left;
|
||||||
|
.font(@fontFamily:@baseFont, @fontSize:20px);
|
||||||
|
color: @COLOR_GRAY04;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,31 @@
|
|||||||
import React, { useCallback, useMemo, useState, useEffect, useRef } from 'react';
|
import React, {
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
useDispatch,
|
||||||
|
useSelector,
|
||||||
|
} from 'react-redux';
|
||||||
|
|
||||||
|
import Marquee from '@enact/sandstone/Marquee';
|
||||||
import Spotlight from '@enact/spotlight';
|
import Spotlight from '@enact/spotlight';
|
||||||
import Spottable from '@enact/spotlight/Spottable';
|
import Spottable from '@enact/spotlight/Spottable';
|
||||||
|
|
||||||
|
import playImg from '../../../../../assets/images/btn/btn-play-thumb-nor.png';
|
||||||
|
import ic_warning from '../../../../../assets/images/icons/ic-warning@3x.png';
|
||||||
import {
|
import {
|
||||||
startMediaPlayer,
|
|
||||||
finishMediaPreview,
|
finishMediaPreview,
|
||||||
switchMediaToFullscreen,
|
|
||||||
minimizeModalMedia,
|
minimizeModalMedia,
|
||||||
restoreModalMedia,
|
restoreModalMedia,
|
||||||
|
startMediaPlayer,
|
||||||
|
switchMediaToFullscreen,
|
||||||
} from '../../../../actions/mediaActions';
|
} from '../../../../actions/mediaActions';
|
||||||
import CustomImage from '../../../../components/CustomImage/CustomImage';
|
import CustomImage from '../../../../components/CustomImage/CustomImage';
|
||||||
import { panel_names } from '../../../../utils/Config';
|
import { panel_names } from '../../../../utils/Config';
|
||||||
import playImg from '../../../../../assets/images/btn/btn-play-thumb-nor.png';
|
|
||||||
import css from './ProductVideo.module.less';
|
import css from './ProductVideo.module.less';
|
||||||
|
|
||||||
const SpottableComponent = Spottable('div');
|
const SpottableComponent = Spottable('div');
|
||||||
@@ -25,6 +39,7 @@ export default function ProductVideo({
|
|||||||
autoPlay = false, // 자동 재생 여부
|
autoPlay = false, // 자동 재생 여부
|
||||||
continuousPlay = false, // 반복 재생 여부
|
continuousPlay = false, // 반복 재생 여부
|
||||||
onFocus = null, // 외부에서 전달된 포커스 핸들러
|
onFocus = null, // 외부에서 전달된 포커스 핸들러
|
||||||
|
disclaimer,
|
||||||
}) {
|
}) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
@@ -315,6 +330,12 @@ export default function ProductVideo({
|
|||||||
<img src={playImg} alt="재생" />
|
<img src={playImg} alt="재생" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={css.notice}>
|
||||||
|
<Marquee className={css.marquee} marqueeOn="render">
|
||||||
|
<img src={ic_warning} alt={disclaimer} />
|
||||||
|
<span>{disclaimer}</span>
|
||||||
|
</Marquee>
|
||||||
|
</div>
|
||||||
</SpottableComponent>
|
</SpottableComponent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,6 +169,9 @@ export default function YouMayAlsoLike({
|
|||||||
prdtId,
|
prdtId,
|
||||||
launchedFromPlayer: launchedFromPlayer,
|
launchedFromPlayer: launchedFromPlayer,
|
||||||
bgVideoInfo: bgVideoInfo, // 백그라운드 비디오 정보 유지
|
bgVideoInfo: bgVideoInfo, // 백그라운드 비디오 정보 유지
|
||||||
|
fromPanel: {
|
||||||
|
fromYouMayLike: true, // YouMayLike에서 선택된 상품임을 표시
|
||||||
|
}, // 출처 정보 통합 객체
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { memo } from "react";
|
import React, { memo } from "react";
|
||||||
|
|
||||||
import IcPartnersDefault from "../../../../assets/images/ic-tab-partners-default@3x.png";
|
import IcPartnersDefault from "../../../../assets/images/ic-tab-partners-default@3x.png";
|
||||||
|
import NBCULogoImage from "../../../../assets/images/featuredBrands/image-nbcu.png";
|
||||||
import CustomImage from "../../../components/CustomImage/CustomImage";
|
import CustomImage from "../../../components/CustomImage/CustomImage";
|
||||||
import css from "./Banner.module.less";
|
import css from "./Banner.module.less";
|
||||||
|
|
||||||
@@ -15,16 +16,20 @@ export default memo(function Banner({
|
|||||||
const { patncLogoPath, patncNm } = selectedBrandInfo;
|
const { patncLogoPath, patncNm } = selectedBrandInfo;
|
||||||
const { topImgAlt, topImgPath } = brandTopImgInfo;
|
const { topImgAlt, topImgPath } = brandTopImgInfo;
|
||||||
|
|
||||||
|
// NBCU 로고 이미지 처리
|
||||||
|
const logoSrc = panelPatnrId === 'NBCU' ? NBCULogoImage : patncLogoPath;
|
||||||
|
const logoName = panelPatnrId === 'NBCU' ? 'Peacock' : patncNm;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={css.container}>
|
<div className={css.container}>
|
||||||
<figure>
|
<figure>
|
||||||
<CustomImage
|
<CustomImage
|
||||||
src={patncLogoPath}
|
src={logoSrc}
|
||||||
alt={patncNm}
|
alt={logoName}
|
||||||
fallbackSrc={IcPartnersDefault}
|
fallbackSrc={IcPartnersDefault}
|
||||||
ariaLabel={patncNm}
|
ariaLabel={logoName}
|
||||||
/>
|
/>
|
||||||
<figcaption>{patncNm}</figcaption>
|
<figcaption>{logoName}</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
<CustomImage src={topImgPath} alt={topImgAlt} ariaLabel={topImgAlt} />
|
<CustomImage src={topImgPath} alt={topImgAlt} ariaLabel={topImgAlt} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ import css from "./FeaturedBrandsPanel.module.less";
|
|||||||
import FeaturedCategory from "./FeaturedCategory/FeaturedCategory";
|
import FeaturedCategory from "./FeaturedCategory/FeaturedCategory";
|
||||||
import FeaturedCreators from "./FeaturedCreators/FeaturedCreators";
|
import FeaturedCreators from "./FeaturedCreators/FeaturedCreators";
|
||||||
import LiveChannels from "./LiveChannels/LiveChannels";
|
import LiveChannels from "./LiveChannels/LiveChannels";
|
||||||
|
import NBCUContent from "./NBCUContent/NBCUContent";
|
||||||
import QuickMenu from "./QuickMenu/QuickMenu";
|
import QuickMenu from "./QuickMenu/QuickMenu";
|
||||||
import RecommendedShows from "./RecommendedShows/RecommendedShows";
|
import RecommendedShows from "./RecommendedShows/RecommendedShows";
|
||||||
import Series from "./Series/Series";
|
import Series from "./Series/Series";
|
||||||
@@ -68,6 +69,7 @@ import TodaysDeals from "./TodaysDeals/TodaysDeals";
|
|||||||
import UpComing from "./UpComing/UpComing";
|
import UpComing from "./UpComing/UpComing";
|
||||||
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
|
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
|
||||||
import { sortedIndexOf } from "lodash";
|
import { sortedIndexOf } from "lodash";
|
||||||
|
import NBCUBgImage from "../../../assets/images/featuredBrands/image-bg.png";
|
||||||
|
|
||||||
const STRING_CONF = {
|
const STRING_CONF = {
|
||||||
CANCEL: "CANCEL",
|
CANCEL: "CANCEL",
|
||||||
@@ -81,6 +83,7 @@ const STRING_CONF = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const TEMPLATE_CODE_CONF = {
|
const TEMPLATE_CODE_CONF = {
|
||||||
|
NBCU: "NBU00100",
|
||||||
LIVE_CHANNELS: "BRD00101",
|
LIVE_CHANNELS: "BRD00101",
|
||||||
UP_COMING: "BRD00102",
|
UP_COMING: "BRD00102",
|
||||||
TODAYS_DEALS: "BRD00103",
|
TODAYS_DEALS: "BRD00103",
|
||||||
@@ -304,8 +307,42 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const sortedBrandLayoutInfo = useMemo(
|
const sortedBrandLayoutInfo = useMemo(
|
||||||
() => brandLayoutInfo?.sort((a, b) => a.expsOrd - b.expsOrd) ?? [],
|
() => {
|
||||||
[brandLayoutInfo]
|
if (!panelInfo?.patnrId) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// NBCU 특별 처리
|
||||||
|
if (panelInfo?.patnrId === 'NBCU') {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
shptmBrndOptTpCd: TEMPLATE_CODE_CONF.NBCU,
|
||||||
|
shptmBrndOptTpNm: 'NBCU',
|
||||||
|
expsOrd: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return brandLayoutInfo?.sort((a, b) => a.expsOrd - b.expsOrd) ?? [];
|
||||||
|
},
|
||||||
|
[brandLayoutInfo, panelInfo?.patnrId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const processedBrandTopImgInfo = useMemo(
|
||||||
|
() => {
|
||||||
|
// NBCU 특별 처리
|
||||||
|
if (panelInfo?.patnrId === 'NBCU') {
|
||||||
|
return {
|
||||||
|
topImgPath: NBCUBgImage,
|
||||||
|
topImgAlt: 'NBCU Background Image',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 다른 브랜드: brandTopImgInfo가 유효한 객체여야 함
|
||||||
|
if (brandTopImgInfo && brandTopImgInfo.topImgPath) {
|
||||||
|
return brandTopImgInfo;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
[brandTopImgInfo, panelInfo?.patnrId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const doSendLogGNB = useCallback(
|
const doSendLogGNB = useCallback(
|
||||||
@@ -415,6 +452,21 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
|
|||||||
<>
|
<>
|
||||||
{sortedBrandLayoutInfo.map((el, idx) => {
|
{sortedBrandLayoutInfo.map((el, idx) => {
|
||||||
switch (el.shptmBrndOptTpCd) {
|
switch (el.shptmBrndOptTpCd) {
|
||||||
|
case TEMPLATE_CODE_CONF.NBCU: {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||||||
|
<NBCUContent
|
||||||
|
handleItemFocus={handleItemFocus}
|
||||||
|
spotlightId={TEMPLATE_CODE_CONF.NBCU}
|
||||||
|
shelfOrder={el.expsOrd}
|
||||||
|
shelfTitle={el.shptmBrndOptTpNm}
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
order={idx + 1}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
case TEMPLATE_CODE_CONF.LIVE_CHANNELS: {
|
case TEMPLATE_CODE_CONF.LIVE_CHANNELS: {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={el.shptmBrndOptTpCd}>
|
<React.Fragment key={el.shptmBrndOptTpCd}>
|
||||||
@@ -709,7 +761,7 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
|
|||||||
|
|
||||||
// effect: layout information fetching due to partner id change
|
// effect: layout information fetching due to partner id change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!fromDetail) {
|
if (!fromDetail && panelInfo?.patnrId) {
|
||||||
dispatch({ type: types.RESET_BRAND_LAYOUT_INFO });
|
dispatch({ type: types.RESET_BRAND_LAYOUT_INFO });
|
||||||
dispatch(getBrandLayoutInfo({ patnrId: panelInfo?.patnrId }));
|
dispatch(getBrandLayoutInfo({ patnrId: panelInfo?.patnrId }));
|
||||||
setIsInitialFocusOccurred(false);
|
setIsInitialFocusOccurred(false);
|
||||||
@@ -719,13 +771,20 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
|
|||||||
|
|
||||||
// effect: set selectedPatnrId and selectedPatncNm
|
// effect: set selectedPatnrId and selectedPatncNm
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (brandInfo) {
|
if (brandInfo || panelInfo?.patnrId) {
|
||||||
const patnrId = panelInfo?.patnrId;
|
const patnrId = panelInfo?.patnrId;
|
||||||
const patncNm = brandInfo.find((b) => b?.patnrId === patnrId).patncNm;
|
|
||||||
|
|
||||||
setSelectedPatncNm(patncNm);
|
// NBCU 특별 처리
|
||||||
|
if (patnrId === 'NBCU') {
|
||||||
if (!fromDetail) setSelectedPatnrId(patnrId);
|
setSelectedPatncNm('NBCU');
|
||||||
|
if (!fromDetail) setSelectedPatnrId('NBCU');
|
||||||
|
} else if (brandInfo) {
|
||||||
|
const brandItem = brandInfo.find((b) => b?.patnrId === patnrId);
|
||||||
|
if (brandItem) {
|
||||||
|
setSelectedPatncNm(brandItem.patncNm);
|
||||||
|
if (!fromDetail) setSelectedPatnrId(patnrId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [brandInfo, panelInfo?.patnrId]);
|
}, [brandInfo, panelInfo?.patnrId]);
|
||||||
|
|
||||||
@@ -958,10 +1017,10 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{brandInfo && brandTopImgInfo && (
|
{((brandInfo && processedBrandTopImgInfo) || panelInfo?.patnrId === 'NBCU') && processedBrandTopImgInfo && (
|
||||||
<Banner
|
<Banner
|
||||||
brandInfo={brandInfo}
|
brandInfo={brandInfo}
|
||||||
brandTopImgInfo={brandTopImgInfo}
|
brandTopImgInfo={processedBrandTopImgInfo}
|
||||||
panelPatnrId={panelInfo?.patnrId}
|
panelPatnrId={panelInfo?.patnrId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
import React, { memo, useCallback, useState, useEffect } from "react";
|
||||||
|
|
||||||
|
import Spotlight from "@enact/spotlight";
|
||||||
|
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||||
|
import Spottable from "@enact/spotlight/Spottable";
|
||||||
|
|
||||||
|
import SectionTitle from "../../../components/SectionTitle/SectionTitle";
|
||||||
|
import NBCUSectionTitle from "./NBCUSectionTitle/NBCUSectionTitle";
|
||||||
|
import { $L } from "../../../utils/helperMethods";
|
||||||
|
import css from "./NBCUContent.module.less";
|
||||||
|
import NBCUList from "./NBCUList/NBCUList";
|
||||||
|
import NBCUSeries from "./NBCUSeries/NBCUSeries";
|
||||||
|
import seriesCard1 from "../../../../assets/images/featuredBrands/series-card-1.png";
|
||||||
|
import seriesCard2 from "../../../../assets/images/featuredBrands/series-card-2.png";
|
||||||
|
import seriesCard3 from "../../../../assets/images/featuredBrands/series-card-3.png";
|
||||||
|
|
||||||
|
const STRING_CONF = {
|
||||||
|
NBCU: "NBCU",
|
||||||
|
PICKED_FOR_YOU: "PICKED FOR YOU",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock data for Series
|
||||||
|
const MOCK_BRAND_SERIES_GROUP_INFO = [
|
||||||
|
{
|
||||||
|
seriesId: "series-1",
|
||||||
|
seriesNm: "Drama Collection",
|
||||||
|
seriesImgUrl: seriesCard1,
|
||||||
|
patnrId: "nbcu-partner-1",
|
||||||
|
brandSeriesProductInfo: Array.from({ length: 6 }).map((_, i) => ({
|
||||||
|
productId: `drama-${i}`,
|
||||||
|
productNm: `Drama Show ${i + 1}`,
|
||||||
|
imageUrl: "assets/images/img-thumb-empty-product@3x.png",
|
||||||
|
priceInfo: "$15.00|$10.00|N|$5.00|33%|PROMO|2025-12-31",
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
seriesId: "series-2",
|
||||||
|
seriesNm: "Comedy Series",
|
||||||
|
seriesImgUrl: seriesCard2,
|
||||||
|
patnrId: "nbcu-partner-1",
|
||||||
|
brandSeriesProductInfo: Array.from({ length: 6 }).map((_, i) => ({
|
||||||
|
productId: `comedy-${i}`,
|
||||||
|
productNm: `Comedy Show ${i + 1}`,
|
||||||
|
imageUrl: "assets/images/img-thumb-empty-product@3x.png",
|
||||||
|
priceInfo: "$12.00|$8.00|N|$4.00|33%|PROMO|2025-12-31",
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
seriesId: "series-3",
|
||||||
|
seriesNm: "Sci-Fi Originals",
|
||||||
|
seriesImgUrl: seriesCard3,
|
||||||
|
patnrId: "nbcu-partner-1",
|
||||||
|
brandSeriesProductInfo: Array.from({ length: 6 }).map((_, i) => ({
|
||||||
|
productId: `scifi-${i}`,
|
||||||
|
productNm: `Sci-Fi Show ${i + 1}`,
|
||||||
|
imageUrl: "assets/images/img-thumb-empty-product@3x.png",
|
||||||
|
priceInfo: "$18.00|$12.00|N|$6.00|33%|PROMO|2025-12-31",
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const MOCK_BRAND_SERIES_INFO = [
|
||||||
|
{ seriesId: "series-1", seriesNm: "LOVE ISLAND" },
|
||||||
|
{ seriesId: "series-2", seriesNm: "TOP CHEF" },
|
||||||
|
{ seriesId: "series-3", seriesNm: "BELOW DECK" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const SpottableDiv = Spottable('div');
|
||||||
|
|
||||||
|
const Container = SpotlightContainerDecorator(
|
||||||
|
{ leaveFor: { right: "" }, enterTo: "last-focused" },
|
||||||
|
"div"
|
||||||
|
);
|
||||||
|
|
||||||
|
const NBCUContent = ({
|
||||||
|
handleItemFocus,
|
||||||
|
spotlightId,
|
||||||
|
shelfOrder,
|
||||||
|
selectedPatnrId,
|
||||||
|
shelfTitle,
|
||||||
|
order,
|
||||||
|
}) => {
|
||||||
|
const [firstChk, setFirstChk] = useState(0);
|
||||||
|
const [selectedSeriesId, setSelectedSeriesId] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('[NBCUContent] Rendered. order:', order);
|
||||||
|
}, [order]);
|
||||||
|
|
||||||
|
const _handleItemFocus = useCallback(() => {
|
||||||
|
if (handleItemFocus) handleItemFocus(spotlightId, shelfOrder);
|
||||||
|
|
||||||
|
const c = Spotlight.getCurrent();
|
||||||
|
if (firstChk === 0) {
|
||||||
|
if (c) {
|
||||||
|
let cAriaLabel = c.getAttribute("aria-label");
|
||||||
|
if (cAriaLabel) {
|
||||||
|
cAriaLabel = "NBCU, Heading1," + cAriaLabel;
|
||||||
|
c.setAttribute("aria-label", cAriaLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFirstChk(1);
|
||||||
|
} else if (firstChk === 1) {
|
||||||
|
if (c) {
|
||||||
|
let cAriaLabel = c.getAttribute("aria-label");
|
||||||
|
if (cAriaLabel) {
|
||||||
|
const newcAriaLabel = cAriaLabel.replace("NBCU, Heading1,", "");
|
||||||
|
c.setAttribute("aria-label", newcAriaLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [handleItemFocus, firstChk, spotlightId, shelfOrder]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
className={css.container}
|
||||||
|
data-shelf-order={order}
|
||||||
|
data-wheel-point
|
||||||
|
spotlightId={spotlightId}
|
||||||
|
>
|
||||||
|
<SectionTitle
|
||||||
|
title={$L(STRING_CONF.NBCU)}
|
||||||
|
data-title="nbcu"
|
||||||
|
label="NBCU Heading 1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<NBCUList
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
spotlightId={spotlightId}
|
||||||
|
shelfOrder={shelfOrder}
|
||||||
|
shelfTitle={shelfTitle}
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Keyword Bubble Section (Dummy) */}
|
||||||
|
{/* <div className={css.keywordContainer}>
|
||||||
|
|
||||||
|
{['Action', 'Comedy', 'Drama', 'Sci-Fi', 'Thriller', 'Romance', 'Documentary'].map((keyword, index) => (
|
||||||
|
<SpottableDiv
|
||||||
|
key={index}
|
||||||
|
className={css.keywordBubble}
|
||||||
|
onClick={() => console.log(`Clicked keyword: ${keyword}`)}
|
||||||
|
>
|
||||||
|
{keyword}
|
||||||
|
</SpottableDiv>
|
||||||
|
))}
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
{/* Picked For You Section Title */}
|
||||||
|
<NBCUSectionTitle
|
||||||
|
title={$L(STRING_CONF.PICKED_FOR_YOU)}
|
||||||
|
data-title="picked-for-you"
|
||||||
|
label="Picked For You Heading"
|
||||||
|
isBlack={true}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Series Component with Mock Data */}
|
||||||
|
<NBCUSeries
|
||||||
|
brandSeriesGroupInfo={MOCK_BRAND_SERIES_GROUP_INFO}
|
||||||
|
brandSeriesInfo={MOCK_BRAND_SERIES_INFO}
|
||||||
|
fromGNB={false}
|
||||||
|
fromQuickMenu={false}
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
order={order}
|
||||||
|
shelfOrder={shelfOrder}
|
||||||
|
shelfTitle={shelfTitle}
|
||||||
|
spotlightId={`${spotlightId}-series`}
|
||||||
|
selectedPatncNm="NBCU"
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
selectedSeriesId={selectedSeriesId}
|
||||||
|
setSelectedSeriesId={setSelectedSeriesId}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(NBCUContent);
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
@import "../../../style/CommonStyle.module.less";
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 50px 0; // Adjust padding as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
.keywordContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 0 60px; // Match side padding of other contents
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keywordBubble {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px 24px;
|
||||||
|
border-radius: 30px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
|
||||||
|
&:focus, &:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
border-color: #ffffff;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import React, { useCallback, useMemo } from 'react';
|
||||||
|
import Spotlight from '@enact/spotlight';
|
||||||
|
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
||||||
|
|
||||||
|
import TItemCardNew from '../../../../components/TItemCard/TItemCard.new';
|
||||||
|
import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList';
|
||||||
|
import css from './NBCUList.module.less';
|
||||||
|
|
||||||
|
// 더미 데이터 생성
|
||||||
|
// priceInfo format: originalPrice|discountedPrice|rewardFlag|discountAmount|discountRate|promotionCode|promotionDate
|
||||||
|
const DUMMY_DATA = Array.from({ length: 10 }).map((_, index) => ({
|
||||||
|
id: `nbcu-item-${index}`,
|
||||||
|
title: `NBCU Content ${index + 1}`,
|
||||||
|
imgUrl: 'assets/images/img-thumb-empty-product@3x.png',
|
||||||
|
priceInfo: '$20.00|$10.00|N|$10.00|50%|PROMO|2025-12-31',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Container = SpotlightContainerDecorator(
|
||||||
|
{ leaveFor: { right: '' }, enterTo: 'last-focused' },
|
||||||
|
'div'
|
||||||
|
);
|
||||||
|
|
||||||
|
const NBCUList = ({ handleItemFocus, spotlightId, shelfTitle, shelfOrder }) => {
|
||||||
|
const renderItem = useCallback(
|
||||||
|
({ index, ...rest }) => {
|
||||||
|
const item = DUMMY_DATA[index];
|
||||||
|
const labelText = `${index + 1} of ${DUMMY_DATA.length}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TItemCardNew
|
||||||
|
{...rest}
|
||||||
|
key={item.id}
|
||||||
|
imageSource={item.imgUrl}
|
||||||
|
productName={item.title}
|
||||||
|
priceInfo={item.priceInfo}
|
||||||
|
spotlightId={`nbcu-spotlightId-${index}`}
|
||||||
|
shelfId={spotlightId}
|
||||||
|
shelfLocation={shelfOrder}
|
||||||
|
shelfTitle={shelfTitle}
|
||||||
|
label={labelText}
|
||||||
|
onFocus={handleItemFocus}
|
||||||
|
onClick={() => {
|
||||||
|
console.log('Clicked NBCU item:', item.title);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[handleItemFocus, spotlightId, shelfOrder, shelfTitle]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container className={css.container} spotlightId="nbcu-list-id">
|
||||||
|
<TVirtualGridList
|
||||||
|
dataSize={DUMMY_DATA.length}
|
||||||
|
direction="horizontal"
|
||||||
|
itemHeight={438}
|
||||||
|
itemWidth={324}
|
||||||
|
spacing={18}
|
||||||
|
renderItem={renderItem}
|
||||||
|
className={css.tVirtualGridList}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(NBCUList);
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
@import "../../../../style/CommonStyle.module.less";
|
||||||
|
@import "../../../../style/utils.module.less";
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
.size(@w: 100%, @h: 438px);
|
||||||
|
padding-right: 18px;
|
||||||
|
|
||||||
|
// tVirtualGridListContainer
|
||||||
|
> div:nth-child(1) {
|
||||||
|
.size(@w: 100%, @h: inherit);
|
||||||
|
|
||||||
|
&.tVirtualGridList {
|
||||||
|
padding-left: 60px;
|
||||||
|
|
||||||
|
> div:nth-child(3) {
|
||||||
|
right: -18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import React, { memo } from "react";
|
||||||
|
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
import css from "./NBCUSectionTitle.module.less";
|
||||||
|
|
||||||
|
export default memo(function NBCUSectionTitle({
|
||||||
|
className,
|
||||||
|
itemCount,
|
||||||
|
title,
|
||||||
|
label,
|
||||||
|
isBlack = false,
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<h2
|
||||||
|
className={classNames(css.sectionTitle, isBlack && css.blackTitle, className)}
|
||||||
|
aria-label={label ? label : title}
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-live="polite"
|
||||||
|
aria-atomic="true"
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
{itemCount && <span>({itemCount})</span>}
|
||||||
|
</h2>
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
@import "../../../../style/CommonStyle.module.less";
|
||||||
|
@import "../../../../style/utils.module.less";
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
position: relative;
|
||||||
|
.flex(@justifyCenter: flex-start);
|
||||||
|
min-height: 50px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 42px;
|
||||||
|
color: #000000 !important;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: inline-block;
|
||||||
|
content: "";
|
||||||
|
.size(@w: 6px, @h: 36px);
|
||||||
|
margin-right: 12px;
|
||||||
|
background-color: #000000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blackTitle {
|
||||||
|
color: #000000;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
import React, { memo, useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import Spotlight from "@enact/spotlight";
|
||||||
|
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||||
|
|
||||||
|
import NBCUSectionTitle from "../NBCUSectionTitle/NBCUSectionTitle";
|
||||||
|
import { $L } from "../../../../utils/helperMethods";
|
||||||
|
import css from "./NBCUSeries.module.less";
|
||||||
|
import SeriesContents from "../../Series/SeriesContents/SeriesContents";
|
||||||
|
import SeriesNav from "../../Series/SeriesNav/SeriesNav";
|
||||||
|
|
||||||
|
const STRING_CONF = {
|
||||||
|
SERIES: "SERIES",
|
||||||
|
};
|
||||||
|
|
||||||
|
const Container = SpotlightContainerDecorator(
|
||||||
|
{ leaveFor: { right: "" }, enterTo: "last-focused" },
|
||||||
|
"div"
|
||||||
|
);
|
||||||
|
|
||||||
|
const NBCUSeries = ({
|
||||||
|
brandSeriesGroupInfo,
|
||||||
|
brandSeriesInfo,
|
||||||
|
fromGNB,
|
||||||
|
fromQuickMenu,
|
||||||
|
handleItemFocus,
|
||||||
|
order,
|
||||||
|
shelfOrder,
|
||||||
|
shelfTitle,
|
||||||
|
spotlightId,
|
||||||
|
selectedPatncNm,
|
||||||
|
selectedPatnrId,
|
||||||
|
selectedSeriesId,
|
||||||
|
setSelectedSeriesId,
|
||||||
|
}) => {
|
||||||
|
const [filteredBrandSeriesGroupInfo, setFilteredSeriesGroupInfo] = useState();
|
||||||
|
const [firstChk, setFirstChk] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectedSeriesId) {
|
||||||
|
return setFilteredSeriesGroupInfo(brandSeriesGroupInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilteredSeriesGroupInfo(
|
||||||
|
brandSeriesGroupInfo.filter(
|
||||||
|
({ seriesId }) => seriesId === selectedSeriesId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [brandSeriesGroupInfo, selectedSeriesId]);
|
||||||
|
|
||||||
|
const _handleItemFocus = useCallback(() => {
|
||||||
|
if (handleItemFocus) handleItemFocus(spotlightId, shelfOrder);
|
||||||
|
|
||||||
|
const c = Spotlight.getCurrent();
|
||||||
|
if (firstChk === 0) {
|
||||||
|
if (c) {
|
||||||
|
let cAriaLabel = c.getAttribute("aria-label");
|
||||||
|
if (cAriaLabel) {
|
||||||
|
cAriaLabel = "series, Heading1," + cAriaLabel;
|
||||||
|
c.setAttribute("aria-label", cAriaLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFirstChk(1);
|
||||||
|
} else if (firstChk === 1) {
|
||||||
|
if (c) {
|
||||||
|
let cAriaLabel = c.getAttribute("aria-label");
|
||||||
|
if (cAriaLabel) {
|
||||||
|
const newcAriaLabel = cAriaLabel.replace("series, Heading1,", "");
|
||||||
|
c.setAttribute("aria-label", newcAriaLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [handleItemFocus, firstChk]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
className={css.container}
|
||||||
|
data-shelf-order={order}
|
||||||
|
data-wheel-point
|
||||||
|
spotlightId={spotlightId}
|
||||||
|
>
|
||||||
|
{/* <NBCUSectionTitle title={$L(STRING_CONF.SERIES)} data-title="series" isBlack={true} /> */}
|
||||||
|
<SeriesNav
|
||||||
|
brandSeriesInfo={brandSeriesInfo}
|
||||||
|
fromGNB={fromGNB}
|
||||||
|
fromQuickMenu={fromQuickMenu}
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
selectedPatncNm={selectedPatncNm}
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
selectedSeriesId={selectedSeriesId}
|
||||||
|
setSelectedSeriesId={setSelectedSeriesId}
|
||||||
|
/>
|
||||||
|
{filteredBrandSeriesGroupInfo &&
|
||||||
|
filteredBrandSeriesGroupInfo.map(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
brandSeriesProductInfo,
|
||||||
|
patnrId,
|
||||||
|
seriesId,
|
||||||
|
seriesImgUrl,
|
||||||
|
seriesNm,
|
||||||
|
},
|
||||||
|
contentsIndex
|
||||||
|
) => (
|
||||||
|
<SeriesContents
|
||||||
|
brandSeriesProductInfo={brandSeriesProductInfo}
|
||||||
|
filteredBrandLength={filteredBrandSeriesGroupInfo.length}
|
||||||
|
contentsIndex={contentsIndex}
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
isCarousel={!selectedSeriesId}
|
||||||
|
key={`${spotlightId}-${contentsIndex}`}
|
||||||
|
patnrId={patnrId}
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
selectedSeriesId={selectedSeriesId}
|
||||||
|
seriesId={seriesId}
|
||||||
|
seriesImgUrl={seriesImgUrl}
|
||||||
|
seriesNm={seriesNm}
|
||||||
|
spotlightId={spotlightId}
|
||||||
|
shelfOrder={shelfOrder}
|
||||||
|
shelfTitle={shelfTitle}
|
||||||
|
selectedPatncNm={selectedPatncNm}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(NBCUSeries);
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
@import "../../../../style/CommonStyle.module.less";
|
||||||
|
@import "../../../../style/utils.module.less";
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 36px;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding-left: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDeco
|
|||||||
import TScroller from "../../../components/TScroller/TScroller";
|
import TScroller from "../../../components/TScroller/TScroller";
|
||||||
import useScrollTo from "../../../hooks/useScrollTo";
|
import useScrollTo from "../../../hooks/useScrollTo";
|
||||||
import { scaleW } from "../../../utils/helperMethods";
|
import { scaleW } from "../../../utils/helperMethods";
|
||||||
import QuickMenuItem from "../QuickMenu/QuickMenuItem/QuickMenuItem";
|
import QuickMenuItem from "./QuickMenuItem/QuickMenuItem";
|
||||||
|
import QuickMenuItemNBCU from "./QuickMenuItemNBCU/QuickMenuItemNBCU";
|
||||||
import css from "./QuickMenu.module.less";
|
import css from "./QuickMenu.module.less";
|
||||||
|
|
||||||
const Container = SpotlightContainerDecorator(
|
const Container = SpotlightContainerDecorator(
|
||||||
@@ -76,18 +77,44 @@ const QuickMenu = ({
|
|||||||
noScrollByWheel
|
noScrollByWheel
|
||||||
>
|
>
|
||||||
<ul ref={ulRef}>
|
<ul ref={ulRef}>
|
||||||
{brandInfo.map((brandInfoItem, itemIndex) => (
|
{panelPatnrId === 'NBCU' ? (
|
||||||
<QuickMenuItem
|
<>
|
||||||
brandInfoItem={brandInfoItem}
|
<QuickMenuItemNBCU
|
||||||
itemIndex={itemIndex}
|
itemIndex={0}
|
||||||
handleItemFocus={_handleItemFocus}
|
handleItemFocus={_handleItemFocus}
|
||||||
key={"brand-info" + itemIndex}
|
key="nbcu-item"
|
||||||
resetStates={resetStates}
|
resetStates={resetStates}
|
||||||
scrollLeft={scrollLeft}
|
scrollLeft={scrollLeft}
|
||||||
selectedPatnrId={selectedPatnrId}
|
selectedPatnrId={selectedPatnrId}
|
||||||
label={itemIndex * 1 + 1 + " of " + brandInfo.length}
|
label={"1 of " + (brandInfo.length + 1)}
|
||||||
/>
|
/>
|
||||||
))}
|
{brandInfo.map((brandInfoItem, itemIndex) => (
|
||||||
|
<QuickMenuItem
|
||||||
|
brandInfoItem={brandInfoItem}
|
||||||
|
itemIndex={itemIndex + 1}
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
key={"brand-info" + itemIndex}
|
||||||
|
resetStates={resetStates}
|
||||||
|
scrollLeft={scrollLeft}
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
label={(itemIndex + 2) + " of " + (brandInfo.length + 1)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
brandInfo.map((brandInfoItem, itemIndex) => (
|
||||||
|
<QuickMenuItem
|
||||||
|
brandInfoItem={brandInfoItem}
|
||||||
|
itemIndex={itemIndex}
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
key={"brand-info" + itemIndex}
|
||||||
|
resetStates={resetStates}
|
||||||
|
scrollLeft={scrollLeft}
|
||||||
|
selectedPatnrId={selectedPatnrId}
|
||||||
|
label={(itemIndex + 1) + " of " + brandInfo.length}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</TScroller>
|
</TScroller>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import React, { memo, useCallback } from "react";
|
||||||
|
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
|
import Spottable from "@enact/spotlight/Spottable";
|
||||||
|
|
||||||
|
import IcPartnersDefault from "../../../../../assets/images/ic-tab-partners-default@3x.png";
|
||||||
|
import { resetPanels, updatePanel } from "../../../../actions/panelActions";
|
||||||
|
import CustomImage from "../../../../components/CustomImage/CustomImage";
|
||||||
|
import useScrollReset from "../../../../hooks/useScrollReset";
|
||||||
|
import { panel_names } from "../../../../utils/Config";
|
||||||
|
import css from "./QuickMenuItemNBCU.module.less";
|
||||||
|
|
||||||
|
const SpottableComponent = Spottable("li");
|
||||||
|
|
||||||
|
const QuickMenuItemNBCU = ({
|
||||||
|
itemIndex,
|
||||||
|
handleItemFocus,
|
||||||
|
resetStates,
|
||||||
|
scrollLeft,
|
||||||
|
selectedPatnrId,
|
||||||
|
label,
|
||||||
|
...rest
|
||||||
|
}) => {
|
||||||
|
const { handleScrollReset, handleStopScrolling } = useScrollReset(
|
||||||
|
scrollLeft,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const panelInfo = useSelector((state) => state.panels.panels[0]?.panelInfo);
|
||||||
|
|
||||||
|
const patnrId = "NBCU";
|
||||||
|
|
||||||
|
const handleBlur = useCallback(() => {
|
||||||
|
if (itemIndex !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleStopScrolling();
|
||||||
|
}, [handleStopScrolling, itemIndex]);
|
||||||
|
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
if (patnrId === (selectedPatnrId ?? panelInfo?.patnrId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const from = "menu";
|
||||||
|
const name = panel_names.FEATURED_BRANDS_PANEL;
|
||||||
|
|
||||||
|
dispatch(resetPanels([{ name }]));
|
||||||
|
dispatch(updatePanel({ name, panelInfo: { from, patnrId } }));
|
||||||
|
resetStates();
|
||||||
|
}, [dispatch, patnrId, resetStates, selectedPatnrId]);
|
||||||
|
|
||||||
|
const handleFocus = useCallback(() => {
|
||||||
|
if (handleItemFocus) handleItemFocus();
|
||||||
|
|
||||||
|
if (itemIndex !== 0) return;
|
||||||
|
|
||||||
|
handleScrollReset();
|
||||||
|
}, [handleScrollReset, handleItemFocus, itemIndex]);
|
||||||
|
|
||||||
|
const selected =
|
||||||
|
(selectedPatnrId ?? panelInfo?.patnrId) === patnrId ? "Selected, " : "";
|
||||||
|
const ariaLabel = selected + "Channel NBCU, Tap " + label;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SpottableComponent
|
||||||
|
className={classNames(
|
||||||
|
css.brand,
|
||||||
|
(selectedPatnrId ?? panelInfo?.patnrId) === patnrId && css.selected
|
||||||
|
)}
|
||||||
|
data-menu-index={itemIndex}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
onClick={handleClick}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
spotlightId={"spotlightId-NBCU"}
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<CustomImage
|
||||||
|
src="assets/images/featuredBrands/image-nbcu.png"
|
||||||
|
alt="NBCU"
|
||||||
|
fallbackSrc={IcPartnersDefault}
|
||||||
|
ariaLabel="NBCU"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SpottableComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(QuickMenuItemNBCU);
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
@import "../../../../style/CommonStyle.module.less";
|
||||||
|
@import "../../../../style/utils.module.less";
|
||||||
|
|
||||||
|
.brand {
|
||||||
|
position: relative;
|
||||||
|
.flex();
|
||||||
|
.size(@w: 144px, @h: 144px);
|
||||||
|
|
||||||
|
> div {
|
||||||
|
position: relative;
|
||||||
|
// NBCU image
|
||||||
|
> img {
|
||||||
|
.size(@w: 120px, @h: 120px);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
// NBCU image
|
||||||
|
.size(@w: 144px, @h: 144px);
|
||||||
|
> div {
|
||||||
|
&:after {
|
||||||
|
.focused(@boxShadow: 0px, @borderRadius: 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
> img {
|
||||||
|
.size(@w: 144px, @h: 144px);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
// NBCU image
|
||||||
|
&:after {
|
||||||
|
.size(@w:100%, @h:6px);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -18px;
|
||||||
|
background: @PRIMARY_COLOR_RED;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
> div {
|
||||||
|
&:after {
|
||||||
|
.focused(@boxShadow: 0px, @borderRadius: 50%);
|
||||||
|
border-color: @PRIMARY_COLOR_RED;
|
||||||
|
}
|
||||||
|
> img {
|
||||||
|
.size(@w: 120px, @h: 120px);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -282,6 +282,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
const watchIntervalLive = useRef(null);
|
const watchIntervalLive = useRef(null);
|
||||||
const watchIntervalVod = useRef(null);
|
const watchIntervalVod = useRef(null);
|
||||||
const watchIntervalMedia = useRef(null);
|
const watchIntervalMedia = useRef(null);
|
||||||
|
const timeoutRef = useRef(null);
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// console.log("###videoLoaded", videoLoaded);
|
// console.log("###videoLoaded", videoLoaded);
|
||||||
// if (nowMenu) {
|
// if (nowMenu) {
|
||||||
@@ -291,8 +292,15 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
if (liveShowInfos && liveShowInfos.length > 0) {
|
if (liveShowInfos && liveShowInfos.length > 0) {
|
||||||
const panelInfoChanId = panelInfo?.chanId;
|
const panelInfoChanId = panelInfo?.chanId;
|
||||||
const isLive = panelInfo?.shptmBanrTpNm === 'LIVE';
|
const isLive = panelInfo?.shptmBanrTpNm === 'LIVE';
|
||||||
|
const isModal = panelInfo?.modal;
|
||||||
|
|
||||||
if (isLive) {
|
if (isLive) {
|
||||||
|
// live full 화면에서 modal 전환시 로그 전송 추가
|
||||||
|
if (isModal) {
|
||||||
|
dispatch(sendLogGNB(Config.LOG_MENU.FULL));
|
||||||
|
prevNowMenuRef.current = nowMenuRef.current;
|
||||||
|
return () => dispatch(sendLogGNB(prevNowMenuRef.current));
|
||||||
|
}
|
||||||
const liveShowInfo = liveShowInfos //
|
const liveShowInfo = liveShowInfos //
|
||||||
.find(({ chanId }) => panelInfoChanId === chanId);
|
.find(({ chanId }) => panelInfoChanId === chanId);
|
||||||
|
|
||||||
@@ -303,7 +311,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}, [liveShowInfos, panelInfo?.chanId, panelInfo?.shptmBanrTpNm]);
|
}, [liveShowInfos, panelInfo?.chanId, panelInfo?.shptmBanrTpNm, panelInfo?.modal]);
|
||||||
|
|
||||||
const currentVODShowInfo = useMemo(() => {
|
const currentVODShowInfo = useMemo(() => {
|
||||||
if (showDetailInfo && showDetailInfo.length > 0) {
|
if (showDetailInfo && showDetailInfo.length > 0) {
|
||||||
@@ -327,7 +335,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
prevNowMenuRef.current = nowMenuRef.current;
|
prevNowMenuRef.current = nowMenuRef.current;
|
||||||
|
|
||||||
return () => dispatch(sendLogGNB(prevNowMenuRef.current));
|
return () => dispatch(sendLogGNB(prevNowMenuRef.current));
|
||||||
} else if (panelInfo?.modal) {
|
} else if (panelInfo?.modal && panelInfo?.shptmBanrTpNm !== 'LIVE') {
|
||||||
dispatch(sendLogGNB(entryMenu));
|
dispatch(sendLogGNB(entryMenu));
|
||||||
}
|
}
|
||||||
}, [panelInfo?.modal, panelInfo?.shptmBanrTpNm]);
|
}, [panelInfo?.modal, panelInfo?.shptmBanrTpNm]);
|
||||||
@@ -619,7 +627,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
|
|
||||||
if (lastFocusedTargetId) {
|
if (lastFocusedTargetId) {
|
||||||
// ShopNowContents가 렌더링될 때까지 대기 후 포커스 복원
|
// ShopNowContents가 렌더링될 때까지 대기 후 포커스 복원
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
dlog('[PlayerPanel] 🔍 800ms 후 포커스 복원 시도:', lastFocusedTargetId);
|
dlog('[PlayerPanel] 🔍 800ms 후 포커스 복원 시도:', lastFocusedTargetId);
|
||||||
Spotlight.focus(lastFocusedTargetId);
|
Spotlight.focus(lastFocusedTargetId);
|
||||||
}, 800);
|
}, 800);
|
||||||
@@ -710,6 +718,13 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
panelInfo?.modal &&
|
panelInfo?.modal &&
|
||||||
liveLogParamsRef.current?.showId === panelInfo?.showId
|
liveLogParamsRef.current?.showId === panelInfo?.showId
|
||||||
) {
|
) {
|
||||||
|
dlog('[PlayerPanel] 📡 LIVE Modal Log Ready and Conditions Met:', {
|
||||||
|
isModalLiveLogReady: logStatus.isModalLiveLogReady,
|
||||||
|
isOnTop,
|
||||||
|
isModal: panelInfo?.modal,
|
||||||
|
showIdMatch: liveLogParamsRef.current?.showId === panelInfo?.showId,
|
||||||
|
logParams: liveLogParamsRef.current,
|
||||||
|
});
|
||||||
let watchStrtDt = formatGMTString(new Date());
|
let watchStrtDt = formatGMTString(new Date());
|
||||||
|
|
||||||
watchIntervalLive.current = setInterval(() => {
|
watchIntervalLive.current = setInterval(() => {
|
||||||
@@ -728,6 +743,10 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
isModalLiveLogReady: false,
|
isModalLiveLogReady: false,
|
||||||
}));
|
}));
|
||||||
clearInterval(watchIntervalLive.current);
|
clearInterval(watchIntervalLive.current);
|
||||||
|
dlog('[PlayerPanel] 🚀 Dispatching LIVE Modal Log:', {
|
||||||
|
logParams: liveLogParamsRef.current,
|
||||||
|
watchStrtDt,
|
||||||
|
});
|
||||||
dispatch(
|
dispatch(
|
||||||
sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () =>
|
sendLogLive({ ...liveLogParamsRef.current, watchStrtDt }, () =>
|
||||||
dispatch(changeLocalSettings({ watchRecord: {} }))
|
dispatch(changeLocalSettings({ watchRecord: {} }))
|
||||||
@@ -1147,7 +1166,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
|
|
||||||
//딮링크로 플레이어 진입 후 이전버튼 클릭시
|
//딮링크로 플레이어 진입 후 이전버튼 클릭시
|
||||||
if (panels.length === 1) {
|
if (panels.length === 1) {
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
Spotlight.focus(SpotlightIds.HOME_TBODY);
|
Spotlight.focus(SpotlightIds.HOME_TBODY);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1685,7 +1704,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentLiveTimeSeconds > liveTotalTime) {
|
if (currentLiveTimeSeconds > liveTotalTime) {
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
dispatch(getMainLiveShow());
|
dispatch(getMainLiveShow());
|
||||||
setShopNowInfo('');
|
setShopNowInfo('');
|
||||||
dispatch(
|
dispatch(
|
||||||
@@ -1694,8 +1713,21 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}, [currentLiveTimeSeconds, liveTotalTime]);
|
}, [currentLiveTimeSeconds, liveTotalTime, dispatch, playListInfo, selectedIndex]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
||||||
|
if (watchIntervalLive.current) clearInterval(watchIntervalLive.current);
|
||||||
|
if (watchIntervalVod.current) clearInterval(watchIntervalVod.current);
|
||||||
|
if (watchIntervalMedia.current) clearInterval(watchIntervalMedia.current);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const mediainfoHandler = useCallback(
|
const mediainfoHandler = useCallback(
|
||||||
(ev) => {
|
(ev) => {
|
||||||
@@ -1994,7 +2026,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
|
|
||||||
const handlePopupClose = useCallback(() => {
|
const handlePopupClose = useCallback(() => {
|
||||||
dispatch(setHidePopup());
|
dispatch(setHidePopup());
|
||||||
setTimeout(() => Spotlight.focus(SpotlightIds.PLAYER_SUBTITLE_BUTTON));
|
timeoutRef.current = setTimeout(() => Spotlight.focus(SpotlightIds.PLAYER_SUBTITLE_BUTTON));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
const reactPlayerSubtitleConfig = useMemo(() => {
|
const reactPlayerSubtitleConfig = useMemo(() => {
|
||||||
if (isSubtitleActive && currentSubtitleBlob) {
|
if (isSubtitleActive && currentSubtitleBlob) {
|
||||||
@@ -2324,7 +2356,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
Spotlight.pause();
|
Spotlight.pause();
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
Spotlight.resume();
|
Spotlight.resume();
|
||||||
dispatch(PanelActions.popPanel());
|
dispatch(PanelActions.popPanel());
|
||||||
}, VIDEO_END_ACTION_DELAY);
|
}, VIDEO_END_ACTION_DELAY);
|
||||||
@@ -2332,7 +2364,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
}
|
}
|
||||||
if (panelInfoRef.current.shptmBanrTpNm === 'VOD') {
|
if (panelInfoRef.current.shptmBanrTpNm === 'VOD') {
|
||||||
Spotlight.pause();
|
Spotlight.pause();
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
stopExternalPlayer();
|
stopExternalPlayer();
|
||||||
if (panelInfoRef.current.modal) {
|
if (panelInfoRef.current.modal) {
|
||||||
// 모달 모드에서는 종료 후 화면을 유지하고 Back 아이콘으로 포커스 이동
|
// 모달 모드에서는 종료 후 화면을 유지하고 Back 아이콘으로 포커스 이동
|
||||||
@@ -2582,7 +2614,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
|
|
||||||
if (lastFocusedTargetId) {
|
if (lastFocusedTargetId) {
|
||||||
// ShopNowContents가 렌더링될 때까지 잠시 대기 후 포커스 복원
|
// ShopNowContents가 렌더링될 때까지 잠시 대기 후 포커스 복원
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
dlog('[PlayerPanel] 🔍 500ms 후 포커스 복원 시도:', lastFocusedTargetId);
|
dlog('[PlayerPanel] 🔍 500ms 후 포커스 복원 시도:', lastFocusedTargetId);
|
||||||
Spotlight.focus(lastFocusedTargetId);
|
Spotlight.focus(lastFocusedTargetId);
|
||||||
}, 500);
|
}, 500);
|
||||||
@@ -2591,6 +2623,10 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
// 한 번 처리한 복귀 플래그는 즉시 해제해 중복 영향을 막는다.
|
// 한 번 처리한 복귀 플래그는 즉시 해제해 중복 영향을 막는다.
|
||||||
prevIsTopPanelDetailFromPlayerRef.current = false;
|
prevIsTopPanelDetailFromPlayerRef.current = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
isOnTop,
|
isOnTop,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 40px;
|
bottom: 30px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
max-width: 455px;
|
max-width: 455px;
|
||||||
height: 92px;
|
height: 92px;
|
||||||
padding: 10px 10px 10px 10px;
|
padding: 10px 10px 10px 10px;
|
||||||
margin-bottom: 50px;
|
margin-bottom: 10px;
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(0, 0, 0, 0.3);
|
||||||
border: 1px solid rgba(234, 234, 234, 0.3);
|
border: 1px solid rgba(234, 234, 234, 0.3);
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
|
|||||||
@@ -1987,35 +1987,25 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
|||||||
/**
|
/**
|
||||||
* LOG 용도,
|
* LOG 용도,
|
||||||
* 검색 시 로그를 보내는 용도의 이펙트
|
* 검색 시 로그를 보내는 용도의 이펙트
|
||||||
* 우선 주석처리 (계속보내는부분에 대한 처리 필요)
|
|
||||||
*/
|
*/
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// const result = Object.values(searchDatas).reduce((acc, curr) => {
|
const result = Object.values(searchDatas).reduce((acc, curr) => {
|
||||||
// return acc + curr.length;
|
return acc + curr.length;
|
||||||
// }, 0);
|
}, 0);
|
||||||
|
|
||||||
// if (searchQuery) {
|
if (searchQuery) {
|
||||||
// dispatch(
|
dispatch(
|
||||||
// sendLogTotalRecommend({
|
sendLogTotalRecommend({
|
||||||
// query: searchQuery,
|
query: searchQuery,
|
||||||
// searchType: searchPerformed ? 'query' : 'keyword',
|
searchType: searchPerformed ? 'query' : 'keyword',
|
||||||
// result: result,
|
result: result,
|
||||||
// contextName: LOG_CONTEXT_NAME.SEARCH,
|
contextName: LOG_CONTEXT_NAME.SEARCH,
|
||||||
// messageId: LOG_MESSAGE_ID.SEARCH_ITEM,
|
messageId: LOG_MESSAGE_ID.SEARCH_ITEM,
|
||||||
// })
|
})
|
||||||
// );
|
);
|
||||||
|
}
|
||||||
// // 검색 완료 후 결과에 따른 Toast 표시
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
// // if (searchPerformed && searchQuery.trim()) {
|
}, [searchDatas, searchPerformed, searchQuery]);
|
||||||
// // if (result > 0) {
|
|
||||||
// // dispatch(showSearchSuccessToast(searchQuery, result));
|
|
||||||
// // } else {
|
|
||||||
// // dispatch(showSearchErrorToast(searchQuery));
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
// }, [searchDatas, searchPerformed, searchQuery]);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clean up 용도
|
* clean up 용도
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import css from './UserReviewPanel.module.less';
|
|||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, dwarn, derror /* eslint-disable-line no-unused-vars */ } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
|
||||||
// 버전에 따른 UI 설정
|
// 버전에 따른 UI 설정
|
||||||
const VERSION_LABEL = REVIEW_VERSION === 1 ? '[v1 - 기존 API]' : '[v2 - 신 API]';
|
const VERSION_LABEL = REVIEW_VERSION === 1 ? '[v1 - 기존 API]' : '[v2 - 신 API]';
|
||||||
@@ -41,8 +41,8 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
|
|||||||
userReviewPanelTotalPages,
|
userReviewPanelTotalPages,
|
||||||
goToNextUserReviewPage,
|
goToNextUserReviewPage,
|
||||||
goToPrevUserReviewPage,
|
goToPrevUserReviewPage,
|
||||||
applyRatingFilter,
|
applyRatingFilter, // eslint-disable-line no-unused-vars
|
||||||
applySentimentFilter,
|
applySentimentFilter, // eslint-disable-line no-unused-vars
|
||||||
clearAllFilters,
|
clearAllFilters,
|
||||||
currentFilter,
|
currentFilter,
|
||||||
filterCounts,
|
filterCounts,
|
||||||
@@ -50,10 +50,10 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
|
|||||||
_debug,
|
_debug,
|
||||||
// 🎯 API 기반 필터링 데이터
|
// 🎯 API 기반 필터링 데이터
|
||||||
filters,
|
filters,
|
||||||
filteredReviewListData,
|
filteredReviewListData, // eslint-disable-line no-unused-vars
|
||||||
currentReviewFilter,
|
currentReviewFilter,
|
||||||
// 전체 리뷰 데이터 (팝업용)
|
// 전체 리뷰 데이터 (팝업용)
|
||||||
allReviews,
|
allReviews, // eslint-disable-line no-unused-vars
|
||||||
filteredReviews, // ✅ 필터링된 전체 리뷰 (팝업에서 사용)
|
filteredReviews, // ✅ 필터링된 전체 리뷰 (팝업에서 사용)
|
||||||
getReviewsWithImages,
|
getReviewsWithImages,
|
||||||
extractImagesFromReviews,
|
extractImagesFromReviews,
|
||||||
@@ -226,7 +226,15 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
|
|||||||
return sentimentMap;
|
return sentimentMap;
|
||||||
}, [filters]);
|
}, [filters]);
|
||||||
|
|
||||||
// API 기반 별점 필터 핸들러
|
const getApiKeywordClickHandler = useCallback(
|
||||||
|
(keywordValue) => () => handleApiKeywordsFilter(keywordValue),
|
||||||
|
[handleApiKeywordsFilter]
|
||||||
|
);
|
||||||
|
|
||||||
|
const getApiSentimentClickHandler = useCallback(
|
||||||
|
(sentimentValue) => () => handleApiSentimentFilter(sentimentValue),
|
||||||
|
[handleApiSentimentFilter]
|
||||||
|
);
|
||||||
const handleApiRatingFilter = useCallback(
|
const handleApiRatingFilter = useCallback(
|
||||||
(rating) => {
|
(rating) => {
|
||||||
if (!prdtId || !patnrId) {
|
if (!prdtId || !patnrId) {
|
||||||
@@ -621,7 +629,7 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
|
|||||||
<FilterItemButton
|
<FilterItemButton
|
||||||
key={keyword.filterTpVal}
|
key={keyword.filterTpVal}
|
||||||
text={`${keyword.filterNm} (${keyword.filterNmCnt})`}
|
text={`${keyword.filterNm} (${keyword.filterNmCnt})`}
|
||||||
onClick={() => handleApiKeywordsFilter(keyword.filterTpVal)}
|
onClick={getApiKeywordClickHandler(keyword.filterTpVal)}
|
||||||
spotlightId={`filter-keyword-${index}`}
|
spotlightId={`filter-keyword-${index}`}
|
||||||
ariaLabel={`Filter by ${keyword.filterNm} keyword`}
|
ariaLabel={`Filter by ${keyword.filterNm} keyword`}
|
||||||
dataSpotlightUp={
|
dataSpotlightUp={
|
||||||
@@ -693,7 +701,7 @@ const UserReviewPanel = ({ className, panelInfo, spotlightId }) => {
|
|||||||
<FilterItemButton
|
<FilterItemButton
|
||||||
key={sentiment}
|
key={sentiment}
|
||||||
text={`${sentiment.charAt(0).toUpperCase() + sentiment.slice(1)} (${count})`}
|
text={`${sentiment.charAt(0).toUpperCase() + sentiment.slice(1)} (${count})`}
|
||||||
onClick={() => handleApiSentimentFilter(sentiment)}
|
onClick={getApiSentimentClickHandler(sentiment)}
|
||||||
spotlightId={`filter-sentiment-${sentiment}`}
|
spotlightId={`filter-sentiment-${sentiment}`}
|
||||||
ariaLabel={`Filter by ${sentiment} sentiment`}
|
ariaLabel={`Filter by ${sentiment} sentiment`}
|
||||||
dataSpotlightUp={
|
dataSpotlightUp={
|
||||||
|
|||||||
Reference in New Issue
Block a user