[251123] Merge: develop_si base로 develop을 merge함

This commit is contained in:
2025-11-23 18:45:09 +09:00
45 changed files with 1059 additions and 315 deletions

View File

@@ -266,6 +266,11 @@ export const handleDeepLink = (contentTarget) => (dispatch, getState) => {
deeplink: deeplinkPanel,
curationId: curationId ? curationId : showId,
productId: prdtId,
partnerID: patnrId,
showId: showId,
channelId: chanId,
category: lgCatNm,
linkTypeCode: linkTpCd,
})
);

View File

@@ -3,6 +3,7 @@
import { Job } from '@enact/core/util';
import Spotlight from '@enact/spotlight';
// <<<<<<< HEAD
import appinfo from '../../webos-meta/appinfo.json';
import appinfo35 from '../../webos-meta/appinfo35.json';
import appinfo79 from '../../webos-meta/appinfo79.json';
@@ -10,7 +11,19 @@ import { handleBypassLink } from '../App/bypassLinkHandler';
import * as lunaSend from '../lunaSend';
import { initialLocalSettings } from '../reducers/localSettingsReducer';
import * as Config from '../utils/Config';
import * as HelperMethods from '../utils/helperMethods';
import { types } from './actionTypes';
// =======
// import appinfo from "../../webos-meta/appinfo.json";
// import appinfo35 from "../../webos-meta/appinfo35.json";
// import appinfo79 from "../../webos-meta/appinfo79.json";
// import { handleBypassLink } from "../App/bypassLinkHandler";
// import * as lunaSend from "../lunaSend";
// import { initialLocalSettings } from "../reducers/localSettingsReducer";
// import * as Config from "../utils/Config";
// import * as HelperMethods from "../utils/helperMethods";
// import { types } from "./actionTypes";
// >>>>>>> gitlab/develop
export const changeAppStatus = (status) => ({
type: types.CHANGE_APP_STATUS,
@@ -31,6 +44,7 @@ export const gnbOpened = (status) => ({
payload: status,
});
// <<<<<<< HEAD
export const setShowPopup = (config, addPayload = {}) => {
let payload;
if (typeof config === 'string') {
@@ -39,6 +53,10 @@ export const setShowPopup = (config, addPayload = {}) => {
payload = config;
}
// =======
// export const setShowPopup = (config) => {
// const payload = typeof config === "string" ? { activePopup: config } : config;
// >>>>>>> gitlab/develop
return {
type: types.SET_SHOW_POPUP,
payload,
@@ -299,21 +317,24 @@ export const getTermsAgreeYn = () => (dispatch, getState) => {
try {
const { terms } = getState().home.termsData.data;
console.log("getTermsAgreeYn", terms.map(term => ({
trmsId: term.trmsId,
trmsTpCd: term.trmsTpCd,
trmsAgrFlag: term.trmsAgrFlag,
trmsPopFlag: term.trmsPopFlag,
})));
console.log(
"getTermsAgreeYn",
terms.map((term) => ({
trmsId: term.trmsId,
trmsTpCd: term.trmsTpCd,
trmsAgrFlag: term.trmsAgrFlag,
trmsPopFlag: term.trmsPopFlag,
}))
);
// MST00405 선택약관 정보만 따로 출력
const optionalTerm = terms.find(term => term.trmsTpCd === 'MST00405');
const optionalTerm = terms.find((term) => term.trmsTpCd === "MST00405");
if (optionalTerm) {
console.log("getTermsAgreeYn MST00405 선택약관:", {
trmsId: optionalTerm.trmsId,
trmsTpCd: optionalTerm.trmsTpCd,
trmsAgrFlag: optionalTerm.trmsAgrFlag,
trmsPopFlag: optionalTerm.trmsPopFlag
trmsPopFlag: optionalTerm.trmsPopFlag,
});
} else {
console.log("getTermsAgreeYn MST00405 선택약관을 찾을 수 없습니다.");
@@ -507,10 +528,20 @@ export const requestLiveSubtitle =
export const addReservation = (data) => (dispatch) => {
lunaSend.addReservation(data, {
onSuccess: (res) => {
console.log(res);
console.log("addReservation success:", res);
// Optionally show success toast
if (res && res.returnValue) {
dispatch(alertToast("Reminder set successfully"));
}
},
onFailure: (err) => {
console.log(err);
console.error("addReservation failed:", err);
// Use the helper function for better error handling
const errorMessage = HelperMethods.getReservationErrorMessage(err);
dispatch(alertToast(errorMessage));
},
onComplete: () => {
console.log("addReservation completed");
},
});
};
@@ -701,8 +732,8 @@ export const getConnectionInfo = () => (dispatch, getState) => {
lunaSend.getConnectionInfo({
onSuccess: (res) => {
console.log("lunasend getConnectionStatus", res);
if (res && res.retrunValue) {
const macAddress = res?.wiredInfo.macAddress;
if (res && res.returnValue) {
const macAddress = res?.wiredInfo?.macAddress;
console.log("macAddress...........", macAddress, res);
}
},
@@ -764,35 +795,37 @@ export const resetOptionalTermsSession = () => ({
// 선택약관 동의 처리를 위한 헬퍼 함수
export const handleOptionalTermsAgree = () => (dispatch) => {
console.log('[CommonActions] 선택약관 동의 처리');
dispatch(setOptionalTermsUserDecision('agreed'));
console.log("[CommonActions] 선택약관 동의 처리");
dispatch(setOptionalTermsUserDecision("agreed"));
dispatch(setOptionalTermsPopupShown(true));
};
// 선택약관 거절 처리를 위한 헬퍼 함수
export const handleOptionalTermsDecline = () => (dispatch) => {
console.log('[CommonActions] 선택약관 거절 처리');
dispatch(setOptionalTermsUserDecision('declined'));
console.log("[CommonActions] 선택약관 거절 처리");
dispatch(setOptionalTermsUserDecision("declined"));
dispatch(setOptionalTermsPopupShown(true));
};
// 선택약관 상태 통합 업데이트 (TV 환경 최적화 - API 호출 없이 즉시 반영)
export const updateOptionalTermsAgreement = (agreed = true) => (dispatch) => {
console.log(`[CommonActions] 선택약관 통합 상태 업데이트: ${agreed}`);
export const updateOptionalTermsAgreement =
(agreed = true) =>
(dispatch) => {
console.log(`[CommonActions] 선택약관 통합 상태 업데이트: ${agreed}`);
// 1. optionalTermsPopupFlow 업데이트 (TV 환경용)
dispatch(setOptionalTermsUserDecision(agreed ? 'agreed' : 'declined'));
dispatch(setOptionalTermsPopupShown(true));
// 1. optionalTermsPopupFlow 업데이트 (TV 환경용)
dispatch(setOptionalTermsUserDecision(agreed ? "agreed" : "declined"));
dispatch(setOptionalTermsPopupShown(true));
// 2. 기본 optionalTermsAgree 상태 직접 업데이트 (API 호출 없이)
dispatch({
type: types.UPDATE_OPTIONAL_TERMS_AGREE_DIRECT,
payload: agreed
});
// 2. 기본 optionalTermsAgree 상태 직접 업데이트 (API 호출 없이)
dispatch({
type: types.UPDATE_OPTIONAL_TERMS_AGREE_DIRECT,
payload: agreed,
});
// 3. termsAgreementStatus도 동기화
dispatch({
type: types.UPDATE_TERMS_AGREEMENT_STATUS_DIRECT,
payload: { MST00405: agreed }
});
};
// 3. termsAgreementStatus도 동기화
dispatch({
type: types.UPDATE_TERMS_AGREEMENT_STATUS_DIRECT,
payload: { MST00405: agreed },
});
};

View File

@@ -234,13 +234,23 @@ export const getSubCategory =
export const continueGetSubCategory = (key, pageNo) => (dispatch, getState) => {
if (!lastSubCategoryParams) {
// <<<<<<< HEAD
console.warn('No previous category parameters found');
// =======
// console.warn("No previous category parameters found");
// >>>>>>> gitlab/develop
return;
}
const subCategoryData = getState().main.subCategoryData;
const targetData =
// <<<<<<< HEAD
subCategoryData[key]?.subCatItemList || subCategoryData[key]?.subCatShowList || [];
// =======
// subCategoryData[key]?.subCatItemList ||
// subCategoryData[key]?.subCatShowList ||
// [];
// >>>>>>> gitlab/develop
const totalCount = subCategoryData[key]?.total ?? 0;
const startIndex = CATEGORY_DATA_MAX_RESULTS_LIMIT * (pageNo - 1);
if (
@@ -251,7 +261,13 @@ export const continueGetSubCategory = (key, pageNo) => (dispatch, getState) => {
//ignore query
return;
}
// <<<<<<< HEAD
dispatch(getSubCategory({ ...lastSubCategoryParams }, pageNo, getSubCategoryKey));
// =======
// dispatch(
// getSubCategory({ ...lastSubCategoryParams }, pageNo, getSubCategoryKey)
// );
// >>>>>>> gitlab/develop
};
const clearSubCategory = () => ({
@@ -325,7 +341,11 @@ export const getMainYouMayLike =
getState,
'get',
URLS.GET_YOUMAYLIKE,
// <<<<<<< HEAD
{ lgCatCd, exclCurationId, exclPatnrId, exclPrdtId, catDpTh3, catDpTh4 },
// =======
// { lgCatCd, catDpTh3, catDpTh4, exclCurationId, exclPatnrId, exclPrdtId },
// >>>>>>> gitlab/develop
{},
onSuccess,
onFail

View File

@@ -182,8 +182,22 @@ export const deleteMyFavorite = (params) => (dispatch, getState) => {
// MyPage 약관 철회 (IF-LGSP-032)
export const setMyTermsWithdraw =
(params, callback) => (dispatch, getState) => {
let localMacAddress;
const { mandatoryIncludeYn, termsList } = params;
// 약관철회 파라미터 추가 로그 요청
const httpHeader = getState().common.httpHeader;
const macAddress = getState().common.macAddress;
const userNumber = getState().common.appStatus.loginUserData?.userNumber;
const macAddr = macAddress?.wired || macAddress?.wifi || macAddress?.p2p;
if (typeof window === "object" && !window.PalmSystem) {
localMacAddress = "00:1A:2B:3C:4D:5E";
}
const logCreateTime = new Date().toISOString();
const xDeviceProduct = httpHeader["X-Device-Product"] || httpHeader.prod_cd;
const onSuccess = (response) => {
console.log("setMyTermsWithdraw onSuccess ", response.data);
@@ -199,13 +213,22 @@ export const setMyTermsWithdraw =
console.error("setMyTermsWithdraw onFail ", error);
};
const requestData = {
mandatoryIncludeYn,
termsList,
xDeviceProduct,
macAddr: macAddr ? macAddr : localMacAddress,
userNumber: userNumber || "",
requestTime: logCreateTime,
};
TAxios(
dispatch,
getState,
"post",
URLS.SET_MY_TERMS_WITHDRAW,
{},
{ mandatoryIncludeYn, termsList },
requestData,
onSuccess,
onFail
);
@@ -223,14 +246,17 @@ export const setMyPageTermsAgree =
// 약관 ID를 약관 코드로 변환하기 위해 state에서 termsIdMap 조회
const termsIdMap = getState().home.termsIdMap || {};
const idToCodeMap = Object.entries(termsIdMap).reduce((acc, [code, id]) => {
acc[id] = code;
return acc;
}, {});
const idToCodeMap = Object.entries(termsIdMap).reduce(
(acc, [code, id]) => {
acc[id] = code;
return acc;
},
{}
);
// 동의한 약관 ID 목록을 약관 코드로 변환
const agreedTermCodes = termsList
.map(id => idToCodeMap[id])
.map((id) => idToCodeMap[id])
.filter(Boolean);
dispatch({

View File

@@ -176,7 +176,8 @@ export default function MobileSendPopUp({
if (rawPhoneNumber.length === getMaxNum(deviceCountryCode)) {
Spotlight.focus("agreeAndSend");
}
if (rawPhoneNumber.length > getMaxNum(deviceCountryCode)) {
// 테스트용: 12자리까지 허용
if (rawPhoneNumber.length > 12) {
return;
}
const phoneUtil = PhoneNumberUtil.getInstance();
@@ -327,7 +328,12 @@ export default function MobileSendPopUp({
const handleAgreeSendClick = useCallback(() => {
let naturalNumber = mobileNumber.replace(/\D/g, "");
if (!mobileNumber || naturalNumber.length < getMaxNum(deviceCountryCode)) {
// 테스트용: 길이 체크를 더 유연하게 (10자리 또는 11자리 허용)
if (
!mobileNumber ||
naturalNumber.length < 10 ||
naturalNumber.length > 12
) {
setSmsRetCode(907);
return;
}
@@ -405,7 +411,6 @@ export default function MobileSendPopUp({
if (smsTpCd === "APP00204") {
params = { ...params, curationId };
}
dispatch(sendSms(params));
}
// EVT00101 & APP00207(welcome) EVT00103 & APP00209 (welcome+Prizes) : smsTpCd 값을 받지 않음

View File

@@ -1,11 +1,9 @@
// src/components/TCheckBox/TCheckBoxSquare.module.less
@SQUARE_BORDER_DEFAULT: #CCCCCC;
@SQUARE_BORDER_ACTIVE: #C70850;
@SQUARE_BG_SELECTED: #7A808D;
@SQUARE_BORDER_DEFAULT: #cccccc;
@SQUARE_BORDER_ACTIVE: #c70850;
@SQUARE_BG_SELECTED: #7a808d;
// @SQUARE_BG_SELECTED: #C70850;
;
.tCheckBoxSquare {
min-width: 45px !important;
min-height: 45px !important;
@@ -17,17 +15,19 @@
position: relative;
box-sizing: border-box;
cursor: pointer;
transition: background 0.15s, border 0.15s !important;
transition:
background 0.15s,
border 0.15s !important;
&:hover,
&:focus,
&.focus {
border-color: @SQUARE_BORDER_ACTIVE !important;
border-width: 4px !important; // 🔥 포커스 시 굵은 테두리
border-width: 4px !important; // 🔥 포커스 시 굵은 테두리
}
&::before {
content: '';
content: "";
position: absolute;
top: 50%;
left: 50%;
@@ -53,6 +53,7 @@
border-color: @SQUARE_BORDER_ACTIVE !important;
border-width: 4px !important;
background-color: @SQUARE_BG_SELECTED !important;
&::before {
transform: translate(-50%, -70%) rotate(-45deg) scale(1);
}

View File

@@ -1,4 +1,11 @@
import React, { memo, useCallback, useEffect, useMemo, useState } from "react";
import React, {
memo,
use,
useCallback,
useEffect,
useMemo,
useState,
} from "react";
import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";
@@ -81,6 +88,8 @@ export default memo(function TItemCard({
nowProductId,
nowCategory,
nowProductTitle,
showId,
showTitle,
contentId,
version = 1,
...rest
@@ -131,6 +140,8 @@ export default memo(function TItemCard({
shelfTitle: shelfTitle,
productId: productId,
productTitle: productName,
showId: showId,
showTitle: showTitle,
nowProductId: nowProductId,
nowCategory: nowCategory,
nowProductTitle: nowProductTitle,
@@ -144,7 +155,6 @@ export default memo(function TItemCard({
curationId: curationId,
curationTitle: curationTitle,
};
console.log("###shelfContentClick", params);
dispatch(sendLogTotalRecommend(params));
}
}

View File

@@ -910,9 +910,9 @@
.optionalConfirmInfo {
width: 100vw;
height: 198px;
background-color: #E6EBF0;
background-color: #e6ebf0;
border-radius: 4px;
box-shadow: 0px 20px 12px rgba(0, 0, 0, 0.30);
box-shadow: 0px 20px 12px rgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
box-sizing: border-box;
@@ -963,7 +963,7 @@
padding: 0 20px !important;
margin: 0 !important;
background: white !important;
border: 1px solid #CFCFCF !important;
border: 1px solid #cfcfcf !important;
border-radius: 4px !important;
display: flex !important;
align-items: center !important;
@@ -973,15 +973,15 @@
// 포커스 스타일
&:focus {
outline: 2px solid #C70850 !important;
outline-offset: 1px !important;
outline: 2px solid #c70850;
outline-offset: -1px;
}
.optionalTermsTitle {
height: 100%;
color: #1A1A1A;
color: #1a1a1a;
font-size: 22px;
font-family: 'LG Smart UI';
font-family: "LG Smart UI";
font-weight: 600;
line-height: 22px;
white-space: nowrap;
@@ -995,7 +995,7 @@
width: 24px;
height: 24px;
border-radius: 50%;
border: 2px solid #1A1A1A;
border: 2px solid #1a1a1a;
display: flex;
align-items: center;
justify-content: center;
@@ -1003,10 +1003,10 @@
margin-left: 8px;
&::after {
content: '>';
content: ">";
font-size: 14px;
font-weight: bold;
color: #1A1A1A;
color: #1a1a1a;
}
}
}
@@ -1037,8 +1037,8 @@
.figmaTermsInfo {
.size(@w: 1064px, @h: 750px);
padding: 60px 57px 40px;
background: #E6EBF0;
box-shadow: 0px 20px 12px rgba(0, 0, 0, 0.30);
background: #e6ebf0;
box-shadow: 0px 20px 12px rgba(0, 0, 0, 0.3);
border-radius: 4px;
}
@@ -1051,7 +1051,7 @@
.figmaTermsCard {
background: white;
border-radius: 4px;
border: 1px solid #CCCCCC;
border: 1px solid #cccccc;
overflow: hidden;
display: flex;
flex-direction: column;
@@ -1059,11 +1059,11 @@
.figmaTermsTitleBar {
padding: 17px 31px;
border-bottom: 1px solid #CCCCCC;
border-bottom: 1px solid #cccccc;
}
.figmaTermsTitleText {
color: #C70850;
color: #c70850;
font-size: 30px;
font-weight: 700;
}

View File

@@ -236,56 +236,108 @@ export const setSubtitleEnableOver5 = (
}
};
// system Alert
// system Alert with time validation
export const addReservation = (data, { onSuccess, onFailure, onComplete }) => {
if (typeof window === "object" && !window.PalmSystem) {
console.log("LUNA SEND addReservation data", data);
return;
}
return new LS2Request().send({
service: "luna://com.webos.service.tvReservationAgent",
method: "add",
parameters: {
scheduleType: "LGShopping",
startTime: {
year: data.startTime.year,
month: data.startTime.month,
day: data.startTime.day,
hour: data.startTime.hour,
minute: data.startTime.minute,
second: data.startTime.second,
},
callback: {
method: "luna://com.webos.notification/createAlert",
params: {
message: data.params.message,
buttons: [
{
label: data.params.buttons[0].label,
onclick: "luna://com.webos.applicationManager/launch",
params: {
id: window.PalmSystem.identifier ?? appinfo.id,
params: data.params.launch,
const createReservation = () => {
return new LS2Request().send({
service: "luna://com.webos.service.tvReservationAgent",
method: "add",
parameters: {
scheduleType: "LGShopping",
startTime: {
year: data.startTime.year,
month: data.startTime.month,
day: data.startTime.day,
hour: data.startTime.hour,
minute: data.startTime.minute,
second: data.startTime.second,
},
callback: {
method: "luna://com.webos.notification/createAlert",
params: {
message: data.params.message,
buttons: [
{
label: data.params.buttons[0].label,
onclick: "luna://com.webos.applicationManager/launch",
params: {
id: window.PalmSystem.identifier ?? appinfo.id,
params: data.params.launch,
},
},
},
{
label: data.params.buttons[1].label,
},
],
autoTimeout: 30,
{
label: data.params.buttons[1].label,
},
],
autoTimeout: 30,
},
},
information: {
showId: data.params.showId,
chanId: data.params.chanId,
},
},
information: {
showId: data.params.showId,
chanId: data.params.chanId,
onSuccess,
onFailure: (err) => {
console.log("LUNA SEND addReservation failed", err);
// Check if error is related to invalid current time
if (
err &&
err.errorText &&
err.errorText.includes("Invalid current time")
) {
console.log(
"Invalid current time error detected, will retry after time validation"
);
// Don't call onFailure immediately, let the retry logic handle it
return;
}
onFailure(err);
},
},
onSuccess,
onFailure,
onComplete,
});
onComplete,
});
};
// First, validate system time before creating reservation
const validateTimeAndCreateReservation = (retryCount = 0, maxRetries = 3) => {
console.log(`LUNA SEND validating system time, attempt ${retryCount + 1}`);
getSystemTime({
onSuccess: (timeRes) => {
console.log("LUNA SEND system time validation success", timeRes);
// Time is available, proceed with reservation
createReservation();
},
onFailure: (timeErr) => {
console.log("LUNA SEND system time validation failed", timeErr);
if (retryCount < maxRetries) {
// Retry with exponential backoff
const delay = Math.min(1000 * Math.pow(2, retryCount), 5000); // Max 5 seconds
console.log(`LUNA SEND retrying time validation in ${delay}ms`);
setTimeout(() => {
validateTimeAndCreateReservation(retryCount + 1, maxRetries);
}, delay);
} else {
console.log("LUNA SEND max retries exceeded for time validation");
// Still try to create reservation as fallback
createReservation();
}
},
onComplete: () => {
console.log("LUNA SEND system time validation complete");
},
});
};
// Start the validation and reservation process
validateTimeAndCreateReservation();
};
export const deleteReservationCallback = (
@@ -454,3 +506,48 @@ export const getConnectionInfo = ({ onSuccess, onFailure, onComplete }) => {
});
}
};
// Check system time availability
export const getSystemTime = ({ onSuccess, onFailure, onComplete }) => {
if (typeof window === "object" && !window.PalmSystem) {
console.log("LUNA SEND getSystemTime - mock environment");
onSuccess({ returnValue: true, utc: Date.now() / 1000 });
return;
}
return new LS2Request().send({
service: "luna://com.webos.settingsservice",
method: "getSystemSettings",
subscribe: false,
parameters: {
category: "time",
keys: ["autoClock"],
},
onSuccess: (res) => {
console.log("LUNA SEND getSystemTime success", res);
if (res && res.returnValue) {
// If autoClock is available, try to get actual time
new LS2Request().send({
service: "luna://com.webos.service.systemservice",
method: "clock/getTime",
subscribe: false,
parameters: {},
onSuccess: (timeRes) => {
console.log("LUNA SEND clock/getTime success", timeRes);
onSuccess(timeRes);
},
onFailure: (timeErr) => {
console.log("LUNA SEND clock/getTime failed", timeErr);
// Fallback to settings response if getTime fails
onSuccess(res);
},
onComplete,
});
} else {
onFailure(res);
}
},
onFailure,
onComplete,
});
};

View File

@@ -20,7 +20,8 @@ const initialState = {
},
broadcast: {},
httpHeader: null,
isGnbOpened: false, popup: {
isGnbOpened: false,
popup: {
popupVisible: false,
activePopup: null,
secondaryPopup: null,
@@ -32,7 +33,7 @@ const initialState = {
optionalTermsConfirmSelected: false,
},
termsFlag: null,
termsLoading: false, // 25.06.16 추가
termsLoading: false, // 25.06.16 추가
introTermsAgree: undefined, // Y, N
checkoutTermsAgree: undefined,
useLog: true,
@@ -85,9 +86,9 @@ const initialState = {
// 선택약관 팝업 상태 관리 (TV 환경 최적화)
optionalTermsPopupFlow: {
popupShown: false, // 팝업 표시 여부
userDecision: null, // 'agreed' | 'declined' | null
agreedInSession: false, // 세션 내 동의 여부 (로컬 상태 기반)
popupShown: false, // 팝업 표시 여부
userDecision: null, // 'agreed' | 'declined' | null
agreedInSession: false, // 세션 내 동의 여부 (로컬 상태 기반)
},
};
@@ -184,7 +185,8 @@ export const commonReducer = (state = initialState, action) => {
secondaryPopupVisible: false,
secondaryPopup: null,
},
}; case types.SET_HIDE_SECONDARY_POPUP:
};
case types.SET_HIDE_SECONDARY_POPUP:
return {
...state,
popup: {
@@ -233,8 +235,13 @@ export const commonReducer = (state = initialState, action) => {
}
case types.GET_TERMS_AGREE_YN_SUCCESS: {
const { privacyTerms, serviceTerms, purchaseTerms, paymentTerms, optionalTerms } =
action.payload;
const {
privacyTerms,
serviceTerms,
purchaseTerms,
paymentTerms,
optionalTerms,
} = action.payload;
const introTermsAgree = privacyTerms === "Y" && serviceTerms === "Y";
const checkoutTermsAgree = purchaseTerms === "Y" && paymentTerms === "Y";
@@ -262,9 +269,11 @@ export const commonReducer = (state = initialState, action) => {
case types.GET_HOME_TERMS: {
const newTermsStatus = { ...state.termsAgreementStatus };
if (action.payload?.data?.terms) {
action.payload.data.terms.forEach(term => {
if (Object.prototype.hasOwnProperty.call(newTermsStatus, term.trmsTpCd)) {
newTermsStatus[term.trmsTpCd] = term.trmsAgrFlag === 'Y';
action.payload.data.terms.forEach((term) => {
if (
Object.prototype.hasOwnProperty.call(newTermsStatus, term.trmsTpCd)
) {
newTermsStatus[term.trmsTpCd] = term.trmsAgrFlag === "Y";
}
});
}
@@ -279,7 +288,7 @@ export const commonReducer = (state = initialState, action) => {
const newTermsStatus = { ...state.termsAgreementStatus };
// action payload에 담겨온 동의한 약관 코드 리스트를 기반으로 상태 업데이트
if (action.payload?.agreedTermCodes) {
action.payload.agreedTermCodes.forEach(termCode => {
action.payload.agreedTermCodes.forEach((termCode) => {
if (Object.prototype.hasOwnProperty.call(newTermsStatus, termCode)) {
newTermsStatus[termCode] = true;
}
@@ -288,7 +297,7 @@ export const commonReducer = (state = initialState, action) => {
return {
...state,
termsLoading: false,
termsAgreementStatus: newTermsStatus
termsAgreementStatus: newTermsStatus,
};
}
case types.SET_MYPAGE_TERMS_AGREE_FAIL:
@@ -310,7 +319,7 @@ export const commonReducer = (state = initialState, action) => {
...state.termsAgreementStatus,
MST00401: true,
MST00402: true,
}
},
};
} else {
return state;
@@ -398,7 +407,7 @@ export const commonReducer = (state = initialState, action) => {
optionalTermsPopupFlow: {
...state.optionalTermsPopupFlow,
userDecision: action.payload,
agreedInSession: action.payload === 'agreed',
agreedInSession: action.payload === "agreed",
},
};
}

View File

@@ -587,6 +587,7 @@ export const ERROR_MESSAGES_GROUPS = [
];
export const LOG_CONTEXT_NAME = {
// <<<<<<< HEAD
SHOPTIME: 'shoptime',
HOME: 'shoptime.home',
CHECKOUT: 'shoptime.checkout',
@@ -608,6 +609,29 @@ export const LOG_CONTEXT_NAME = {
ENTRY: 'shoptime.entry',
MYORDER: 'shoptime.myorder',
DETAILPAGE: 'shoptime.detailpage',
// =======
// SHOPTIME: "shoptime",
// HOME: "shoptime.home",
// CHECKOUT: "shoptime.checkout",
// PINCODE: "shoptime.pincode",
// YOUMAYLIKE: "shoptime.youmayalsolike",
// SHOW: "shoptime.show",
// SHOPBYMOBILE: "shoptime.shopbymobile",
// GNB: "shoptime.gnb",
// REMINDERS: "shoptime.reminders",
// MYPAGE: "shoptime.mypage",
// FEATURED_BRANDS: "shoptime.featuredpartner",
// MYINFO: "shoptime.myinfo",
// ON_SALE: "shoptime.onsale",
// TRENDING_NOW: "shoptime.trendingnow",
// HOT_PICKS: "shoptime.hotpicks",
// SEARCH: "shoptime.search",
// THEME_CURATION: "shoptime.themecuration",
// CATEGORY: "shoptime.category",
// ENTRY: "shoptime.entry",
// MYORDER: "shoptime.myorder",
// DETAILPAGE: "shoptime.detailpage",
// >>>>>>> gitlab/develop
};
export const LOG_MESSAGE_ID = {

View File

@@ -530,3 +530,45 @@ export const getErrorMessage = (errorCode, retMsg, retDetailCode, returnBindStri
return errorPrefix + 'An unknown error occurred. Please try again later.';
}
};
/**
* Check if the reservation error is related to system time issues
* @param {Object} error - The error object from Luna service
* @returns {boolean} - True if error is time-related
*/
export const isTimeRelatedError = (error) => {
if (!error) return false;
const timeErrorPatterns = [
"Invalid current time",
"Fail to get Current Time",
"time not available",
"clock not set",
];
const errorText = error.errorText || error.message || "";
return timeErrorPatterns.some((pattern) =>
errorText.toLowerCase().includes(pattern.toLowerCase())
);
};
/**
* Get user-friendly error message for reservation failures
* @param {Object} error - The error object from Luna service
* @returns {string} - User-friendly error message
*/
export const getReservationErrorMessage = (error) => {
if (!error) return $L("Failed to set reminder. Please try again.");
if (isTimeRelatedError(error)) {
return $L(
"Unable to set reminder: System time not available. Please check your TV's time settings and try again."
);
}
if (error.errorText) {
return $L(`Failed to set reminder: ${error.errorText}`);
}
return $L("Failed to set reminder. Please try again.");
};

View File

@@ -351,8 +351,8 @@ const CategoryPanel = ({ panelInfo, isOnTop, spotlightId }) => {
...params,
category: categoryShowInfos?.catNm,
partner: findPartnerName(patnrId),
contentId: showId,
contentTitle: showNm,
showId: showId,
showTitle: showNm,
});
}
@@ -365,8 +365,8 @@ const CategoryPanel = ({ panelInfo, isOnTop, spotlightId }) => {
...params,
category: categoryShowInfos?.catNm,
partner: findPartnerName(topShowInfo?.patnrId),
productId: prdtId,
productTitle: prdtNm,
showId: prdtId,
showTitle: prdtNm,
price: discountRate ? discountPrice : regularPrice,
discount: discountRate,
});
@@ -379,8 +379,8 @@ const CategoryPanel = ({ panelInfo, isOnTop, spotlightId }) => {
...params,
category: categoryShowInfos?.catNm,
partner: findPartnerName(patnrId),
contentId: showId,
contentTitle: showNm,
showId: showId,
showTitle: showNm,
});
}

View File

@@ -12,6 +12,7 @@ import { getMainCategoryDetail, getMainYouMayLike } from '../../actions/mainActi
import { finishModalMediaForce } from '../../actions/mediaActions';
import { popPanel, updatePanel } from '../../actions/panelActions';
import {
// <<<<<<< HEAD
finishVideoPreview,
pauseFullscreenVideo,
resumeFullscreenVideo,
@@ -30,6 +31,45 @@ import THeaderCustom from './components/THeaderCustom';
import css from './DetailPanel.module.less';
import ProductAllSection from './ProductAllSection/ProductAllSection';
import ThemeItemListOverlay from './ThemeItemListOverlay/ThemeItemListOverlay';
// =======
// changeAppStatus,
// changeLocalSettings,
// setHidePopup,
// } from "../../actions/commonActions";
// import { clearCouponInfo } from "../../actions/couponActions";
// import { getDeviceAdditionInfo } from "../../actions/deviceActions";
// import {
// clearThemeDetail,
// getThemeCurationDetailInfo,
// getThemeHotelDetailInfo,
// } from "../../actions/homeActions";
// import {
// getMainCategoryDetail,
// getMainYouMayLike,
// } from "../../actions/mainActions";
// import { popPanel, updatePanel } from "../../actions/panelActions";
// import { finishVideoPreview } from "../../actions/playActions";
// import {
// clearProductDetail,
// getProductGroup,
// getProductImageLength,
// getProductOptionId,
// } from "../../actions/productActions";
// import MobileSendPopUp from "../../components/MobileSend/MobileSendPopUp";
// import TBody from "../../components/TBody/TBody";
// import THeader from "../../components/THeader/THeader";
// import TPanel from "../../components/TPanel/TPanel";
// import * as Config from "../../utils/Config";
// import { panel_names } from "../../utils/Config";
// import { $L, getQRCodeUrl } from "../../utils/helperMethods";
// import css from "./DetailPanel.module.less";
// import GroupProduct from "./GroupProduct/GroupProduct";
// import SingleProduct from "./SingleProduct/SingleProduct";
// import ThemeProduct from "./ThemeProduct/ThemeProduct";
// import UnableProduct from "./UnableProduct/UnableProduct";
// import YouMayLike from "./YouMayLike/YouMayLike";
// import { now } from "lodash";
// >>>>>>> gitlab/develop
export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
const dispatch = useDispatch();
@@ -128,6 +168,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
const [productType, setProductType] = useState(null);
const [openThemeItemOverlay, setOpenThemeItemOverlay] = useState(false);
// <<<<<<< HEAD
const [scrollToSection, setScrollToSection] = useState(null);
const [pendingScrollSection, setPendingScrollSection] = useState(null);
const updateSelectedIndex = useCallback((newIndex) => {
@@ -138,12 +179,79 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
)()
);
}, []);
// =======
// useEffect(() => {
// if (lgCatCd) {
// dispatch(
// getMainYouMayLike({
// lgCatCd: lgCatCd,
// exclCurationId: panelInfo?.curationId,
// exclPatnrId: panelInfo?.patnrId,
// exclPrdtId: panelInfo?.prdtId,
// catDpTh3:
// panelInfo?.type === "theme"
// ? themeProductInfos[selectedIndex]?.catDpTh3
// : productData?.catDpTh3,
// catDpTh4:
// panelInfo?.type === "theme"
// ? themeProductInfos[selectedIndex]?.catDpTh4
// : productData?.catDpTh4,
// })
// );
// }
// }, [panelInfo?.curationId, panelInfo?.patnrId, panelInfo?.prdtId, lgCatCd]);
// >>>>>>> gitlab/develop
const updateThemeItemOverlay = useCallback((isOpen) => {
setOpenThemeItemOverlay(fp.pipe(() => isOpen, Boolean)());
}, []);
// <<<<<<< HEAD
const onSpotlightUpTButton = useCallback((e) => {
// =======
// useEffect(() => {
// if (
// themeProductInfos &&
// themeProductInfos.length > 0 &&
// panelInfo?.themePrdtId
// ) {
// for (let i = 0; i < themeProductInfos.length; i++) {
// if (themeProductInfos[i].prdtId === panelInfo?.themePrdtId) {
// setSelectedIndex(i);
// }
// }
// }
// if (hotelInfos && hotelInfos.length > 0 && panelInfo?.themeHotelId) {
// for (let i = 0; i < hotelInfos.length; i++) {
// if (hotelInfos[i].hotelId === panelInfo?.themeHotelId) {
// setSelectedIndex(i);
// }
// }
// }
// }, [
// themeProductInfos,
// hotelInfos,
// panelInfo?.themePrdtId,
// panelInfo?.themeHotelId,
// ]);
// const { detailUrl } = useMemo(() => {
// return getQRCodeUrl({
// serverHOST,
// serverType,
// index: deviceInfo?.dvcIndex,
// patnrId: productInfo?.patnrId,
// prdtId: productInfo?.prdtId,
// entryMenu: entryMenu,
// nowMenu: nowMenu,
// liveFlag: "Y",
// qrType: "billingDetail",
// });
// }, [serverHOST, serverType, deviceInfo, entryMenu, productInfo]);
// const onSpotlightUpTButton = (e) => {
// >>>>>>> gitlab/develop
e.stopPropagation();
Spotlight.focus('spotlightId_backBtn');
}, []);
@@ -1041,6 +1149,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
productInfo={productDataSource}
isOpen={openThemeItemOverlay}
panelInfo={panelInfo}
// <<<<<<< HEAD
productType={productType}
setSelectedIndex={updateSelectedIndex}
openThemeItemOverlay={openThemeItemOverlay}
@@ -1048,5 +1157,55 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
/>
</TPanel>
</div>
// =======
// setSelectedIndex={setSelectedIndex}
// p
// roductInfo={productData || themeProductInfos[selectedIndex]}
// setIsYouMayLikeOpened={setIsYouMayLikeOpened}
// />
// )}
// {activePopup === Config.ACTIVE_POPUP.smsPopup && (
// <MobileSendPopUp
// open={popupVisible}
// onClose={handleSMSonClose}
// title={$L("Send a purchase link for this item via SMS")}
// subTitle={mobileSendPopUpSubtitle}
// patncNm={
// panelInfo?.type === "theme" &&
// themeProductInfos &&
// themeProductInfos[selectedIndex]
// ? themeProductInfos[selectedIndex].patncNm
// : productData?.patncNm
// }
// productImg={mobileSendPopUpProductImg}
// patnrId={panelInfo?.patnrId}
// prdtId={
// panelInfo?.type === "theme" &&
// themeProductInfos &&
// themeProductInfos[selectedIndex]
// ? themeProductInfos[selectedIndex].prdtId
// : panelInfo?.prdtId
// }
// smsTpCd={panelInfo?.type === "hotel" ? "APP00205" : "APP00201"}
// curationId={panelInfo?.curationId}
// curationNm={panelInfo?.curationNm}
// hotelId={
// panelInfo?.type === "hotel" && hotelInfos[selectedIndex]?.hotelId
// }
// hotelNm={
// panelInfo?.type === "hotel" && hotelInfos[selectedIndex]?.hotelNm
// }
// hotelDtlUrl={
// panelInfo?.type === "hotel" &&
// hotelInfos[selectedIndex]?.hotelDetailInfo?.hotelDtlUrl
// }
// productPrice={panelInfo?.type === "hotel" && Price()}
// shopByMobileLogRef={shopByMobileLogRef}
// spotlightId="shopbymobile_Btn"
// smsText={productInfo?.pmtSuptYn === "Y" ? detailUrl : undefined}
// />
// )}
// </>
// >>>>>>> gitlab/develop
);
}

View File

@@ -1492,7 +1492,7 @@ export default function ProductAllSection({
<img src={arrowDownIcon} className={css.themeButtonIcon} />
</TButton>
</Container>
)}
)}
<DetailMobileSendPopUp
ismobileSendPopupOpen={mobileSendPopupOpen}

View File

@@ -453,7 +453,8 @@ export default function SingleOption({
}
if (userNumber && selectedPatnrId && selectedPrdtId && quantity) {
const { prodOptCval, priceInfo } = selectedOptions || {};
const { patncNm, brndNm, catNm, prdtNm, prdtId } = productInfo;
const { patncNm, brndNm, catNm, prdtNm, prdtId, showId, showNm } =
productInfo;
const regularPrice = priceInfo?.split("|")[0];
const discountPrice = priceInfo?.split("|")[1];
const discountRate = priceInfo?.split("|")[4];
@@ -470,6 +471,8 @@ export default function SingleOption({
category: catNm,
contextName: Config.LOG_CONTEXT_NAME.DETAILPAGE,
messageId: Config.LOG_MESSAGE_ID.BUY_NOW,
showId: showId ?? "",
showNm: showNm ?? "",
})
);
dispatch(

View File

@@ -96,13 +96,13 @@ export default function ShowOption({
inDt: formatGMTString(new Date()),
linkTpCd: panelInfo?.linkTpCd ?? "",
logTpNo: LOG_TP_NO.DETAIL.THEME_DETAIL,
patncNm: themeInfo?.patncNm ?? "",
patnrId: themeInfo?.patnrId ?? "",
patncNm: themeInfo?.productInfos[selectedIndex]?.patncNm ?? "",
patnrId: themeInfo?.productInfos[selectedIndex]?.patnrId ?? "",
};
detailLogParamsRef.current = params;
return () => dispatch(sendLogDetail(params));
dispatch(sendLogDetail(params));
}
}, [productData]);
@@ -172,22 +172,24 @@ export default function ShowOption({
}, [productData]);
const handleMobileSendPopupOpen = useCallback(() => {
if (productData && Object.keys(productData).length > 0) {
const regularPrice = productData?.priceInfo?.split("|")[0];
const discountPrice = productData?.priceInfo?.split("|")[1];
const discountRate = productData?.priceInfo?.split("|")[4];
if (showProductInfo && Object.keys(showProductInfo).length > 0) {
const regularPrice = showProductInfo?.priceInfo?.split("|")[0];
const discountPrice = showProductInfo?.priceInfo?.split("|")[1];
const discountRate = showProductInfo?.priceInfo?.split("|")[4];
const logParams = {
status: "open",
nowMenu: nowMenu,
partner: productData?.patncNm,
productId: productData?.prdtId,
productTitle: productData?.prdtNm,
partner: showProductInfo?.patncNm,
productId: showProductInfo?.prdtId,
productTitle: showProductInfo?.prdtNm,
price: discountRate ? discountPrice : regularPrice,
brand: productData?.brndNm,
brand: showProductInfo?.brndNm,
discount: discountRate,
category: productData?.catNm,
category: showProductInfo?.catNm,
contextName: LOG_CONTEXT_NAME.SHOPBYMOBILE,
messageId: LOG_MESSAGE_ID.SMB,
showId: showProductInfo?.showId ?? "",
showNm: showProductInfo?.showNm ?? "",
};
dispatch(sendLogTotalRecommend(logParams));
dispatch(
@@ -276,7 +278,7 @@ export default function ShowOption({
isBillingProductVisible={isBillingProductVisible}
isCall
isFullOption={showProductInfo?.pmtSuptYn === "Y"}
isDescription={!showProductInfo?.pmtSuptYn === "Y"}
isDescription={showProductInfo?.pmtSuptYn !== "Y"}
thumbnailUrl={showProductInfo?.imgUrls600[0]}
productInfo={showProductInfo}
/>

View File

@@ -215,6 +215,21 @@ export default function UnableOption({
</div>
);
} else if (TYPE_CASE.case2) {
if (
selectedPrdtId === "27LX6TYGA" &&
offerInfo &&
offerInfo?.length > 0
) {
return (
<div className={css.wrapper}>
<span
dangerouslySetInnerHTML={{
__html: offerInfo && offerInfo,
}}
/>
</div>
);
}
return (
<div className={css.wrapper}>
<div className={css.topLayer}>

View File

@@ -67,6 +67,7 @@ import Showroom from "./Showroom/Showroom";
import TodaysDeals from "./TodaysDeals/TodaysDeals";
import UpComing from "./UpComing/UpComing";
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
import { sortedIndexOf } from "lodash";
const STRING_CONF = {
CANCEL: "CANCEL",
@@ -318,29 +319,34 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
return;
}
const foundElement = sortedBrandLayoutInfo.find(
(el) => el.shptmBrndOptTpCd === containerId
);
const actualShelfOrder = foundElement ? foundElement.expsOrd : null;
const selectedBrand = `${LOG_MENU.FEATURED_BRANDS}/${selectedPatncNm}`;
const currentShelf = `${getMenuByContainerId(containerId)}`;
const menu =
selectedBrand && currentShelf && `${selectedBrand} ${currentShelf}`;
dispatch(sendLogGNB(menu));
dispatch(
sendLogTotalRecommend({
contextName: LOG_CONTEXT_NAME.FEATURED_BRANDS,
messageId: LOG_MESSAGE_ID.SHELF,
partner: selectedPatncNm,
shelfLocation: shelfOrder,
shelfLocation: actualShelfOrder,
shelfId: containerId,
shelfTitle: currentShelf,
})
);
dispatch(sendLogGNB(menu));
setIsLogGNBSent(true);
prevSelectedPatncNmRef.current = selectedPatncNm;
lastMenuRef.current = getMenuByContainerId(containerId);
},
[selectedPatncNm, sortedBrandLayoutInfo, selectedPatncNm]
[selectedPatncNm, sortedBrandLayoutInfo]
);
const focusOnMount = useCallback((targetId) => {

View File

@@ -46,6 +46,8 @@ const FeaturedCategoryContents = ({
spotlightId={spotlightId}
shelfOrder={shelfOrder}
shelfTitle={shelfTitle}
selectedPatncNm={selectedPatncNm}
catNm={catNm}
/>
) : (
<FeaturedCategoryProductGrid

View File

@@ -57,6 +57,8 @@ export default function FeaturedCategoryProductList({
spotlightId,
shelfTitle,
shelfOrder,
selectedPatncNm,
catNm,
}) {
const { getScrollTo, scrollLeft } = useScrollTo();
@@ -105,7 +107,6 @@ export default function FeaturedCategoryProductList({
const handleClick = useCallback(
(prdtId) => (e) => {
const tItemCard = e.currentTarget;
const lastFocusedTarget = Spotlight.getCurrent();
const lastFocusedTargetId =
lastFocusedTarget?.getAttribute("data-spotlight-id");
@@ -185,7 +186,8 @@ export default function FeaturedCategoryProductList({
contextName={LOG_CONTEXT_NAME.FEATURED_BRANDS}
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
order={expsOrd}
category={selectedCatCdLv1}
category={catNm}
patnerName={selectedPatncNm}
shelfLocation={shelfOrder}
shelfTitle={shelfTitle}
shelfId={spotlightId}

View File

@@ -81,8 +81,8 @@ export default function EventPopUpBanner() {
pushPanel({
name: panel_names.HOT_PICKS_PANEL,
panelInfo: {
curationId: eventPopData?.curationId,
patnrId: eventPopData?.patnrId,
curationId: eventPopData?.shptmLnkInfo?.lnkCurationId,
patnrId: eventPopData?.shptmLnkInfo?.lnkPatnrId,
},
})
);
@@ -208,10 +208,14 @@ export default function EventPopUpBanner() {
case 'EVT00203':
dispatch(pushPanel({ name: panel_names.TRENDING_NOW_PANEL }));
break;
// <<<<<<< HEAD
case 'EVT00204':
if (playerPanelInfo?.modal) {
dispatch(finishVideoPreview());
}
// =======
// case "EVT00204":
// >>>>>>> gitlab/develop
dispatch(
pushPanel({
name: panel_names.HOT_PICKS_PANEL,
@@ -328,7 +332,7 @@ export default function EventPopUpBanner() {
<TPopUp
kind="textPopup"
open={popupVisible}
hasText
hasText
text={$L('Downloading coupon complete.')}
/>
)}

View File

@@ -575,8 +575,8 @@ export default function RandomUnit({
// 비디오 클릭
const videoClick = useCallback(() => {
const lastFocusedTargetId = getContainerId(Spotlight.getCurrent());
const currentSpot = Spotlight.getCurrent();
// <<<<<<< HEAD
if (lastFocusedTargetId) {
dispatch(
updateHomeInfo({
@@ -589,6 +589,20 @@ export default function RandomUnit({
})
);
}
// =======
// const currentSpotlightId = currentSpot?.getAttribute("data-spotlight-id") || spotlightId;
// dispatch(
// updateHomeInfo({
// name: panel_names.HOME_PANEL,
// panelInfo: {
// lastFocusedTargetId: currentSpotlightId,
// focusedContainerId: TEMPLATE_CODE_CONF.TOP,
// currentSpot: currentSpotlightId,
// },
// })
// );
// >>>>>>> gitlab/develop
// ✅ modal=true → modal=false로 전환 (또는 초기 로드 시 modal=false)
// playActions의 shouldSkipVideoPlayback이 modal 상태를 확인하므로
@@ -631,9 +645,13 @@ export default function RandomUnit({
randomDataRef,
sendBannerLog,
onBlur,
// <<<<<<< HEAD
playerPanelInfo?.modal,
dispatch,
handleStartVideo,
// =======
// dispatch,
// >>>>>>> gitlab/develop
]);
// 투데이즈 딜 가격 정보

View File

@@ -23,6 +23,7 @@ import {
getHomeLayout,
getHomeMainContents,
updateHomeInfo,
// <<<<<<< HEAD
} from '../../actions/homeActions';
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions';
import { getSubCategory, getTop20Show } from '../../actions/mainActions';
@@ -67,6 +68,20 @@ const BACKGROUND_IMAGES = {
};
// [COMMENTED OUT] useVideoMove 관련 코드 주석 처리 - 향후 사용 검토 필요
// import { useVideoMove } from '../../hooks/useVideoTransition/useVideoMove';
// =======
// } from "../../actions/homeActions";
// import { sendLogGNB, sendLogTotalRecommend } from "../../actions/logActions";
// import { getSubCategory, getTop20Show } from "../../actions/mainActions";
// import { getHomeOnSaleInfo } from "../../actions/onSaleActions";
// import { finishVideoPreview } from "../../actions/playActions";
// import { getBestSeller } from "../../actions/productActions";
// import TBody from "../../components/TBody/TBody";
// import TButton, { TYPES } from "../../components/TButton/TButton";
// import TPanel from "../../components/TPanel/TPanel";
// import TPopUp from "../../components/TPopUp/TPopUp";
// import TVerticalPagenator from "../../components/TVerticalPagenator/TVerticalPagenator";
// import useDebugKey from "../../hooks/useDebugKey";
// >>>>>>> gitlab/develop
import {
ACTIVE_POPUP,
LOG_CONTEXT_NAME,
@@ -186,6 +201,9 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
const isInitialRender = useRef(true);
const verticalPagenatorRef = useRef(null);
const currentSentMenuRef = useRef(null);
const lastRestoredIdRef = useRef(null);
const focusedContainerIdRef = useRef(null);
const prevIsOnTopRef = useRef(isOnTop);
// ✅ [251119] DetailPanelBackground 이미지 프리로딩
// HomePanel 마운트 시 백그라운드로 모든 파트너사 배경 이미지를 미리 로드하여
@@ -250,8 +268,6 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
const expandIntervalRef = useRef(null); // 최상단에서의 interval
const expandAttemptRef = useRef(0); // 복구 시도 횟수
const focusedContainerIdRef = usePrevious(focusedContainerId);
const loadingComplete = useSelector((state) => state.common?.loadingComplete);
const isVideoTransitionLocked = useSelector((state) => state.home.videoTransitionLocked);
@@ -757,6 +773,7 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
// 비디오가 재생이 아니면 videoPlayIntentRef의 bannerId로 비디오 재생
// [251116] isHomeOnTop인 경우에는 비디오가 항상 재생되어야 함
useEffect(() => {
// <<<<<<< HEAD
// console.log('[HomeActive] useEffect 실행 - isOnTop:', isOnTop);
// console.log('[HomeActive] videoPlayIntentRef.current:', videoPlayIntentRef.current);
// console.log(
@@ -973,6 +990,23 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
}
}
}, [detailPanelClosed, isOnTop, bannerDataList, dispatch]);
// =======
// const justCameBack = !prevIsOnTopRef.current && isOnTop;
// if (
// justCameBack &&
// panelInfo?.lastFocusedTargetId &&
// panelInfo.lastFocusedTargetId !== lastRestoredIdRef.current
// ) {
// lastRestoredIdRef.current = panelInfo.lastFocusedTargetId;
// setTimeout(() => {
// Spotlight.focus(panelInfo.lastFocusedTargetId);
// }, 150);
// }
// prevIsOnTopRef.current = isOnTop;
// }, [isOnTop, panelInfo?.lastFocusedTargetId]);
// >>>>>>> gitlab/develop
useEffect(() => {
return () => {
@@ -997,13 +1031,17 @@ const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
currentSpot: currentSpot,
currentCatCd: targetSpotlightCatcd,
currentCateName: targetSpotlightCateNm,
// <<<<<<< HEAD
focusedContainerId: focusedContainerIdRef.current,
lastFocusedTargetId: lastFocusedTargetRef.current || panelInfo.lastFocusedTargetId,
// =======
// focusedContainerId: focusedContainerId,
// >>>>>>> gitlab/develop
},
})
);
};
}, [dispatch]);
}, [dispatch, focusedContainerId]);
const handleArrowClick = useCallback(() => {
if (verticalPagenatorRef.current) {

View File

@@ -271,7 +271,11 @@ const PopularShow = ({
patncNm,
catCd,
showUrl,
// <<<<<<< HEAD
foryou,
// =======
productInfos,
// >>>>>>> gitlab/develop
},
itemIndex
) => {
@@ -286,8 +290,8 @@ const PopularShow = ({
shelfLocation={shelfLocation}
shelfTitle={shelfTitle}
patnerName={patncNm}
contentId={showId}
contentTitle={showNm}
showId={showId}
showTitle={showNm}
imageSource={
(thumbnailUrl && thumbnailUrl960) ?
thumbnailUrl !== thumbnailUrl960
@@ -296,7 +300,7 @@ const PopularShow = ({
: thumbnailUrl
}
imageAlt={showNm}
productName={showNm}
productName={productInfos[0].prdtNm}
nonPosition={true}
type={TYPES.videoShow}
imgType={
@@ -305,7 +309,7 @@ const PopularShow = ({
: IMAGETYPES.imgVertical
}
logo={patncLogoPath}
productId={showId}
productId={productInfos[0].prdtId}
onFocus={handleFocus(itemIndex)}
onBlur={handleBlur(itemIndex)}
onClick={handleCardClick(patnrId, showId, catCd, showUrl)}

View File

@@ -1,13 +1,10 @@
import React, {
memo,
useCallback,
} from 'react';
import React, { memo, useCallback } from "react";
import classNames from 'classnames';
import classNames from "classnames";
import Spottable from '@enact/spotlight/Spottable';
import Spottable from "@enact/spotlight/Spottable";
import css from './CategoryNavItem.module.less';
import css from "./CategoryNavItem.module.less";
const SpottableComponent = Spottable("div");

View File

@@ -826,7 +826,7 @@ function IntroPanelWithOptional({
return shouldShowBenefitsView ? (
<div className={css.optionalDescription}>
{$L(
'By checking "Optional terms", you allow Shop Time to use your activity (views, purchases, searches, etc.) to show you more relevant content, product recommendations, special offers, and ads. If you do not check, you can still use all basic Shop Time features',
'By checking Optional terms, you allow Shop Time to use your activity (views, purchases, searches, etc.) to show you more relevant content, product recommendations, special offers, and ads. If you do not check, you can still use all basic Shop Time features',
)}
</div>
) : (

View File

@@ -195,16 +195,12 @@
// &:focus-visible,
&:hover {
outline: 4px #c91d53 solid !important;
outline-offset: 2px !important;
transform: translateY(-2px) !important;
box-shadow: 0 4px 12px rgba(201, 29, 83, 0.3) !important;
.termsText {
font-weight: bold !important;
}
}
}
}
}
.termsRightPanel {
@@ -347,14 +343,12 @@
&.selected:before {
background-color: #c91d53 !important;
border: 4px solid #c91d53 !important; // 굵은 테두리로 변경
box-shadow: 0 0 8px rgba(201, 29, 83, 0.3); // 약간의 그림자 효과
}
// 포커스 받았지만 선택 안됨
&.focused:not(.selected):before {
background-color: rgba(201, 29, 83, 0.1);
border: 4px solid #c91d53 !important;
box-shadow: 0 0 10px rgba(199, 8, 80, 0.3) !important;
}
// 비활성화됨
@@ -367,7 +361,6 @@
// 포커스 받음 (선택된 상태가 아닌 경우에만 적용)
&.focused:not(.selected):before {
border: 4px solid #c91d53 !important;
box-shadow: 0 0 10px rgba(199, 8, 80, 0.3) !important;
}
// 체크마크

View File

@@ -214,12 +214,15 @@ export default function Favorites({ title, panelInfo, isOnTop }) {
}, [favoritesDatas, activeDelete]);
const handleItemClick = useCallback(
(patnrId, prdtId, prdtNm, patncNm) => (ev) => {
(patnrId, prdtId, prdtNm, patncNm, showId, showNm, brndNm) => (ev) => {
const params = {
menu: "Favorite",
productId: prdtId,
productTitle: prdtNm,
partner: patncNm,
showId: showId,
showTitle: showNm,
brand: brndNm,
contextName: LOG_CONTEXT_NAME.MYPAGE,
messageId: LOG_MESSAGE_ID.MYPAGE_CLICK,
};

View File

@@ -303,11 +303,6 @@ export default function MyInfo({ title, cbScrollTo }) {
return (
<>
<THeader title={title} aria-label={title + " Heading 1"}>
{serverHOST && (
<span className={css.serverHostBadge}>[serverHost] {serverHOST}</span>
)}
</THeader>
<TBody className={css.tBody} cbScrollTo={cbScrollTo}>
<Container className={css.myInfoContainer}>
<div className={css.contentsBox}>

View File

@@ -64,38 +64,42 @@ export default function RecentlyViewedContents({
}, [mainContainerId, recentDataInfoItem, scrollLeft]);
const handleItemClick = useCallback(
(showId, showNm, patnrId, lgCatCd, prdtId, prdtNm, patncNm) => () => {
const params = {
menu: "Recently Viewed",
partner: patncNm,
contentId: showId,
contentTitle: showNm,
productId: prdtId,
productTitle: prdtNm,
contextName: LOG_CONTEXT_NAME.MYPAGE,
messageId: LOG_MESSAGE_ID.MYPAGE_CLICK,
};
dispatch(sendLogTotalRecommend(params));
(showId, showNm, patnrId, lgCatCd, prdtId, prdtNm, patncNm, brndNm) =>
() => {
const params = {
menu: "Recently Viewed",
partner: patncNm,
contentId: showId,
contentTitle: showNm,
productId: prdtId,
productTitle: prdtNm,
showId: showId,
showTitle: showNm,
brand: brndNm,
contextName: LOG_CONTEXT_NAME.MYPAGE,
messageId: LOG_MESSAGE_ID.MYPAGE_CLICK,
};
dispatch(sendLogTotalRecommend(params));
if (showId) {
dispatch(
startVideoPlayer({
showId,
patnrId,
shptmBanrTpNm: "VOD",
lgCatCd,
modal: false,
})
);
} else {
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId, prdtId },
})
);
}
},
if (showId) {
dispatch(
startVideoPlayer({
showId,
patnrId,
shptmBanrTpNm: "VOD",
lgCatCd,
modal: false,
})
);
} else {
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: { patnrId, prdtId },
})
);
}
},
[recentDataInfoItem]
);
const _handleItemToggle = useCallback(

View File

@@ -39,7 +39,6 @@ export default memo(function OnSaleContents({
shelfId: selectedLgCatCd,
shelfTitle: saleNm,
};
console.log("###shelfListShown", params);
dispatch(sendLogTotalRecommend(params));
}
}, [

View File

@@ -76,9 +76,9 @@ export default function OnSaleNav({
const containerId = "on-sale-nav";
setContainerLastFocusedElement(node, [containerId]);
}
setTimeout(() => {
Spotlight.focus(node);
}, 100);
// setTimeout(() => {
// Spotlight.focus(node);
// }, 100);
}
}, [panelInfoLgCatCd]);

View File

@@ -1,7 +1,7 @@
import React, { memo, useCallback, useEffect } from "react";
import classNames from "classnames";
import { useDispatch } from "react-redux";
import { connect, useDispatch } from "react-redux";
import Spottable from "@enact/spotlight/Spottable";
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
@@ -32,8 +32,8 @@ export default memo(function OnSaleNavItem({
const selected = selectedLgCatCd
? selectedLgCatCd === lgCatCd && css.selected
: panelInfoLgCatCd
? panelInfoLgCatCd === lgCatCd && css.selected
: itemIndex === 0;
? panelInfoLgCatCd === lgCatCd && css.selected
: itemIndex === 0;
const selectedText = selected === true ? "Selected, " : "";
@@ -77,8 +77,8 @@ export default memo(function OnSaleNavItem({
selectedLgCatCd
? selectedLgCatCd === lgCatCd && css.selected
: panelInfoLgCatCd
? panelInfoLgCatCd === lgCatCd && css.selected
: itemIndex === 0 && css.selected
? panelInfoLgCatCd === lgCatCd && css.selected
: itemIndex === 0 && css.selected
)}
onClick={handleClick}
id={"spotlightId-" + lgCatCd}

View File

@@ -57,8 +57,8 @@ export default function OnSalePanel({ panelInfo, spotlightId }) {
const enteredThroughEventPopup = Object.keys(panelInfo).length === 1;
const enteredThroughGNB = Object.keys(panelInfo).length === 0;
const previousPanelIsHome = Object.keys(panelInfo).length === 3;
const previousPanelIsDetail = Object.keys(panelInfo).length > 4;
const previousPanelIsHome = panelInfo?.nowShelf !== undefined;
const previousPanelIsDetail = panelInfo?.noResetFlag === true;
const cbChangePageRef = useRef(null);
const focusedContainerIdRef = useRef(0);
@@ -132,7 +132,6 @@ export default function OnSalePanel({ panelInfo, spotlightId }) {
useEffect(() => {
if (categories && saleInfos && Object.keys(saleInfos).length > 0) {
const prdtId = saleInfos[0]?.saleProductInfos[0]?.prdtId;
if (prdtId) {
setFirstFocusableTarget("spotlightId-" + removeDotAndColon(prdtId));
setIsReadyForInitialFocusTarget(true);
@@ -149,9 +148,8 @@ export default function OnSalePanel({ panelInfo, spotlightId }) {
}
if (previousPanelIsHome) {
targetId = panelInfo?.linkTpCd
? "spotlightId-" + panelInfo?.lgCatCd
: "spotlightId-" + panelInfo?.prdtId;
// 홈에서 온세일 아이템을 선택한 경우 해당 카테고리의 nav 아이템에 포커스
targetId = "spotlightId-" + panelInfo?.lgCatCd;
}
if (enteredThroughEventPopup) {
@@ -180,8 +178,6 @@ export default function OnSalePanel({ panelInfo, spotlightId }) {
isInitialFocusOccurred,
isReadyForInitialFocusTarget,
panelInfo?.lgCatCd,
panelInfo?.linkTpCd,
panelInfo?.prdtId,
panelInfo?.targetId,
previousPanelIsDetail,
previousPanelIsHome,
@@ -300,7 +296,6 @@ export default function OnSalePanel({ panelInfo, spotlightId }) {
cbChangePageRef.current(0);
}
}, []);
const handleShelfFocus = useCallback(
(shelfOrder) => {
// 현재 포커스된 shelf와 다른 shelf에 포커스될 때만 true 반환

View File

@@ -69,8 +69,15 @@ function PlayerOverlayContents({
}, [dispatch, captionEnable, setIsSubtitleActive]);
const patncLogoPath = useMemo(() => {
// <<<<<<< HEAD
let logo = playListInfo[selectedIndex]?.patncLogoPath;
if (type === 'MEDIA') {
// =======
// let logo = playListInfo[selectedIndex]?.patncLogoPath
// ? playListInfo[selectedIndex]?.patncLogoPath
// : playListInfo[selectedIndex]?.logoImgPath;
// if (type === "MEDIA") {
// >>>>>>> gitlab/develop
logo = panelInfo?.patncLogoPath;
}

View File

@@ -1,16 +1,18 @@
import React, { useMemo } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import classNames from 'classnames';
import { useSelector } from 'react-redux';
import TQRCode from '../../../components/TQRCode/TQRCode';
import css from './PlayerOverlayQRCode.module.less';
import { getQRCodeUrl, scaleH, scaleW } from '../../../utils/helperMethods';
import { getQRCodeUrl, scaleH, scaleW, $L } from '../../../utils/helperMethods';
function PlayerOverlayQRCode({ qrCurrentItem, type, modalScale }) {
const { cntry_cd } = useSelector((state) => state.common.httpHeader);
const deviceInfo = useSelector((state) => state.device.deviceInfo);
const [isShowQRCode, setIsShowQRCode] = useState(true);
const timerRef = useRef(null);
const serverHOST = useSelector((state) => state.common.appStatus.serverHOST);
const serverType = useSelector((state) => state.localSettings.serverType);
const { entryMenu, nowMenu } = useSelector((state) => state.common.menu);
@@ -102,6 +104,28 @@ function PlayerOverlayQRCode({ qrCurrentItem, type, modalScale }) {
return qrCurrentItem?.qrcodeUrl;
}, [detailUrl, qrCurrentItem, type]);
useEffect(() => {
const toggleQRCode = () => {
if (isShowQRCode) {
timerRef.current = setTimeout(() => {
setIsShowQRCode(false);
}, 10000);
} else {
timerRef.current = setTimeout(() => {
setIsShowQRCode(true);
}, 5000);
}
};
toggleQRCode();
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
};
}, [isShowQRCode]);
return (
<>
{innerStylePosition && QRCodeUrl && (
@@ -115,6 +139,7 @@ function PlayerOverlayQRCode({ qrCurrentItem, type, modalScale }) {
)}
style={innerStylePosition}
>
{/* <<<<<<< HEAD */}
<div>
<TQRCode
text={QRCodeUrl}
@@ -124,6 +149,27 @@ function PlayerOverlayQRCode({ qrCurrentItem, type, modalScale }) {
/>
<div className={css.text}>{label}</div>
</div>
{/* =======
{isShowQRCode ? (
<div>
<TQRCode
text={QRCodeUrl}
width={width}
height={height}
ariaLabel='QR CODE, "SCAN TO SHOP" go to Shoptime App'
/>
<div className={css.text}>{label}</div>
</div>
) : (
<div className={css.qrRollingWrap}>
<div className={css.innerText}>
<h3>{$L("Scan QR")}</h3>
<p>{$L("with your phone, Check Product")}</p>
<p>{$L("info & Purchase easily")}</p>
</div>
</div>
)}
>>>>>>> gitlab/develop */}
</div>
)}
</>

View File

@@ -68,4 +68,84 @@
}
}
}
.qrRollingWrap {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
text-align: center;
width: 100%;
height: 100%;
background: @COLOR_WHITE;
.innerText {
width: 100%;
padding: 0 10px;
h3 {
word-break: break-word;
font-size: 24px;
font-weight: bold;
color: @PRIMARY_COLOR_RED;
& + p {
margin-top: 10px;
}
}
p {
font-size: 16px;
font-weight: bold;
line-height: 1.2;
color: @COLOR_GRAY05;
word-break: keep-all;
}
}
}
// 국가별 롤링 텍스트 크기 조정 (폰트 사이즈만)
&.us .qrRollingWrap {
.innerText {
h3 {
font-size: 27px;
}
p {
font-size: 18px;
}
}
}
&.ru .qrRollingWrap {
.innerText {
h3 {
font-size: 22px;
}
p {
font-size: 15px;
}
}
}
&.de .qrRollingWrap {
.innerText {
h3 {
font-size: 26px;
}
p {
font-size: 17px;
}
}
}
&.gb .qrRollingWrap {
.innerText {
h3 {
font-size: 23px;
}
p {
font-size: 16px;
}
}
}
}

View File

@@ -28,9 +28,16 @@ import {
getMainCategoryShowDetail,
getMainLiveShow,
getMainLiveShowNowProduct,
// <<<<<<< HEAD
} from '../../actions/mainActions';
import * as PanelActions from '../../actions/panelActions';
import { updatePanel } from '../../actions/panelActions';
// =======
// } from "../../actions/mainActions";
// import { getBrandLiveChannelInfo } from "../../actions/brandActions";
// import * as PanelActions from "../../actions/panelActions";
// import { updatePanel } from "../../actions/panelActions";
// >>>>>>> gitlab/develop
import {
CLEAR_PLAYER_INFO,
getChatLog,

View File

@@ -33,16 +33,20 @@ export default function TabContainer({
prevChannelIndex,
currentTime,
spotlightId,
isFilteredByPatnr19,
}) {
const [tab, setTab] = useState(0);
const tabList = [
$L("SHOP NOW"),
panelInfo?.shptmBanrTpNm === "LIVE"
? $L("LIVE CHANNEL")
? isFilteredByPatnr19
? $L("VOD CHANNEL")
: $L("LIVE CHANNEL")
: $L("FEATURED SHOWS"),
];
// console.log("###liveChannelInfos", liveChannelInfos[selectedIndex]);
const handleItemClick = useCallback(
({ index }) => {
if (index === tab) return;
@@ -101,7 +105,6 @@ export default function TabContainer({
},
[videoVerticalVisible]
);
return (
<Container
className={classNames(
@@ -121,7 +124,7 @@ export default function TabContainer({
{tab === 0 && (
<ShopNowContents
tabTitle = {tabList}
tabTitle={tabList}
shopNowInfo={shopNowInfo}
playListInfo={playListInfo && playListInfo[selectedIndex]}
videoVerticalVisible={videoVerticalVisible}
@@ -130,9 +133,25 @@ export default function TabContainer({
handleItemFocus={_handleItemFocus}
/>
)}
{panelInfo?.shptmBanrTpNm === "VOD" &&
panelInfo?.patnrId === "19" &&
tab === 1 && (
<FeaturedShowContents
tabTitle={tabList}
featuredShowsInfos={playListInfo}
currentVideoInfo={playListInfo[selectedIndex]}
setSelectedIndex={setSelectedIndex}
selectedIndex={selectedIndex}
videoVerticalVisible={videoVerticalVisible}
currentVideoShowId={playListInfo[selectedIndex]?.showId}
tabIndex={tab}
panelInfo={panelInfo}
handleItemFocus={_handleItemFocus}
/>
)}
{panelInfo?.shptmBanrTpNm === "VOD" && tab === 1 && (
<FeaturedShowContents
tabTitle = {tabList}
tabTitle={tabList}
featuredShowsInfos={playListInfo}
currentVideoInfo={playListInfo[selectedIndex]}
setSelectedIndex={setSelectedIndex}
@@ -146,7 +165,7 @@ export default function TabContainer({
)}
{panelInfo?.shptmBanrTpNm === "LIVE" && tab === 1 && liveChannelInfos && (
<LiveChannelContents
tabTitle = {tabList}
tabTitle={tabList}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
videoVerticalVisible={videoVerticalVisible}
@@ -156,6 +175,7 @@ export default function TabContainer({
handleItemFocus={_handleItemFocus}
panelInfo={panelInfo}
currentTime={currentTime}
isFilteredByPatnr19={isFilteredByPatnr19}
/>
)}

View File

@@ -4,6 +4,7 @@ import { useDispatch } from 'react-redux';
import Spotlight from '@enact/spotlight';
// <<<<<<< HEAD
import defaultImage from '../../../../../assets/images/img-thumb-empty-144@3x.png';
import { updatePanel } from '../../../../actions/panelActions';
import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList';
@@ -14,6 +15,23 @@ import ListEmptyContents from '../TabContents/ListEmptyContents/ListEmptyContent
import css from './LiveChannelContents.module.less';
import { getMainCategoryShowDetail } from '../../../../actions/mainActions';
import { sendLogTotalRecommend } from '../../../../actions/logActions';
// =======
// import defaultImage from "../../../../../assets/images/img-thumb-empty-144@3x.png";
// import { updatePanel } from "../../../../actions/panelActions";
// import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
// import {
// LOG_CONTEXT_NAME,
// LOG_MENU,
// LOG_MESSAGE_ID,
// panel_names,
// } from "../../../../utils/Config";
// import { $L, removeSpecificTags } from "../../../../utils/helperMethods";
// import PlayerItemCard, { TYPES } from "../../PlayerItemCard/PlayerItemCard";
// import ListEmptyContents from "../TabContents/ListEmptyContents/ListEmptyContents";
// import css from "./LiveChannelContents.module.less";
// import { getMainCategoryShowDetail } from "../../../../actions/mainActions";
// import { sendLogTotalRecommend } from "../../../../actions/logActions";
// >>>>>>> gitlab/develop
export default function FeaturedShowContents({
featuredShowsInfos,
@@ -44,6 +62,8 @@ export default function FeaturedShowContents({
({ index, ...rest }) => {
const {
thumbnailUrl,
logoImgPath,
thumbnailImgPath,
patncLogoPath,
patnrId,
showId,
@@ -106,8 +126,14 @@ export default function FeaturedShowContents({
{...rest}
key={prdtId}
imageAlt={prdtId}
logo={patncLogoPath}
imageSource={thumbnailUrl ? thumbnailUrl : defaultImage}
logo={logoImgPath ? logoImgPath : patncLogoPath}
imageSource={
thumbnailUrl
? thumbnailUrl
: thumbnailImgPath
? thumbnailImgPath
: defaultImage
}
productName={showNameDangerouslySetInnerHTML}
patnerName={patncNm}
onClick={handleItemClick}

View File

@@ -4,6 +4,7 @@ import { useDispatch } from 'react-redux';
import Spotlight from '@enact/spotlight';
// <<<<<<< HEAD
import { updatePanel } from '../../../../actions/panelActions';
import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList';
import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, panel_names } from '../../../../utils/Config';
@@ -13,6 +14,21 @@ import ListEmptyContents from '../TabContents/ListEmptyContents/ListEmptyContent
import css from './LiveChannelContents.module.less';
import cssV2 from './LiveChannelContents.v2.module.less';
import { sendLogTotalRecommend } from '../../../../actions/logActions';
// =======
// import { updatePanel } from "../../../../actions/panelActions";
// import TVirtualGridList from "../../../../components/TVirtualGridList/TVirtualGridList";
// import {
// LOG_CONTEXT_NAME,
// LOG_MENU,
// LOG_MESSAGE_ID,
// panel_names,
// } from "../../../../utils/Config";
// import { $L } from "../../../../utils/helperMethods";
// import PlayerItemCard, { TYPES } from "../../PlayerItemCard/PlayerItemCard";
// import ListEmptyContents from "../TabContents/ListEmptyContents/ListEmptyContents";
// import css from "./LiveChannelContents.module.less";
// import { sendLogTotalRecommend } from "../../../../actions/logActions";
// >>>>>>> gitlab/develop
export default function LiveChannelContents({
liveInfos,
@@ -24,13 +40,22 @@ export default function LiveChannelContents({
handleItemFocus,
tabTitle,
panelInfo,
// <<<<<<< HEAD
direction = 'vertical',
version = 1,
isFilteredByPatnr19,
}) {
const dispatch = useDispatch();
const isClickBlocked = useRef(false);
const blockTimeoutRef = useRef(null);
// =======
// isFilteredByPatnr19,
// }) {
// const dispatch = useDispatch();
// const isClickBlocked = useRef(false);
const scrollToRef = useRef(null);
// >>>>>>> gitlab/develop
const handleFocus = useCallback(
() => () => {
if (handleItemFocus) {
@@ -40,6 +65,18 @@ export default function LiveChannelContents({
[handleItemFocus]
);
// cbScrollTo 콜백으로 scrollTo 함수 받기
const handleScrollTo = useCallback((scrollToFn) => {
scrollToRef.current = scrollToFn;
}, []);
// VOD Channel로 전환될 때 스크롤을 최상단으로 이동
useEffect(() => {
if (isFilteredByPatnr19 && scrollToRef.current) {
scrollToRef.current({ index: 0, animate: false, focus: false });
}
}, [isFilteredByPatnr19]);
const renderItem = useCallback(
({ index, ...rest }) => {
const {
@@ -144,7 +181,11 @@ export default function LiveChannelContents({
startDt={strtDt}
endDt={endDt}
currentTime={currentTime}
// <<<<<<< HEAD
version={version}
// =======
// currentVideoVisible={currentVideoShowId === liveInfos[index].showId}
// >>>>>>> gitlab/develop
/>
);
},
@@ -167,6 +208,7 @@ export default function LiveChannelContents({
<div className={containerClass}>
{liveInfos && liveInfos.length > 0 ? (
<TVirtualGridList
cbScrollTo={handleScrollTo}
dataSize={liveInfos.length}
direction={direction}
renderItem={renderItem}

View File

@@ -27,7 +27,6 @@ export default function YouMayLikeContents({
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
const gridStyle = useMemo(() => ({ height: `${height}px` }), [height]);
useEffect(() => {
if (shopNowInfo && shopNowInfo.length === 2) {
setHeight(scaleH(300));
@@ -82,7 +81,12 @@ export default function YouMayLikeContents({
showNm: playListInfo?.showNm,
showId: playListInfo?.showId,
liveFlag: playListInfo?.liveFlag,
// <<<<<<< HEAD
thumbnailUrl: playListInfo?.thumbnailUrl,
// =======
catDpTh3: playListInfo?.catDpTh3,
catDpTh4: playListInfo?.catDpTh4,
// >>>>>>> gitlab/develop
patnrId,
prdtId,
launchedFromPlayer: true,

View File

@@ -43,7 +43,8 @@ export default memo(function SearchShowCard({
const sendLog = (newParams) => {
const logParams = {
...newParams,
contentTitle: title,
showTitle: title,
showId: contentId.split("_").pop() || "",
partner: patncNm,
contextName: LOG_CONTEXT_NAME.SEARCH,
messageId: LOG_MESSAGE_ID.SEARCH_RESULT_CLICK,

View File

@@ -128,8 +128,8 @@ const PopularVideoCard = ({
shelfLocation: 1,
shelfId: SpotlightIds.TRENDING_NOW_POPULAR_SHOW,
shelfTitle: currentShelf,
contentId: showId,
contentTitle: showNm,
showId: showId,
showTitle: showNm,
partner: patncNm,
location: selectedIndex + 1,
};