[251210] feat: FeaturedBrandsPanel-TopBannerImage 추가

🕐 커밋 시간: 2025. 12. 10. 15:53:45

📊 변경 통계:
  • 총 파일: 6개
  • 추가: +51줄
  • 삭제: -21줄

📁 추가된 파일:
  + com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.jsx
  + com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.module.less

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/brandActions.js
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.module.less
  ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/FeaturedBrandsPanel.jsx

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • 소규모 기능 개선
  • 모듈 구조 개선
This commit is contained in:
2025-12-10 15:53:46 +09:00
parent bc7a999cf1
commit bf7af5aa2e
6 changed files with 143 additions and 21 deletions

View File

@@ -432,19 +432,20 @@ export const getBrandShopByShow = (props) => (dispatch, getState) => {
export const getBrandTopBanner = (props) => (dispatch, getState) => {
const { patnrId } = props;
console.log("[getBrandTopBanner] Called - patnrId:", patnrId);
console.log("[BRAND-TOP-BANNER-API] Called - patnrId:", patnrId);
// NBCU(patnrId: 21)가 아니면 호출하지 않음
if (patnrId !== 21) {
console.log("[getBrandTopBanner] Skip - patnrId is not 21 (NBCU)");
if (patnrId !== 21 && patnrId !== "21") {
console.log("[BRAND-TOP-BANNER-API] Skip - patnrId is not 21 (NBCU), patnrId:", patnrId, "(type:", typeof patnrId, ")");
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);
console.log("[BRAND-TOP-BANNER-API] onSuccess - patnrId:", patnrId);
console.log("[BRAND-TOP-BANNER-API] Full response data:", response.data.data);
console.log("[BRAND-TOP-BANNER-API] brandTopBannerInfo:", response.data.data.brandTopBannerInfo);
dispatch({
type: types.GET_BRAND_TOP_BANNER,
@@ -457,7 +458,7 @@ export const getBrandTopBanner = (props) => (dispatch, getState) => {
};
const onFail = (error) => {
console.log("[getBrandTopBanner] onFail - patnrId:", patnrId, "error:", error);
console.log("[BRAND-TOP-BANNER-API] onFail - patnrId:", patnrId, "error:", error);
derror('getBrandTopBanner onFail ', error);
dispatch(changeAppStatus({ showLoadingPanel: { show: false } }));
};

View File

@@ -2,6 +2,7 @@ import React, { memo } from "react";
import IcPartnersDefault from "../../../../assets/images/ic-tab-partners-default@3x.png";
import CustomImage from "../../../components/CustomImage/CustomImage";
import TopBannerImage from "../TopBannerImage/TopBannerImage";
import css from "./Banner.module.less";
export default memo(function Banner({
@@ -18,11 +19,14 @@ export default memo(function Banner({
const { topImgAlt, topImgPath } = brandTopImgInfo || {};
// NBCU(patnrId: 21)인 경우 Top Banner 정보 사용
const isNBCU = selectedPatnrId === 21;
console.log("[Banner] isNBCU:", isNBCU);
console.log("[Banner] brandTopBannerInfo:", brandTopBannerInfo);
const isNBCU = selectedPatnrId === 21 || selectedPatnrId === "21";
console.log("[FB-BANNER-COMP] ===== BANNER COMPONENT START =====");
console.log("[FB-BANNER-COMP] selectedPatnrId:", selectedPatnrId, "(type:", typeof selectedPatnrId, ")");
console.log("[FB-BANNER-COMP] panelPatnrId:", panelPatnrId, "(type:", typeof panelPatnrId, ")");
console.log("[FB-BANNER-COMP] isNBCU:", isNBCU);
console.log("[FB-BANNER-COMP] brandTopBannerInfo:", brandTopBannerInfo);
// Top Banner 정보에서 필요한 필드 추출
// Top Banner 정보에서 필요한 필드 추출 (현재는 사용하지 않음)
const {
banrImgUrl, // 배너 이미지 URL
banrImgNm, // 배너 이미지 이름
@@ -31,12 +35,21 @@ export default memo(function Banner({
banrNm // 배너 이름
} = brandTopBannerInfo || {};
// NBCU인 경우 Top Banner 이미지를, 아니면 기존 Top 이미지 사용
const bannerImageSrc = isNBCU ? banrImgUrl : topImgPath;
const bannerImageAlt = isNBCU ? banrImgNm || banrNm : topImgAlt;
// 현재는 Top Banner 이미지를 사용하지 않고 기존 Top 이미지 사용
// TODO: 향후 Top Banner 이미지를 사용하려면 아래 주석 처리된 부분을 활성화
const bannerImageSrc = topImgPath; // isNBCU ? banrImgUrl : topImgPath;
const bannerImageAlt = topImgAlt; // isNBCU ? banrImgNm || banrNm : topImgAlt;
console.log("[Banner] bannerImageSrc:", bannerImageSrc);
console.log("[Banner] bannerImageAlt:", bannerImageAlt);
console.log("[FB-BANNER-COMP] Top Banner 이미지는 현재 비활성화됨");
if (isNBCU && brandTopBannerInfo) {
console.log("[FB-BANNER-COMP] NBCU Top Banner 데이터 수신 (사용하지 않음):");
console.log("[FB-BANNER-COMP] - banrImgUrl:", banrImgUrl);
console.log("[FB-BANNER-COMP] - pupBanrImgUrl:", pupBanrImgUrl);
console.log("[FB-BANNER-COMP] - pupBanrTtl:", pupBanrTtl);
}
console.log("[FB-BANNER-COMP] Using original Top Image");
console.log("[FB-BANNER-COMP] bannerImageSrc:", bannerImageSrc);
console.log("[FB-BANNER-COMP] ===== BANNER COMPONENT END =====");
return (
<div className={css.container}>
@@ -56,6 +69,16 @@ export default memo(function Banner({
ariaLabel={bannerImageAlt}
/>
)}
{/* NBCU Top Banner Image */}
{isNBCU && brandTopBannerInfo?.banrImgUrl && (
<TopBannerImage
banrImgUrl={banrImgUrl}
banrImgNm={banrImgNm}
banrNm={banrNm}
spotlightId="nbcu-top-banner-image"
/>
)}
</div>
);
});

View File

@@ -3,6 +3,7 @@
.container {
position: fixed;
// position: relative; // changed from fixed to relative for absolute positioning of children
.flex(@justifyCenter: flex-start, @alignCenter: flex-end);
.size(@w: 100%, @h: 108px);
margin-bottom: 58px;

View File

@@ -799,9 +799,12 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
// effect: data fetching based on brandLayoutInfo and selectedPatnrId
useEffect(() => {
console.log("[FB-PANEL-DATA-FETCH] Effect triggered");
console.log("[FB-PANEL-DATA-FETCH] sortedBrandLayoutInfo:", sortedBrandLayoutInfo);
console.log("[FB-PANEL-DATA-FETCH] selectedPatnrId:", selectedPatnrId);
if (sortedBrandLayoutInfo && selectedPatnrId) {
console.log("[FeaturedBrandsPanel] Data Fetching Effect - selectedPatnrId:", selectedPatnrId);
console.log("[FeaturedBrandsPanel] sortedBrandLayoutInfo:", sortedBrandLayoutInfo);
console.log("[FB-PANEL-DATA-FETCH] Fetching data - patnrId:", selectedPatnrId);
Object.entries(DISPATCH_MAP) //
.forEach(([templateCode, action]) => {
if (hasTemplateCodeWithValue(sortedBrandLayoutInfo, templateCode)) {
@@ -811,18 +814,20 @@ const FeaturedBrandsPanel = ({ isOnTop, panelInfo, spotlightId }) => {
fromDetail &&
shouldRenderComponent(brandShopByShowContsList)
) {
console.log("[FeaturedBrandsPanel] Skip re-fetch ShopByShow on return from detail");
console.log("[FB-PANEL-DATA-FETCH] Skip re-fetch ShopByShow on return from detail");
return;
}
console.log("[FeaturedBrandsPanel] Fetching data for template:", templateCode, "patnrId:", selectedPatnrId);
console.log("[FB-PANEL-DATA-FETCH] Dispatching for template:", templateCode, "patnrId:", selectedPatnrId);
dispatch(action({ patnrId: selectedPatnrId }));
}
});
// NBCU(patnrId: 21)인 경우 Top Banner API 호출
if (selectedPatnrId === 21) {
console.log("[FeaturedBrandsPanel] NBCU detected - calling Top Banner API");
if (selectedPatnrId === 21 || selectedPatnrId === "21") {
console.log("[FB-PANEL-TOP-BANNER] NBCU(patnrId=21) detected - calling Top Banner API");
console.log("[FB-PANEL-TOP-BANNER] selectedPatnrId:", selectedPatnrId, "(type:", typeof selectedPatnrId, ")");
console.log("[FB-PANEL-TOP-BANNER] Before API call - brandTopBannerInfo:", brandTopBannerInfo);
dispatch(getBrandTopBanner({ patnrId: selectedPatnrId }));
}

View File

@@ -0,0 +1,67 @@
import React, { memo, useCallback, useState } from "react";
import CustomImage from "../../../components/CustomImage/CustomImage";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import css from "./TopBannerImage.module.less";
const Container = SpotlightContainerDecorator(
{ leaveFor: { left: "", right: "", down: "best-seller-spotlightId" }, enterTo: "default-element" },
"div"
);
const TopBannerImage = memo(({ banrImgUrl, banrImgNm, banrNm, spotlightId }) => {
console.log("[TOP-BANNER-IMG] Rendering with URL:", banrImgUrl);
console.log("[TOP-BANNER-IMG] spotlightId:", spotlightId);
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
const handleClick = useCallback(() => {
console.log("[TOP-BANNER-IMG] Clicked");
// 필요시 클릭 핸들러 로직 추가
}, []);
const handleImageLoad = useCallback((e) => {
const img = e.target;
console.log("[TOP-BANNER-IMG] Image loaded - dimensions:", img.naturalWidth, "x", img.naturalHeight);
// 원본 이미지 크기
const naturalWidth = img.naturalWidth;
const naturalHeight = img.naturalHeight;
setImageDimensions({
width: naturalWidth,
height: naturalHeight
});
}, []);
if (!banrImgUrl) {
console.log("[TOP-BANNER-IMG] No image URL provided");
return null;
}
return (
<Container
className={css.topBannerContainer}
spotlightId={spotlightId}
tabIndex={0}
onClick={handleClick}
style={{
// 이미지 크기에 맞춰 컨테이너 크기 조정
width: imageDimensions.width ? `${imageDimensions.width + 30}px` : 'auto', // 패딩 15px 양쪽
height: imageDimensions.height ? `${imageDimensions.height + 30}px` : 'auto' // 패딩 15px 상하
}}
>
<img
src={banrImgUrl}
alt={banrImgNm || banrNm || "NBCU Top Banner"}
className={css.topBannerImage}
onLoad={handleImageLoad}
style={{
width: imageDimensions.width || 'auto',
height: imageDimensions.height || 'auto'
}}
/>
</Container>
);
});
export default TopBannerImage;

View File

@@ -0,0 +1,25 @@
.topBannerContainer {
position: absolute;
right: 60px;
top: 48px;
padding: 15px;
background-color: transparent;
// Spotlight 포커스 스타일
&:focus {
outline: 2px solid #fff;
outline-offset: 2px;
background-color: rgba(255, 255, 255, 0.1);
}
// Spotlight hover 효과
&[data-spotlight-id] {
cursor: pointer;
}
}
.topBannerImage {
display: block;
// 크기는 JavaScript에서 동적으로 설정
border-radius: 4px;
}