[251122] fix: DetailPanel ThemeButton

🕐 커밋 시간: 2025. 11. 22. 22:11:22

📊 변경 통계:
  • 총 파일: 3개
  • 추가: +91줄
  • 삭제: -7줄

📁 추가된 파일:
  + com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/heightCalculator.js

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.module.less

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx (javascript):
    🔄 Modified: extractProductMeta()
  📄 com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/heightCalculator.js (javascript):
     Added: handleResize()

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
This commit is contained in:
2025-11-22 22:11:22 +09:00
parent ec5829eebe
commit dbbd7114a2
3 changed files with 198 additions and 7 deletions

View File

@@ -15,6 +15,7 @@ import couponImg from '../../../../assets/images/icons/coupon.png';
// import Spottable from '@enact/spotlight/Spottable'; // import Spottable from '@enact/spotlight/Spottable';
//image //image
import arrowDown from '../../../../assets/images/icons/ic_arrow_down_3x_new.png'; import arrowDown from '../../../../assets/images/icons/ic_arrow_down_3x_new.png';
import arrowDownIcon from '../../../../assets/images/icons/ic-arrow-down.svg';
import indicatorDefaultImage from '../../../../assets/images/img-thumb-empty-144@3x.png'; import indicatorDefaultImage from '../../../../assets/images/img-thumb-empty-144@3x.png';
import { setHidePopup, setShowPopup } from '../../../actions/commonActions.js'; import { setHidePopup, setShowPopup } from '../../../actions/commonActions.js';
import { import {
@@ -1452,15 +1453,22 @@ export default function ProductAllSection({
})()} */} })()} */}
</Container> </Container>
{panelInfo && panelInfo.type === 'theme' && !openThemeItemOverlay && ( {/* Theme Item Button - 새로운 bottomButtonWrapper로 감싸기 */}
<TButton {/* {panelInfo && panelInfo.type === 'theme' && !openThemeItemOverlay && ( */}
<Container
className={css.bottomButtonWrapper}
spotlightId="theme-item-button-container"
>
<div
className={css.themeButton} className={css.themeButton}
onClick={handleThemeItemButtonClick} onClick={handleThemeItemButtonClick}
spotlightId="theme-open-button" spotlightId="theme-open-button"
> >
{$L('THEME ITEM')} <div>{$L('THEME ITEM')}</div>
</TButton> <img src={arrowDownIcon} className={css.themeButtonIcon} />
)} </div>
</Container>
{/* )} */}
<DetailMobileSendPopUp <DetailMobileSendPopUp
ismobileSendPopupOpen={mobileSendPopupOpen} ismobileSendPopupOpen={mobileSendPopupOpen}

View File

@@ -444,7 +444,7 @@
align-items: center !important; align-items: center !important;
justify-content: center !important; justify-content: center !important;
&:focus { &:focus {
background: @PRIMARY_COLOR_RED !important; background: @PRIMARY_COLOR_RED !important;
> div { > div {
.couponText { .couponText {
color: white !important; color: white !important;
@@ -459,7 +459,7 @@
color: white !important; color: white !important;
font-size: 25px !important; font-size: 25px !important;
font-family: @baseFont !important; font-family: @baseFont !important;
font-weight: 400 !important; font-weight: 400 !important;
text-align: center !important; text-align: center !important;
} }
.buttonImg { .buttonImg {
@@ -661,6 +661,24 @@
} }
} }
// Theme Item Button을 위한 새로운 Wrapper
.bottomButtonWrapper {
position: absolute;
bottom: 40px; // 바닥에서 40px 마진
left: 60px; // 왼쪽에서 60px
width: 635px; // 고정 너비
min-width: 13.5rem; // 최소 너비
max-width: 27.08333rem; // 최대 너비
letter-spacing: -0.75px; // 자간 조정
> * {
margin-bottom: 5px;
&:last-child {
margin-bottom: 0;
}
}
}
.productDetailsButton, .productDetailsButton,
.userReviewsButton, .userReviewsButton,
.youMayLikeButton { .youMayLikeButton {
@@ -689,6 +707,64 @@
} }
} }
.productDetailsButton,
.userReviewsButton,
.youMayLikeButton {
align-self: stretch;
height: 60px;
background: rgba(255, 255, 255, 0.05); // 기본 회색 배경
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
color: #eaeaea;
font-size: 25px;
font-family: @baseFont; // LG Smart 폰트 사용
font-weight: 400; // Bold에서 Regular로 변경
line-height: 35px;
&:focus {
background: @PRIMARY_COLOR_RED; // 포커스시만 빨간색
}
&.active {
border: 4px solid #4f172c;
background: #4f172c;
}
}
.themeButton {
width: 100%;
height: 60px;
padding: 20px 30px;
background: rgba(255, 255, 255, 0.05);
overflow: hidden;
border-radius: 6px;
justify-content: center;
align-items: center;
gap: 15px;
display: inline-flex;
color: white;
font-size: 25px;
font-family: @baseFont; // LG Smart UI
font-weight: 600;
line-height: 35px;
word-wrap: break-word;
&:focus {
background: @PRIMARY_COLOR_RED;
}
}
.themeButtonIcon {
width: 52.5px;
height: 31.25px;
object-fit: contain;
}
.addToCartButton { .addToCartButton {
flex: 1 1 0% !important; flex: 1 1 0% !important;
width: auto !important; width: auto !important;

View File

@@ -0,0 +1,107 @@
// InfoSection 높이 측정을 위한 유틸리티 함수
// InfoSection 내부 요소들의 높이를 계산하는 함수
export const calculateInfoSectionHeight = (infoSectionElement) => {
if (!infoSectionElement) {
console.error('InfoSection element not found');
return null;
}
const result = {
// 전체 InfoSection 높이
totalHeight: infoSectionElement.offsetHeight || infoSectionElement.clientHeight,
// 내부 요소들의 높이
elements: {},
};
// 주요 요소들의 높이 측정
const selectors = [
'.leftInfoContainer', // 전체 왼쪽 컨테이너
'.leftInfoWrapper', // 내부 래퍼
'.headerContent', // 헤더 콘텐츠 (태그, 별점)
'.productOverview', // 제품 개요
'.qrWrapper', // QR 코드
'.buttonStackContainer', // 버튼 스택 컨테이너
'.couponStackContainer', // 쿠폰 스택 (있을 경우)
'.buyNowCartContainer', // BUY NOW + ADD TO CART (있을 경우)
'.buttonContainer', // SHOP BY MOBILE (있을 경우)
'.callToOrderSection', // 전화 주문 섹션
'.actionButtonsWrapper', // PRODUCT DETAILS, USER REVIEWS, YOU MAY ALSO LIKE
'.themeButton', // THEME ITEM 버튼
'.DetailMobileSendPopUp', // 모바일 전송 팝업
];
selectors.forEach((selector) => {
const element = infoSectionElement.querySelector(selector);
if (element) {
result.elements[selector] = {
height: element.offsetHeight,
clientHeight: element.clientHeight,
scrollHeight: element.scrollHeight,
marginTop: parseInt(window.getComputedStyle(element).marginTop) || 0,
marginBottom: parseInt(window.getComputedStyle(element).marginBottom) || 0,
paddingTop: parseInt(window.getComputedStyle(element).paddingTop) || 0,
paddingBottom: parseInt(window.getComputedStyle(element).paddingBottom) || 0,
isVisible: element.offsetParent !== null,
};
}
});
// 실제 사용된 높이 계산
const calculatedHeight = Object.values(result.elements).reduce((total, element) => {
if (element && element.isVisible) {
return total + element.height + element.marginTop + element.marginBottom;
}
return total;
}, 0);
result.calculatedHeight = calculatedHeight;
result.remainingSpace = result.totalHeight - calculatedHeight;
result.isOverflowing = calculatedHeight > result.totalHeight;
return result;
};
// React Hook으로 만든 버전
export const useInfoSectionHeight = (infoSectionRef) => {
const [heightInfo, setHeightInfo] = useState(null);
const measureHeight = useCallback(() => {
if (infoSectionRef.current) {
const info = calculateInfoSectionHeight(infoSectionRef.current);
setHeightInfo(info);
console.log('InfoSection Height Info:', info);
return info;
}
}, [infoSectionRef]);
// 컴포넌트 마운트 시 측정
useEffect(() => {
measureHeight();
}, [measureHeight]);
// 윈도우 리사이즈 시 재측정 (선택사항)
useEffect(() => {
const handleResize = () => {
measureHeight();
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [measureHeight]);
return {
heightInfo,
measureHeight,
};
};
// 사용 예시:
// const infoSectionRef = useRef(null);
// const { heightInfo, measureHeight } = useInfoSectionHeight(infoSectionRef);
//
// // JSX에서
// <div ref={infoSectionRef} className={css.infoSection}>
// ... content ...
// </div>