From a2b29d219a5c83aaf334ca8991710d71e9d9aecc Mon Sep 17 00:00:00 2001 From: optrader Date: Wed, 10 Dec 2025 16:33:38 +0900 Subject: [PATCH] [251210] feat: FeaturedBrandsPanel-TopBannerImage Popup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit πŸ• 컀밋 μ‹œκ°„: 2025. 12. 10. 16:33:37 πŸ“Š λ³€κ²½ 톡계: β€’ 총 파일: 6개 β€’ μΆ”κ°€: +69쀄 β€’ μ‚­μ œ: -5쀄 πŸ“ μΆ”κ°€λœ 파일: + com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.figma.jsx + com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.jsx + com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.module.less πŸ“ μˆ˜μ •λœ 파일: ~ com.twin.app.shoptime/src/components/GlobalPopup/GlobalPopup.jsx ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.jsx πŸ”§ μ£Όμš” λ³€κ²½ λ‚΄μš©: β€’ UI μ»΄ν¬λ„ŒνŠΈ μ•„ν‚€ν…μ²˜ κ°œμ„  β€’ μ†Œκ·œλͺ¨ κΈ°λŠ₯ κ°œμ„  β€’ λͺ¨λ“ˆ ꡬ쑰 κ°œμ„  --- .../components/GlobalPopup/GlobalPopup.jsx | 49 +++++++++ .../FeaturedBrandsPanel/Banner/Banner.jsx | 5 +- .../TopBannerImage/TopBannerImage.jsx | 20 +++- .../TopBannerImage/TopBannerPopup.figma.jsx | 13 +++ .../TopBannerImage/TopBannerPopup.jsx | 61 +++++++++++ .../TopBannerImage/TopBannerPopup.module.less | 100 ++++++++++++++++++ 6 files changed, 243 insertions(+), 5 deletions(-) create mode 100644 com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.figma.jsx create mode 100644 com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.jsx create mode 100644 com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.module.less diff --git a/com.twin.app.shoptime/src/components/GlobalPopup/GlobalPopup.jsx b/com.twin.app.shoptime/src/components/GlobalPopup/GlobalPopup.jsx index e9627f02..96dc3849 100644 --- a/com.twin.app.shoptime/src/components/GlobalPopup/GlobalPopup.jsx +++ b/com.twin.app.shoptime/src/components/GlobalPopup/GlobalPopup.jsx @@ -18,6 +18,7 @@ import { setHidePopup } from '../../actions/commonActions'; import { getPopupConfig } from '../../constants/popupConfig'; import usePrevious from '../../hooks/usePrevious'; import TPopUp from '../TPopUp/TPopUp'; +import TopBannerPopup from '../../views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup'; // μ»€μŠ€ν…€ ν›…: νŒμ—… μƒνƒœ 관리 const useGlobalPopupState = () => { @@ -128,9 +129,16 @@ const GlobalPopup = () => { secondaryData } = useGlobalPopupState(); + const [imageDimensions, setImageDimensions] = React.useState({ width: 0, height: 0 }); + const handlers = usePopupCloseHandlers(); const previousPopupVisible = usePrevious(popupVisible); + const handleImageLoad = useCallback((dimensions) => { + console.log("[GLOBAL-POPUP] Image dimensions received:", dimensions); + setImageDimensions(dimensions); + }, []); + // ν˜„μž¬ νŒμ—… μ„€μ • const currentConfig = useMemo(() => { if (!activePopup) return null; @@ -214,6 +222,47 @@ const GlobalPopup = () => { return null; } + // TopBannerImagePopup 특수 처리 + if (activePopup === 'topBannerImagePopup') { + // Figma λ””μžμΈ 기반 κ³ μ • 크기 + // λ„ˆλΉ„: 1060px + // 높이: 헀더(110px) + 이미지(556px) + ν‘Έν„°(138px) = 804px + const popupWidth = '1060px'; + const popupHeight = '804px'; + + return ( +
+
+ +
+
+ ); + } + // 섀정이 μ—†μœΌλ©΄ κΈ°λ³Έ νŒμ—…λ„ λ Œλ”λ§ν•˜μ§€ μ•ŠμŒ if (!currentConfig) { console.warn(`No configuration found for popup type: ${activePopup}`); diff --git a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx index 66f5bc42..dfe9f9aa 100644 --- a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx +++ b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/Banner/Banner.jsx @@ -26,11 +26,12 @@ export default memo(function Banner({ console.log("[FB-BANNER-COMP] isNBCU:", isNBCU); console.log("[FB-BANNER-COMP] brandTopBannerInfo:", brandTopBannerInfo); - // Top Banner μ •λ³΄μ—μ„œ ν•„μš”ν•œ ν•„λ“œ μΆ”μΆœ (ν˜„μž¬λŠ” μ‚¬μš©ν•˜μ§€ μ•ŠμŒ) + // Top Banner μ •λ³΄μ—μ„œ ν•„μš”ν•œ ν•„λ“œ μΆ”μΆœ const { banrImgUrl, // λ°°λ„ˆ 이미지 URL banrImgNm, // λ°°λ„ˆ 이미지 이름 pupBanrImgUrl, // νŒμ—… λ°°λ„ˆ 이미지 URL + pupBanrImgNm, // νŒμ—… λ°°λ„ˆ 이미지 이름 pupBanrTtl, // νŒμ—… λ°°λ„ˆ 타이틀 banrNm // λ°°λ„ˆ 이름 } = brandTopBannerInfo || {}; @@ -76,6 +77,8 @@ export default memo(function Banner({ banrImgUrl={banrImgUrl} banrImgNm={banrImgNm} banrNm={banrNm} + pupBanrImgUrl={pupBanrImgUrl} + pupBanrImgNm={pupBanrImgNm} spotlightId="nbcu-top-banner-image" /> )} diff --git a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.jsx b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.jsx index 742f4b52..af115f70 100644 --- a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.jsx +++ b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerImage.jsx @@ -1,4 +1,6 @@ import React, { memo, useCallback, useState } from "react"; +import { useDispatch } from "react-redux"; +import { setShowPopup } from "../../../actions/commonActions"; import CustomImage from "../../../components/CustomImage/CustomImage"; import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import css from "./TopBannerImage.module.less"; @@ -8,16 +10,26 @@ const Container = SpotlightContainerDecorator( "div" ); -const TopBannerImage = memo(({ banrImgUrl, banrImgNm, banrNm, spotlightId }) => { +const TopBannerImage = memo(({ banrImgUrl, banrImgNm, banrNm, pupBanrImgUrl, pupBanrImgNm, spotlightId }) => { console.log("[TOP-BANNER-IMG] Rendering with URL:", banrImgUrl); console.log("[TOP-BANNER-IMG] spotlightId:", spotlightId); + const dispatch = useDispatch(); const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 }); const handleClick = useCallback(() => { - console.log("[TOP-BANNER-IMG] Clicked"); - // ν•„μš”μ‹œ 클릭 ν•Έλ“€λŸ¬ 둜직 μΆ”κ°€ - }, []); + console.log("[TOP-BANNER-IMG] Clicked - Opening popup"); + if (pupBanrImgUrl) { + console.log("[TOP-BANNER-IMG] Dispatching topBannerImagePopup"); + dispatch(setShowPopup({ + activePopup: 'topBannerImagePopup', + data: { + pupBanrImgUrl, + pupBanrImgNm: pupBanrImgNm || banrImgNm || banrNm + } + })); + } + }, [dispatch, pupBanrImgUrl, pupBanrImgNm, banrImgNm, banrNm]); const handleImageLoad = useCallback((e) => { const img = e.target; diff --git a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.figma.jsx b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.figma.jsx new file mode 100644 index 00000000..f3f203eb --- /dev/null +++ b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.figma.jsx @@ -0,0 +1,13 @@ +
+
+
Wells Fargo Active Cash Credit Card
+
+
+ +
+
+
+
CLOSE
+
+
+
\ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.jsx b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.jsx new file mode 100644 index 00000000..ac228719 --- /dev/null +++ b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.jsx @@ -0,0 +1,61 @@ +import React, { memo, useCallback, useState } from "react"; +import { useDispatch } from "react-redux"; +import { setHidePopup } from "../../../actions/commonActions"; +import css from "./TopBannerPopup.module.less"; + +const TopBannerPopup = memo(({ title, imageUrl, imageAlt, onImageLoad }) => { + const dispatch = useDispatch(); + const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 }); + + const handleImageLoad = useCallback((e) => { + const img = e.target; + console.log("[TOP-BANNER-POPUP] Image loaded - dimensions:", img.naturalWidth, "x", img.naturalHeight); + + const dimensions = { + width: img.naturalWidth, + height: img.naturalHeight + }; + + setImageDimensions(dimensions); + + // λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ— 크기 전달 + if (onImageLoad) { + onImageLoad(dimensions); + } + }, [onImageLoad]); + + const handleClose = useCallback(() => { + console.log("[TOP-BANNER-POPUP] Closing popup"); + dispatch(setHidePopup()); + }, [dispatch]); + + return ( +
+ {/* Title Section */} +
+
{title}
+
+ + {/* Image Section */} +
+ {imageAlt +
+ + {/* Button Section */} +
+ +
+
+ ); +}); + +TopBannerPopup.displayName = "TopBannerPopup"; + +export default TopBannerPopup; diff --git a/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.module.less b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.module.less new file mode 100644 index 00000000..bc108b95 --- /dev/null +++ b/com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.module.less @@ -0,0 +1,100 @@ +.container { + width: 100%; + height: 100%; + background: white; + overflow: hidden; + border-radius: 12px; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; + display: flex; +} + +// 헀더: 높이 110px (상단 λ§ˆμ§„ 30 + λ‚΄μš© 50 + ν•˜λ‹¨ λ§ˆμ§„ 30) +.titleSection { + flex: 0 0 110px; + background: #E7EBEF; + padding-top: 30px; + padding-bottom: 30px; + padding-left: 30px; + padding-right: 30px; + justify-content: flex-start; + align-items: center; + gap: 15px; + display: flex; +} + +.titleText { + flex: 1; + text-align: center; + color: black; + font-size: 42px; + font-family: 'LG Smart UI', sans-serif; + font-weight: 700; + line-height: 42px; + word-wrap: break-word; + word-break: break-word; +} + +// 이미지: 높이 556px +.imageSection { + flex: 0 0 556px; + justify-content: center; + align-items: center; + display: flex; + background: white; + overflow: hidden; +} + +.popupImage { + width: 100%; + height: 100%; + object-fit: contain; +} + +// ν‘Έν„°: 높이 138px (상단 λ§ˆμ§„ 30 + λ²„νŠΌ 78 + ν•˜λ‹¨ λ§ˆμ§„ 30) +.buttonSection { + flex: 0 0 138px; + padding-left: 60px; + padding-right: 60px; + padding-top: 30px; + padding-bottom: 30px; + justify-content: center; + align-items: center; + gap: 10px; + display: flex; +} + +.closeButton { + width: 300px; + height: 78px; + background: #7A808D; + border-radius: 12px; + border: none; + justify-content: center; + align-items: center; + gap: 10px; + display: flex; + cursor: pointer; + transition: background-color 0.2s ease; + + color: white; + font-size: 30px; + font-family: 'LG Smart UI', sans-serif; + font-weight: 700; + line-height: 30px; + text-align: center; + + &:hover { + background: #6a7278; + } + + &:focus { + outline: 2px solid #fff; + outline-offset: 2px; + } + + &:active { + background: #5a6268; + } +}