[251210] feat: featuredBrandTopBanner API추가 , nbcu bg추가

🕐 커밋 시간: 2025. 12. 10. 13:02:33

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

📁 추가된 파일:
  + com.twin.app.shoptime/assets/images/bg/nbcu_new.png

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/actionTypes.js
  ~ com.twin.app.shoptime/src/actions/brandActions.js
  ~ com.twin.app.shoptime/src/api/apiConfig.js
  ~ com.twin.app.shoptime/src/reducers/brandReducer.js
  ~ com.twin.app.shoptime/src/views/DetailPanel/components/DetailPanelBackground/DetailPanelBackground.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/components/DetailPanelBackground/DetailPanelBackground.v2.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/FeaturedBrandsPanel.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx

🔧 주요 변경 내용:
  • 타입 시스템 안정성 강화
  • 핵심 비즈니스 로직 개선
  • API 서비스 레이어 개선
  • UI 컴포넌트 아키텍처 개선
  • 소규모 기능 개선
  • 모듈 구조 개선
This commit is contained in:
2025-12-10 13:02:34 +09:00
parent db7bc4b2ed
commit d6656848a2
10 changed files with 100 additions and 4 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

View File

@@ -131,6 +131,7 @@ export const types = {
GET_BRAND_SHOWROOM: 'GET_BRAND_SHOWROOM', GET_BRAND_SHOWROOM: 'GET_BRAND_SHOWROOM',
GET_BRAND_RECENTLY_AIRED: 'GET_BRAND_RECENTLY_AIRED', GET_BRAND_RECENTLY_AIRED: 'GET_BRAND_RECENTLY_AIRED',
GET_BRAND_SHOP_BY_SHOW: 'GET_BRAND_SHOP_BY_SHOW', GET_BRAND_SHOP_BY_SHOW: 'GET_BRAND_SHOP_BY_SHOW',
GET_BRAND_TOP_BANNER: 'GET_BRAND_TOP_BANNER',
SET_BRAND_LIVE_CHANNEL_UPCOMING: 'SET_BRAND_LIVE_CHANNEL_UPCOMING', SET_BRAND_LIVE_CHANNEL_UPCOMING: 'SET_BRAND_LIVE_CHANNEL_UPCOMING',
SET_BRAND_CHAN_INFO: 'SET_BRAND_CHAN_INFO', SET_BRAND_CHAN_INFO: 'SET_BRAND_CHAN_INFO',
RESET_BRAND_STATE: 'RESET_BRAND_STATE', RESET_BRAND_STATE: 'RESET_BRAND_STATE',

View File

@@ -428,6 +428,43 @@ export const getBrandShopByShow = (props) => (dispatch, getState) => {
TAxios(dispatch, getState, 'get', URLS.GET_BRAND_SHOP_BY_SHOW, params, {}, onSuccess, onFail); TAxios(dispatch, getState, 'get', URLS.GET_BRAND_SHOP_BY_SHOW, params, {}, onSuccess, onFail);
}; };
// Featured Brands Top Banner 정보 조회 IF-LGSP-377 (NBCU 전용)
export const getBrandTopBanner = (props) => (dispatch, getState) => {
const { patnrId } = props;
console.log("[getBrandTopBanner] Called - patnrId:", patnrId);
// NBCU(patnrId: 21)가 아니면 호출하지 않음
if (patnrId !== 21) {
console.log("[getBrandTopBanner] Skip - patnrId is not 21 (NBCU)");
return;
}
dispatch(changeAppStatus({ showLoadingPanel: { show: true, type: 'wait' } }));
const onSuccess = (response) => {
console.log("[getBrandTopBanner] onSuccess - patnrId:", patnrId, "data:", response.data.data);
console.log("[getBrandTopBanner] brandTopBannerInfo:", response.data.data.brandTopBannerInfo);
dispatch({
type: types.GET_BRAND_TOP_BANNER,
payload: {
data: response.data.data,
},
});
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};
const onFail = (error) => {
console.log("[getBrandTopBanner] onFail - patnrId:", patnrId, "error:", error);
derror('getBrandTopBanner onFail ', error);
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};
TAxios(dispatch, getState, 'get', URLS.GET_BRAND_TOP_BANNER, { patnrId }, {}, onSuccess, onFail);
};
// Featured Brands Recently Aired 조회 IF-LGSP-373 // Featured Brands Recently Aired 조회 IF-LGSP-373
export const getBrandRecentlyAired = (props) => (dispatch, getState) => { export const getBrandRecentlyAired = (props) => (dispatch, getState) => {
const { patnrId } = props; const { patnrId } = props;

View File

@@ -56,6 +56,7 @@ export const URLS = {
GET_BRAND_SHOWROOM: "/lgsp/v1/brand/showroom.lge", GET_BRAND_SHOWROOM: "/lgsp/v1/brand/showroom.lge",
GET_BRAND_RECENTLY_AIRED: "/lgsp/v1/brand/recently/aired.lge", GET_BRAND_RECENTLY_AIRED: "/lgsp/v1/brand/recently/aired.lge",
GET_BRAND_SHOP_BY_SHOW: "/lgsp/v1/brand/shopByShow.lge", GET_BRAND_SHOP_BY_SHOW: "/lgsp/v1/brand/shopByShow.lge",
GET_BRAND_TOP_BANNER: "/lgsp/v1/brand/top/banner.lge",
//on-sale controller //on-sale controller
GET_ON_SALE_INFO: "/lgsp/v1/onsale/onsale.lge", GET_ON_SALE_INFO: "/lgsp/v1/onsale/onsale.lge",

View File

@@ -48,6 +48,10 @@ const initialState = {
brandShopByShowData: { brandShopByShowData: {
data: {}, data: {},
}, },
brandTopBannerData: {
data: {},
},
}; };
export const brandReducer = (state = initialState, action) => { export const brandReducer = (state = initialState, action) => {
@@ -179,6 +183,12 @@ export const brandReducer = (state = initialState, action) => {
}; };
} }
case types.GET_BRAND_TOP_BANNER:
return {
...state,
brandTopBannerData: action.payload,
};
case types.SET_BRAND_LIVE_CHANNEL_UPCOMING: case types.SET_BRAND_LIVE_CHANNEL_UPCOMING:
return { return {
...state, ...state,

View File

@@ -10,6 +10,7 @@ import ontv4u from '../../../../../assets/images/bg/ontv4u_new.png';
import Pinkfong from '../../../../../assets/images/bg/Pinkfong_new.png'; import Pinkfong from '../../../../../assets/images/bg/Pinkfong_new.png';
import qvc from '../../../../../assets/images/bg/qvc_new.png'; import qvc from '../../../../../assets/images/bg/qvc_new.png';
import shoplc from '../../../../../assets/images/bg/shoplc_new.png'; import shoplc from '../../../../../assets/images/bg/shoplc_new.png';
import nbcu from '../../../../../assets/images/bg/nbcu_new.png';
import css from './DetailPanelBackground.module.less'; import css from './DetailPanelBackground.module.less';
/** /**
@@ -38,6 +39,7 @@ export default function DetailPanelBackground({
11: shoplc, 11: shoplc,
16: koreaKiosk, 16: koreaKiosk,
19: Pinkfong, 19: Pinkfong,
21: nbcu,
}; };
const detailPanelBg = useMemo(() => { const detailPanelBg = useMemo(() => {

View File

@@ -9,6 +9,7 @@ import ontv4u from '../../../../../assets/images/bg/ontv4u_new.png';
import Pinkfong from '../../../../../assets/images/bg/Pinkfong_new.png'; import Pinkfong from '../../../../../assets/images/bg/Pinkfong_new.png';
import qvc from '../../../../../assets/images/bg/qvc_new.png'; import qvc from '../../../../../assets/images/bg/qvc_new.png';
import shoplc from '../../../../../assets/images/bg/shoplc_new.png'; import shoplc from '../../../../../assets/images/bg/shoplc_new.png';
import nbcu from '../../../../../assets/images/bg/nbcu_new.png';
import css from './DetailPanelBackground.module.less'; import css from './DetailPanelBackground.module.less';
// ==================== 로깅 함수들 ==================== // ==================== 로깅 함수들 ====================
@@ -65,6 +66,7 @@ export default function DetailPanelBackgroundV2({
11: shoplc, // SHOPLC 11: shoplc, // SHOPLC
16: koreaKiosk, // KOREA KIOSK 16: koreaKiosk, // KOREA KIOSK
19: Pinkfong, // PINKFONG 19: Pinkfong, // PINKFONG
21: nbcu, // NBCU
}), }),
[] []
); );
@@ -200,7 +202,7 @@ export function PreloadedBackgroundImages({
launchedFromPlayer = false, launchedFromPlayer = false,
}) { }) {
// 모든 파트너사 ID 목록 // 모든 파트너사 ID 목록
const allPatnrIds = useMemo(() => [1, 2, 4, 9, 11, 16, 19], []); const allPatnrIds = useMemo(() => [1, 2, 4, 9, 11, 16, 19, 21], []);
// ✅ 원래 로직 복원: HomePanel이 onTop이 아니고 selectedPatnrId가 있을 때만 배경 표시 // ✅ 원래 로직 복원: HomePanel이 onTop이 아니고 selectedPatnrId가 있을 때만 배경 표시
const shouldShowBackground = !isHomePanelOnTop && selectedPatnrId; const shouldShowBackground = !isHomePanelOnTop && selectedPatnrId;

View File

@@ -7,13 +7,36 @@ import css from "./Banner.module.less";
export default memo(function Banner({ export default memo(function Banner({
brandInfo, brandInfo,
brandTopImgInfo, brandTopImgInfo,
brandTopBannerInfo,
panelPatnrId, panelPatnrId,
selectedPatnrId,
}) { }) {
const selectedBrandInfo = const selectedBrandInfo =
brandInfo?.find(({ patnrId }) => panelPatnrId === patnrId) || {}; brandInfo?.find(({ patnrId }) => panelPatnrId === patnrId) || {};
const { patncLogoPath, patncNm } = selectedBrandInfo; const { patncLogoPath, patncNm } = selectedBrandInfo;
const { topImgAlt, topImgPath } = brandTopImgInfo; const { topImgAlt, topImgPath } = brandTopImgInfo || {};
// NBCU(patnrId: 21)인 경우 Top Banner 정보 사용
const isNBCU = selectedPatnrId === 21;
console.log("[Banner] isNBCU:", isNBCU);
console.log("[Banner] brandTopBannerInfo:", brandTopBannerInfo);
// Top Banner 정보에서 필요한 필드 추출
const {
banrImgUrl, // 배너 이미지 URL
banrImgNm, // 배너 이미지 이름
pupBanrImgUrl, // 팝업 배너 이미지 URL
pupBanrTtl, // 팝업 배너 타이틀
banrNm // 배너 이름
} = brandTopBannerInfo || {};
// NBCU인 경우 Top Banner 이미지를, 아니면 기존 Top 이미지 사용
const bannerImageSrc = isNBCU ? banrImgUrl : topImgPath;
const bannerImageAlt = isNBCU ? banrImgNm || banrNm : topImgAlt;
console.log("[Banner] bannerImageSrc:", bannerImageSrc);
console.log("[Banner] bannerImageAlt:", bannerImageAlt);
return ( return (
<div className={css.container}> <div className={css.container}>
@@ -26,7 +49,13 @@ export default memo(function Banner({
/> />
<figcaption>{patncNm}</figcaption> <figcaption>{patncNm}</figcaption>
</figure> </figure>
<CustomImage src={topImgPath} alt={topImgAlt} ariaLabel={topImgAlt} /> {bannerImageSrc && (
<CustomImage
src={bannerImageSrc}
alt={bannerImageAlt}
ariaLabel={bannerImageAlt}
/>
)}
</div> </div>
); );
}); });

View File

@@ -26,6 +26,7 @@ import {
getBrandShopByShow, getBrandShopByShow,
getBrandShowroom, getBrandShowroom,
getBrandTSVInfo, getBrandTSVInfo,
getBrandTopBanner,
} from "../../actions/brandActions"; } from "../../actions/brandActions";
import { changeAppStatus, setHidePopup } from "../../actions/commonActions"; import { changeAppStatus, setHidePopup } from "../../actions/commonActions";
import { import {
@@ -276,6 +277,9 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
const brandShopByShowContsInfo = useSelector( const brandShopByShowContsInfo = useSelector(
(state) => state.brand.brandShopByShowData.data.brandShopByShowContsInfo (state) => state.brand.brandShopByShowData.data.brandShopByShowContsInfo
); );
const brandTopBannerInfo = useSelector(
(state) => state.brand.brandTopBannerData.data.brandTopBannerInfo
);
const [displayTopButton, setDisplayTopButton] = useState(false); const [displayTopButton, setDisplayTopButton] = useState(false);
const [focusedContainerId, setFocusedContainerId] = useState(null); const [focusedContainerId, setFocusedContainerId] = useState(null);
@@ -816,6 +820,12 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
} }
}); });
// NBCU(patnrId: 21)인 경우 Top Banner API 호출
if (selectedPatnrId === 21) {
console.log("[FeaturedBrandsPanel] NBCU detected - calling Top Banner API");
dispatch(getBrandTopBanner({ patnrId: selectedPatnrId }));
}
resetStates(); resetStates();
} }
}, [sortedBrandLayoutInfo, selectedPatnrId]); }, [sortedBrandLayoutInfo, selectedPatnrId]);
@@ -1035,11 +1045,13 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
/> />
)} )}
{brandInfo && brandTopImgInfo && ( {brandInfo && (brandTopImgInfo || (selectedPatnrId === 21 && brandTopBannerInfo)) && (
<Banner <Banner
brandInfo={brandInfo} brandInfo={brandInfo}
brandTopImgInfo={brandTopImgInfo} brandTopImgInfo={brandTopImgInfo}
brandTopBannerInfo={brandTopBannerInfo}
panelPatnrId={panelInfo?.patnrId} panelPatnrId={panelInfo?.patnrId}
selectedPatnrId={selectedPatnrId}
/> />
)} )}

View File

@@ -27,6 +27,7 @@ import ontv4u from '../../../assets/images/bg/ontv4u_new.png';
import Pinkfong from '../../../assets/images/bg/Pinkfong_new.png'; import Pinkfong from '../../../assets/images/bg/Pinkfong_new.png';
import qvc from '../../../assets/images/bg/qvc_new.png'; import qvc from '../../../assets/images/bg/qvc_new.png';
import shoplc from '../../../assets/images/bg/shoplc_new.png'; import shoplc from '../../../assets/images/bg/shoplc_new.png';
import nbcu from '../../../assets/images/bg/nbcu_new.png';
import { types } from '../../actions/actionTypes'; import { types } from '../../actions/actionTypes';
import { import {
changeAppStatus, changeAppStatus,
@@ -123,6 +124,7 @@ const BACKGROUND_IMAGES = {
11: shoplc, // SHOPLC 11: shoplc, // SHOPLC
16: koreaKiosk, // KOREA KIOSK 16: koreaKiosk, // KOREA KIOSK
19: Pinkfong, // PINKFONG 19: Pinkfong, // PINKFONG
21: nbcu, // NBCU
}; };
export const TEMPLATE_CODE_CONF = { export const TEMPLATE_CODE_CONF = {