[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:
@@ -15,6 +15,7 @@ import couponImg from '../../../../assets/images/icons/coupon.png';
|
||||
// import Spottable from '@enact/spotlight/Spottable';
|
||||
//image
|
||||
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 { setHidePopup, setShowPopup } from '../../../actions/commonActions.js';
|
||||
import {
|
||||
@@ -1452,15 +1453,22 @@ export default function ProductAllSection({
|
||||
})()} */}
|
||||
</Container>
|
||||
|
||||
{panelInfo && panelInfo.type === 'theme' && !openThemeItemOverlay && (
|
||||
<TButton
|
||||
{/* Theme Item Button - 새로운 bottomButtonWrapper로 감싸기 */}
|
||||
{/* {panelInfo && panelInfo.type === 'theme' && !openThemeItemOverlay && ( */}
|
||||
<Container
|
||||
className={css.bottomButtonWrapper}
|
||||
spotlightId="theme-item-button-container"
|
||||
>
|
||||
<div
|
||||
className={css.themeButton}
|
||||
onClick={handleThemeItemButtonClick}
|
||||
spotlightId="theme-open-button"
|
||||
>
|
||||
{$L('THEME ITEM')}
|
||||
</TButton>
|
||||
)}
|
||||
<div>{$L('THEME ITEM')}</div>
|
||||
<img src={arrowDownIcon} className={css.themeButtonIcon} />
|
||||
</div>
|
||||
</Container>
|
||||
{/* )} */}
|
||||
|
||||
<DetailMobileSendPopUp
|
||||
ismobileSendPopupOpen={mobileSendPopupOpen}
|
||||
|
||||
@@ -444,7 +444,7 @@
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
&:focus {
|
||||
background: @PRIMARY_COLOR_RED !important;
|
||||
background: @PRIMARY_COLOR_RED !important;
|
||||
> div {
|
||||
.couponText {
|
||||
color: white !important;
|
||||
@@ -459,7 +459,7 @@
|
||||
color: white !important;
|
||||
font-size: 25px !important;
|
||||
font-family: @baseFont !important;
|
||||
font-weight: 400 !important;
|
||||
font-weight: 400 !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
.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,
|
||||
.userReviewsButton,
|
||||
.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 {
|
||||
flex: 1 1 0% !important;
|
||||
width: auto !important;
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user