[포유 작업]#1

- action, reducer 에 recommendProduct 관련 추가.
 - 로그 관련으로 Config에 pickedforyou추가
 - homepanel pickforyou노출 건으로 추가.
 - homepanel getSubCategory에 파라미터 추가.
 - bestseller,pickedforyou노출 변경.(foru api에서 내려주는걸로)
 - subCategory 노출 변경. foru api에서 내려주는 아이템 2개 추가및 기존 데이터 중복시 제거.
This commit is contained in:
junghoon86.park
2025-11-10 16:17:51 +09:00
parent 3e547df1a4
commit 11582840b8
7 changed files with 156 additions and 67 deletions

View File

@@ -1,10 +1,18 @@
import { URLS } from '../api/apiConfig'; import { URLS } from '../api/apiConfig';
import { TAxios } from '../api/TAxios'; import { TAxios } from '../api/TAxios';
import { convertUtcToLocal } from '../components/MediaPlayer/util'; import { convertUtcToLocal } from '../components/MediaPlayer/util';
import { CATEGORY_DATA_MAX_RESULTS_LIMIT, LOG_CONTEXT_NAME, LOG_MESSAGE_ID } from '../utils/Config'; import {
CATEGORY_DATA_MAX_RESULTS_LIMIT,
LOG_CONTEXT_NAME,
LOG_MESSAGE_ID,
} from '../utils/Config';
import * as HelperMethods from '../utils/helperMethods'; import * as HelperMethods from '../utils/helperMethods';
import { types } from './actionTypes'; import { types } from './actionTypes';
import { addReservation, changeAppStatus, deleteReservation } from './commonActions'; import {
addReservation,
changeAppStatus,
deleteReservation,
} from './commonActions';
//IF-LGSP-007 //IF-LGSP-007
export const getMainLiveShow = (props) => (dispatch, getState) => { export const getMainLiveShow = (props) => (dispatch, getState) => {
@@ -155,7 +163,7 @@ let lastSubCategoryParams = {};
export const getSubCategory = export const getSubCategory =
(params, pageNo = 1, key = null, clear = false) => (params, pageNo = 1, key = null, clear = false) =>
(dispatch, getState) => { (dispatch, getState) => {
const { lgCatCd, patnrIdList, tabType, filterType } = params; const { lgCatCd, patnrIdList, tabType, filterType, recommendIncFlag } = params;
let pageSize = params.pageSize || CATEGORY_DATA_MAX_RESULTS_LIMIT; let pageSize = params.pageSize || CATEGORY_DATA_MAX_RESULTS_LIMIT;
if (pageNo === 1) { if (pageNo === 1) {
@@ -179,21 +187,34 @@ export const getSubCategory =
if (pageNo === 1) { if (pageNo === 1) {
getSubCategoryKey = new Date(); getSubCategoryKey = new Date();
currentKey = getSubCategoryKey; currentKey = getSubCategoryKey;
// ✅ recommendProduct 분리
const { recommendProduct, ...restData } = response.data.data;
dispatch({ dispatch({
type: types.GET_SUB_CATEGORY, type: types.GET_SUB_CATEGORY,
payload: response.data.data, payload: {
...restData,
recommendProduct,
},
categoryParams: { categoryParams: {
lgCatCd, lgCatCd,
patnrIdList, patnrIdList,
tabType, tabType,
filterType, filterType,
recommendIncFlag,
pageSize, pageSize,
}, },
}); });
} else if (getSubCategoryKey === currentKey) { } else if (getSubCategoryKey === currentKey) {
const { recommendProduct, ...restData } = response.data.data;
dispatch({ dispatch({
type: types.GET_SUB_CATEGORY, type: types.GET_SUB_CATEGORY,
payload: response.data.data, payload: {
...restData,
recommendProduct,
},
append: true, append: true,
startIndex: (pageNo - 1) * pageSize, startIndex: (pageNo - 1) * pageSize,
}); });
@@ -212,7 +233,7 @@ export const getSubCategory =
getState, getState,
'get', 'get',
URLS.GET_SUB_CATEGORY, URLS.GET_SUB_CATEGORY,
{ lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType }, { lgCatCd, patnrIdList, pageSize, pageNo, tabType, filterType,recommendIncFlag },
{}, {},
onSuccess, onSuccess,
onFail onFail

View File

@@ -10,11 +10,13 @@ const initialState = {
showDetailInfo: [], showDetailInfo: [],
showNowInfo: null, showNowInfo: null,
featuredShowsInfos: {}, featuredShowsInfos: {},
recommendProduct: null,
categoryParams: { categoryParams: {
lgCatCd: null, lgCatCd: null,
patnrIdList: null, patnrIdList: null,
tabType: null, tabType: null,
filterType: null, filterType: null,
recommendIncFlag: null,
pageSize: CATEGORY_DATA_MAX_RESULTS_LIMIT, pageSize: CATEGORY_DATA_MAX_RESULTS_LIMIT,
}, },
}; };
@@ -39,6 +41,7 @@ export const mainReducer = (state = initialState, action) => {
categoryFilterCd: action.payload.categoryFilterCd, categoryFilterCd: action.payload.categoryFilterCd,
topShowInfo: action.payload.topShowInfo, topShowInfo: action.payload.topShowInfo,
partnerInfos: action.payload.partnerInfos, partnerInfos: action.payload.partnerInfos,
recommendProduct: action.payload.recommendProduct,
categoryParams: action.categoryParams, categoryParams: action.categoryParams,
}; };
} }
@@ -63,6 +66,7 @@ export const mainReducer = (state = initialState, action) => {
categoryFilterCd: action.payload.categoryFilterCd, categoryFilterCd: action.payload.categoryFilterCd,
topShowInfo: action.payload.topShowInfo, topShowInfo: action.payload.topShowInfo,
partnerInfos: action.payload.partnerInfos, partnerInfos: action.payload.partnerInfos,
recommendProduct: action.payload.recommendProduct,
categoryParams: action.categoryParams, categoryParams: action.categoryParams,
}; };
} }
@@ -93,6 +97,7 @@ export const mainReducer = (state = initialState, action) => {
categoryFilterCd: action.payload.categoryFilterCd, categoryFilterCd: action.payload.categoryFilterCd,
topShowInfo: action.payload.topShowInfo, topShowInfo: action.payload.topShowInfo,
partnerInfos: action.payload.partnerInfos, partnerInfos: action.payload.partnerInfos,
recommendProduct: action.payload.recommendProduct,
}; };
} else { } else {
return { return {
@@ -107,6 +112,7 @@ export const mainReducer = (state = initialState, action) => {
categoryFilterCd: action.payload.categoryFilterCd, categoryFilterCd: action.payload.categoryFilterCd,
topShowInfo: action.payload.topShowInfo, topShowInfo: action.payload.topShowInfo,
partnerInfos: action.payload.partnerInfos, partnerInfos: action.payload.partnerInfos,
recommendProduct: action.payload.recommendProduct,
categoryParams: action.categoryParams, categoryParams: action.categoryParams,
}; };
} }
@@ -206,6 +212,7 @@ export const mainReducer = (state = initialState, action) => {
return { return {
...state, ...state,
subCategoryData: {}, subCategoryData: {},
recommendProduct: null,
}; };
default: default:

View File

@@ -292,6 +292,7 @@ export const LOG_MENU = {
HOME_ON_SALE: 'Home/On Sale', HOME_ON_SALE: 'Home/On Sale',
HOME_POPULAR_SHOWS: 'Home/Popular Shows', HOME_POPULAR_SHOWS: 'Home/Popular Shows',
HOME_BEST_SELLER: 'Home/Best Sellers', HOME_BEST_SELLER: 'Home/Best Sellers',
HOME_PICKED_FOR_YOU: 'Home/Picked For You',
TRENDING_NOW_POPULAR_SHOWS: 'Trending Now/Popular Shows', TRENDING_NOW_POPULAR_SHOWS: 'Trending Now/Popular Shows',
TRENDING_NOW_BEST_SELLER: 'Trending Now/Best Sellers', TRENDING_NOW_BEST_SELLER: 'Trending Now/Best Sellers',

View File

@@ -67,18 +67,33 @@ const BestSeller = ({
const { cursorVisible } = useSelector((state) => state.common.appStatus); const { cursorVisible } = useSelector((state) => state.common.appStatus);
const bestSellerDatas = useSelector(
(state) => state.product.bestSellerData?.bestSeller
); const bestSellerNewDatas = useSelector(
(state) =>
state.foryou?.justForYouInfo?.shelfInfos
);
const [drawChk, setDrawChk] = useState(false); const [drawChk, setDrawChk] = useState(false);
const [firstChk, setFirstChk] = useState(0); const [firstChk, setFirstChk] = useState(0);
const [bestInfos, setBestInfos] = useState(null);
useEffect(()=>{
setBestInfos(
bestSellerNewDatas?.filter(
(item) => item.recommendTpCd === "BESTSELLER"
)
)
},[bestSellerNewDatas])
const orderStyle = useMemo(() => ({ order: order }), [order]); const orderStyle = useMemo(() => ({ order: order }), [order]);
useEffect(() => { useEffect(() => {
setDrawChk(true); setDrawChk(true);
}, [bestSellerDatas]); }, [bestSellerNewDatas]);
const handleCardClick = useCallback( const handleCardClick = useCallback(
(patnrId, prdtId) => () => { (patnrId, prdtId) => () => {
@@ -176,22 +191,7 @@ const BestSeller = ({
handleShelfFocus(); handleShelfFocus();
} }
}, [handleShelfFocus]); }, [handleShelfFocus]);
const [bestSellerNewData, setBestSellerNewData] = useState([]);
const _randomProduct = useCallback(() => {
const randomChk = Math.round(Math.random()) === 0 ? false : true;
return randomChk;
}, []);
useEffect(() => {
setBestSellerNewData(
bestSellerDatas?.map((item) => ({
...item,
// foryou: _randomProduct(),
}))
);
}, [bestSellerDatas]);
return ( return (
<Container <Container
@@ -213,8 +213,8 @@ const BestSeller = ({
cbScrollTo={getScrollTo} cbScrollTo={getScrollTo}
noScrollByWheel noScrollByWheel
> >
{bestSellerNewData && {bestInfos &&
bestSellerNewData.map( bestInfos?.[0].productInfos.map(
( (
{ {
prdtId, prdtId,
@@ -226,7 +226,7 @@ const BestSeller = ({
offerInfo, offerInfo,
brndNm, brndNm,
patncNm, patncNm,
catNm, //catNm, 없음
//foryou, //foryou,
euEnrgLblInfos, euEnrgLblInfos,
}, },
@@ -251,7 +251,7 @@ const BestSeller = ({
shelfTitle={shelfTitle} shelfTitle={shelfTitle}
patnerName={patncNm} patnerName={patncNm}
brandName={brndNm} brandName={brndNm}
catNm={catNm} // catNm={catNm}
imageAlt={prdtId} imageAlt={prdtId}
imageSource={imgUrl} imageSource={imgUrl}
priceInfo={priceInfo} priceInfo={priceInfo}
@@ -265,7 +265,7 @@ const BestSeller = ({
offerInfo={offerInfo} offerInfo={offerInfo}
spotlightId={"bestsellerItem" + itemIndex} spotlightId={"bestsellerItem" + itemIndex}
firstLabel={rankText} firstLabel={rankText}
label={itemIndex * 1 + 1 + " of " + bestSellerNewData.length} label={itemIndex * 1 + 1 + " of " + bestInfos?.[0].productInfos.length}
lastLabel=" go to detail, button" lastLabel=" go to detail, button"
euEnrgLblInfos={euEnrgLblInfos} euEnrgLblInfos={euEnrgLblInfos}
> >

View File

@@ -1,7 +1,17 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useDispatch, useSelector } from 'react-redux'; import {
useDispatch,
useSelector,
} from 'react-redux';
import { applyMiddleware } from 'redux';
import Spotlight from '@enact/spotlight'; import Spotlight from '@enact/spotlight';
import { import {
@@ -23,20 +33,31 @@ import {
getHomeMainContents, getHomeMainContents,
updateHomeInfo, updateHomeInfo,
} from '../../actions/homeActions'; } from '../../actions/homeActions';
import { sendLogGNB, sendLogTotalRecommend } from '../../actions/logActions'; import {
import { getSubCategory, getTop20Show } from '../../actions/mainActions'; sendLogGNB,
sendLogTotalRecommend,
} from '../../actions/logActions';
import {
getSubCategory,
getTop20Show,
} from '../../actions/mainActions';
import { getHomeOnSaleInfo } from '../../actions/onSaleActions'; import { getHomeOnSaleInfo } from '../../actions/onSaleActions';
import { finishVideoPreview, shrinkVideoTo1px, expandVideoFrom1px } from '../../actions/playActions';
import { updatePanel } from '../../actions/panelActions'; import { updatePanel } from '../../actions/panelActions';
import {
expandVideoFrom1px,
finishVideoPreview,
shrinkVideoTo1px,
} from '../../actions/playActions';
import { getBestSeller } from '../../actions/productActions'; import { getBestSeller } from '../../actions/productActions';
import TBody from '../../components/TBody/TBody'; import TBody from '../../components/TBody/TBody';
import TButton, { TYPES } from '../../components/TButton/TButton'; import TButton, { TYPES } from '../../components/TButton/TButton';
import TPanel from '../../components/TPanel/TPanel'; import TPanel from '../../components/TPanel/TPanel';
import TPopUp from '../../components/TPopUp/TPopUp'; import TPopUp from '../../components/TPopUp/TPopUp';
import TVerticalPagenator from '../../components/TVerticalPagenator/TVerticalPagenator'; import TVerticalPagenator
from '../../components/TVerticalPagenator/TVerticalPagenator';
import useDebugKey from '../../hooks/useDebugKey'; import useDebugKey from '../../hooks/useDebugKey';
import usePrevious from '../../hooks/usePrevious';
import { useFocusHistory } from '../../hooks/useFocusHistory/useFocusHistory'; import { useFocusHistory } from '../../hooks/useFocusHistory/useFocusHistory';
import usePrevious from '../../hooks/usePrevious';
import { useVideoPlay } from '../../hooks/useVideoPlay/useVideoPlay'; import { useVideoPlay } from '../../hooks/useVideoPlay/useVideoPlay';
import { useVideoMove } from '../../hooks/useVideoTransition/useVideoMove'; import { useVideoMove } from '../../hooks/useVideoTransition/useVideoMove';
import { import {
@@ -55,7 +76,7 @@ import css from '../HomePanel/HomePanel.module.less';
import PopularShow from '../HomePanel/PopularShow/PopularShow'; import PopularShow from '../HomePanel/PopularShow/PopularShow';
import SubCategory from '../HomePanel/SubCategory/SubCategory'; import SubCategory from '../HomePanel/SubCategory/SubCategory';
import EventPopUpBanner from './EventPopUpBanner/EventPopUpBanner'; import EventPopUpBanner from './EventPopUpBanner/EventPopUpBanner';
import { applyMiddleware } from 'redux'; import PickedForYou from './PickedForYou/PickedForYou';
export const TEMPLATE_CODE_CONF = { export const TEMPLATE_CODE_CONF = {
TOP: 'DSP00101', TOP: 'DSP00101',
@@ -63,6 +84,7 @@ export const TEMPLATE_CODE_CONF = {
ON_SALE: 'DSP00103', ON_SALE: 'DSP00103',
POPULAR_SHOW: 'DSP00104', POPULAR_SHOW: 'DSP00104',
BEST_SELLER: 'DSP00105', BEST_SELLER: 'DSP00105',
PICK_FOR_YOU: 'DSP00106',
}; };
const HomePanel = ({ isOnTop }) => { const HomePanel = ({ isOnTop }) => {
@@ -251,6 +273,9 @@ const HomePanel = ({ isOnTop }) => {
case TEMPLATE_CODE_CONF.BEST_SELLER: case TEMPLATE_CODE_CONF.BEST_SELLER:
nowMenu = LOG_MENU.HOME_BEST_SELLER; nowMenu = LOG_MENU.HOME_BEST_SELLER;
break; break;
case TEMPLATE_CODE_CONF.PICK_FOR_YOU:
nowMenu = LOG_MENU.HOME_PICKED_FOR_YOU;
break;
default: default:
nowMenu = LOG_MENU.HOME_TOP; nowMenu = LOG_MENU.HOME_TOP;
break; break;
@@ -384,6 +409,24 @@ const HomePanel = ({ isOnTop }) => {
); );
} else break; } else break;
} }
case TEMPLATE_CODE_CONF.PICK_FOR_YOU: {
if (bestSellerDatas && bestSellerDatas.length > 0) {
return (
<PickedForYou
key={el.shptmApphmDspyOptCd}
spotlightId={el.shptmApphmDspyOptCd}
handleShelfFocus={handleItemFocus(
el.shptmApphmDspyOptCd,
el.expsOrd,
el.shptmApphmDspyOptNm
)}
handleItemFocus={handleItemFocus(el.shptmApphmDspyOptCd)}
shelfLocation={el.expsOrd}
shelfTitle={el.shptmApphmDspyOptNm}
/>
);
} else break;
}
} }
})} })}
{loadingComplete && sortedHomeLayoutInfo && sortedHomeLayoutInfo.length > 0 && ( {loadingComplete && sortedHomeLayoutInfo && sortedHomeLayoutInfo.length > 0 && (
@@ -593,6 +636,7 @@ const HomePanel = ({ isOnTop }) => {
pageSize: 10, pageSize: 10,
tabType: 'CAT00102', tabType: 'CAT00102',
filterType: 'CAT00202', filterType: 'CAT00202',
recommendIncFlag: 'Y',
}, },
1 1
) )

View File

@@ -52,7 +52,7 @@ const PickedForYou = ({
shelfLocation, shelfLocation,
shelfTitle, shelfTitle,
}) => { }) => {
console.log("###Test pjh 여기지 ?");
const { getScrollTo, scrollLeft } = useScrollTo(); const { getScrollTo, scrollLeft } = useScrollTo();
const { handleScrollReset, handleStopScrolling } = useScrollReset( const { handleScrollReset, handleStopScrolling } = useScrollReset(
scrollLeft, scrollLeft,
@@ -67,11 +67,26 @@ const PickedForYou = ({
(state) => state.product.bestSellerData?.bestSeller (state) => state.product.bestSellerData?.bestSeller
); );
const justForYouDatasNew = useSelector(
(state) => state.foryou?.justForYouInfo?.shelfInfos
)
const [drawChk, setDrawChk] = useState(false); const [drawChk, setDrawChk] = useState(false);
const [firstChk, setFirstChk] = useState(0); const [firstChk, setFirstChk] = useState(0);
const [pickedForYou, setPickedForYou] = useState(null);
const orderStyle = useMemo(() => ({ order: order }), [order]); const orderStyle = useMemo(() => ({ order: order }), [order]);
useEffect(()=>{
setPickedForYou(
justForYouDatasNew?.filter(
(item) => item.recommendTpCd === "PICKEDFORYOU"
)
)
},[justForYouDatasNew])
useEffect(() => { useEffect(() => {
setDrawChk(true); setDrawChk(true);
}, [justForYouDatas]); }, [justForYouDatas]);
@@ -193,8 +208,8 @@ const PickedForYou = ({
cbScrollTo={getScrollTo} cbScrollTo={getScrollTo}
noScrollByWheel noScrollByWheel
> >
{justForYouDatas && {pickedForYou &&
justForYouDatas.map( pickedForYou?.[0].productInfos.map(
( (
{ {
prdtId, prdtId,
@@ -233,7 +248,7 @@ const PickedForYou = ({
onClick={handleCardClick(patnrId, prdtId)} onClick={handleCardClick(patnrId, prdtId)}
offerInfo={offerInfo} offerInfo={offerInfo}
spotlightId={"bestsellerItem" + itemIndex} spotlightId={"bestsellerItem" + itemIndex}
label={itemIndex * 1 + 1 + " of " + justForYouDatas.length} label={itemIndex * 1 + 1 + " of " + pickedForYou?.[0].productInfos.length}
lastLabel=" go to detail, button" lastLabel=" go to detail, button"
/> />
); );

View File

@@ -71,6 +71,10 @@ export default memo(function SubCategory({
(state) => state.main.subCategoryData?.categoryItemInfos (state) => state.main.subCategoryData?.categoryItemInfos
); );
const foruItemInfos = useSelector(
(state) => state.main.recommendProduct[0]?.productInfos
);
const nowMenu = useSelector((state) => state.common.menu.nowMenu); const nowMenu = useSelector((state) => state.common.menu.nowMenu);
const [currentLgCatCd, setCurrentLgCatCd] = useState(catCd ? catCd : null); const [currentLgCatCd, setCurrentLgCatCd] = useState(catCd ? catCd : null);
@@ -110,6 +114,7 @@ export default memo(function SubCategory({
pageSize: "10", pageSize: "10",
tabType: "CAT00102", tabType: "CAT00102",
filterType: "CAT00202", filterType: "CAT00202",
recommendIncFlag: 'Y',
}, },
1 1
) )
@@ -222,27 +227,23 @@ export default memo(function SubCategory({
} }
}, [handleShelfFocus]); }, [handleShelfFocus]);
const _randomProduct = useCallback(() => {
const randomChk = Math.round(Math.random()) === 0 ? false : true;
return randomChk;
}, []);
useEffect(() => { useEffect(() => {
setCategoryItemNewData( const recommendedData = foruItemInfos?.slice(0, 2).map((item) => ({
categoryItemInfos?.subCatItemList?.map((item) => ({ ...item,
...item, foryou: true,
foryou: _randomProduct(), })) || [];
}))
); const recommendedPrdtIds = new Set(recommendedData.map(item => item.prdtId));
}, [categoryItemInfos?.subCatItemList]);
const baseData = categoryItemInfos?.subCatItemList?.filter(
useEffect(() => { (item) => !recommendedPrdtIds.has(item.prdtId)
dispatch( ).map((item) => ({
getRecentlySawItem( ...item,
categoryItemNewData.filter((item) => item.foryou === true) foryou: false,
) })) || [];
);
}, [categoryItemNewData, dispatch]); setCategoryItemNewData([...recommendedData, ...baseData]);
}, [categoryItemInfos?.subCatItemList, foruItemInfos]);
return ( return (
<Container <Container
@@ -321,7 +322,7 @@ export default memo(function SubCategory({
} }
)} 원본 보관*/} )} 원본 보관*/}
{categoryItemNewData && {categoryItemNewData &&
categoryItemNewData.map( categoryItemNewData.slice(0, 10).map(
( (
{ {
prdtId, prdtId,
@@ -332,7 +333,7 @@ export default memo(function SubCategory({
offerInfo, offerInfo,
brndNm, brndNm,
patncNm, patncNm,
//foryou, foryou,
}, },
itemIndex itemIndex
) => { ) => {
@@ -367,7 +368,7 @@ export default memo(function SubCategory({
} }
lastLabel=" go to detail, button" lastLabel=" go to detail, button"
> >
{/* {foryou === true && <Tag text={"For You"} />} */} {foryou === true && <Tag text={"For You"} />}
</TItemCardNew> </TItemCardNew>
); );
} }