"[GIT AUTO COMMIT]: Fri Sep 05 2025 16:21:25 GMT+0900 (대한민국 표준시)"

This commit is contained in:
junghoon86.park
2025-09-05 16:21:25 +09:00
parent 62d32a6f6f
commit 39e1598d22
13 changed files with 287 additions and 215 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -11,8 +11,8 @@
rgba(0, 0, 0, 0.539) 73.73%, rgba(0, 0, 0, 0.539) 73.73%,
rgba(0, 0, 0, 0.7) 100% rgba(0, 0, 0, 0.7) 100%
), ),
linear-gradient(0deg, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)); linear-gradient(0deg, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)),
// var(--bg-url); url("../../../assets/images/default_bg_image.png");
} }
.header { .header {

View File

@@ -1,49 +1,75 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import classNames from 'classnames';
import { PropTypes } from 'prop-types';
import {
useDispatch,
useSelector,
} from 'react-redux';
import Spotlight from '@enact/spotlight';
/* eslint-disable react/jsx-no-bind */ /* eslint-disable react/jsx-no-bind */
// src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx // src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator"; import SpotlightContainerDecorator
import Spottable from "@enact/spotlight/Spottable"; from '@enact/spotlight/SpotlightContainerDecorator';
import React, { useCallback, useRef, useState, useMemo, useEffect } from "react"; import Spottable from '@enact/spotlight/Spottable';
import { useSelector, useDispatch } from "react-redux";
import Spotlight from "@enact/spotlight";
import { PropTypes } from "prop-types";
import { toggleShowAllReviews } from '../../../actions/productActions';
// ProductInfoSection imports // ProductInfoSection imports
import TButton from "../../../components/TButton/TButton"; import TButton from '../../../components/TButton/TButton';
import { $L } from "../../../utils/helperMethods"; import useScrollTo from '../../../hooks/useScrollTo';
import { import {
curry, pipe, when, isVal, isNotNil, defaultTo, defaultWith, get, identity, isEmpty, isNil, andThen, tap andThen,
} from "../../../utils/fp"; curry,
import { toggleShowAllReviews } from "../../../actions/productActions"; defaultTo,
import FavoriteBtn from "../components/FavoriteBtn"; defaultWith,
import StarRating from "../components/StarRating"; get,
import ProductTag from "../components/ProductTag"; identity,
import DetailMobileSendPopUp from "../components/DetailMobileSendPopUp"; isEmpty,
import { SpotlightIds } from "../../../utils/SpotlightIds"; isNil,
import QRCode from "../ProductInfoSection/QRCode/QRCode"; isNotNil,
import ProductOverview from "../ProductOverview/ProductOverview"; isVal,
pipe,
tap,
when,
} from '../../../utils/fp';
import { $L } from '../../../utils/helperMethods';
import { SpotlightIds } from '../../../utils/SpotlightIds';
import CustomScrollbar from '../components/CustomScrollbar/CustomScrollbar';
import DetailMobileSendPopUp from '../components/DetailMobileSendPopUp';
import FavoriteBtn from '../components/FavoriteBtn';
import ProductTag from '../components/ProductTag';
import StarRating from '../components/StarRating';
// ProductContentSection imports // ProductContentSection imports
import TScrollerDetail from "../components/TScroller/TScrollerDetail"; import TScrollerDetail from '../components/TScroller/TScrollerDetail';
import CustomScrollbar from "../components/CustomScrollbar/CustomScrollbar"; import ProductDescription
import useScrollTo from "../../../hooks/useScrollTo"; from '../ProductContentSection/ProductDescription/ProductDescription';
import ProductDetail from "../ProductContentSection/ProductDetail/ProductDetail.new"; import ProductDetail
import UserReviews from "../ProductContentSection/UserReviews/UserReviews"; from '../ProductContentSection/ProductDetail/ProductDetail.new';
import YouMayAlsoLike from "../ProductContentSection/YouMayAlsoLike/YouMayAlsoLike"; import UserReviews from '../ProductContentSection/UserReviews/UserReviews';
import ProductDescription from "../ProductContentSection/ProductDescription/ProductDescription"; import YouMayAlsoLike
from '../ProductContentSection/YouMayAlsoLike/YouMayAlsoLike';
import QRCode from '../ProductInfoSection/QRCode/QRCode';
import ProductOverview from '../ProductOverview/ProductOverview';
// CSS imports // CSS imports
// import infoCSS from "../ProductInfoSection/ProductInfoSection.module.less"; // import infoCSS from "../ProductInfoSection/ProductInfoSection.module.less";
// import contentCSS from "../ProductContentSection/ProductContentSection.module.less"; // import contentCSS from "../ProductContentSection/ProductContentSection.module.less";
import css from "./ProductAllSection.module.less"; import css from './ProductAllSection.module.less';
const Container = SpotlightContainerDecorator( const Container = SpotlightContainerDecorator(
{ {
enterTo: "last-focused", enterTo: "last-focused",
preserveld: true, preserveld: true,
leaveFor: { right: "content-scroller-container" }, leaveFor: { right: "content-scroller-container" },
spotlightDirection: "vertical" spotlightDirection: "vertical",
}, },
"div", "div"
); );
const ContentContainer = SpotlightContainerDecorator( const ContentContainer = SpotlightContainerDecorator(
@@ -51,12 +77,12 @@ const ContentContainer = SpotlightContainerDecorator(
enterTo: "default-element", enterTo: "default-element",
preserveld: true, preserveld: true,
leaveFor: { leaveFor: {
left: "spotlight-product-info-section-container" left: "spotlight-product-info-section-container",
}, },
restrict: "none", restrict: "none",
spotlightDirection: "vertical" spotlightDirection: "vertical",
}, },
"div", "div"
); );
const HorizontalContainer = SpotlightContainerDecorator( const HorizontalContainer = SpotlightContainerDecorator(
@@ -64,17 +90,19 @@ const HorizontalContainer = SpotlightContainerDecorator(
enterTo: "last-focused", enterTo: "last-focused",
preserveld: true, preserveld: true,
defaultElement: "spotlight-product-info-section-container", defaultElement: "spotlight-product-info-section-container",
spotlightDirection: "horizontal" spotlightDirection: "horizontal",
}, },
"div", "div"
); );
// FP: Pure function to determine product data based on type // FP: Pure function to determine product data based on type
const getProductData = curry((productType, themeProductInfo, productInfo) => const getProductData = curry((productType, themeProductInfo, productInfo) =>
pipe( pipe(
when( when(
() => isVal(productType) && productType === "theme" && isVal(themeProductInfo), () =>
isVal(productType) &&
productType === "theme" &&
isVal(themeProductInfo),
() => themeProductInfo () => themeProductInfo
), ),
defaultTo(productInfo), defaultTo(productInfo),
@@ -86,19 +114,14 @@ const getProductData = curry((productType, themeProductInfo, productInfo) =>
const deriveFavoriteFlag = curry((favoriteOverride, productData) => const deriveFavoriteFlag = curry((favoriteOverride, productData) =>
pipe( pipe(
when(isNotNil, identity), when(isNotNil, identity),
defaultWith(() => defaultWith(() => pipe(get("favorYn"), defaultTo("N"))(productData))
pipe(
get("favorYn"),
defaultTo("N")
)(productData)
)
)(favoriteOverride) )(favoriteOverride)
); );
// FP: Pure function to extract review grade and order phone // FP: Pure function to extract review grade and order phone
const extractProductMeta = (productInfo) => ({ const extractProductMeta = (productInfo) => ({
revwGrd: get("revwGrd", productInfo), revwGrd: get("revwGrd", productInfo),
orderPhnNo: get("orderPhnNo", productInfo) orderPhnNo: get("orderPhnNo", productInfo),
}); });
// 레이아웃 확인용 샘플 컴포넌트 - Spottable로 변경 // 레이아웃 확인용 샘플 컴포넌트 - Spottable로 변경
@@ -128,14 +151,16 @@ export default function ProductAllSection({
}) { }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const productData = useMemo(() => const productData = useMemo(
getProductData(productType, themeProductInfo, productInfo), () => getProductData(productType, themeProductInfo, productInfo),
[productType, themeProductInfo, productInfo] [productType, themeProductInfo, productInfo]
); );
// [임시 테스트] LayoutSample 클릭 핸들러 // [임시 테스트] LayoutSample 클릭 핸들러
const handleLayoutSampleClick = useCallback(() => { const handleLayoutSampleClick = useCallback(() => {
console.log("[Test] LayoutSample clicked - dispatching toggleShowAllReviews"); console.log(
"[Test] LayoutSample clicked - dispatching toggleShowAllReviews"
);
dispatch(toggleShowAllReviews()); dispatch(toggleShowAllReviews());
}, [dispatch]); }, [dispatch]);
@@ -145,19 +170,21 @@ export default function ProductAllSection({
hasProductData: !!productData, hasProductData: !!productData,
imgUrls600: productData?.imgUrls600, imgUrls600: productData?.imgUrls600,
imgUrls600Length: productData?.imgUrls600?.length, imgUrls600Length: productData?.imgUrls600?.length,
imgUrls600Type: Array.isArray(productData?.imgUrls600) ? 'array' : typeof productData?.imgUrls600 imgUrls600Type: Array.isArray(productData?.imgUrls600)
? "array"
: typeof productData?.imgUrls600,
}); });
}, [productData]); }, [productData]);
const { revwGrd, orderPhnNo } = useMemo(() => const { revwGrd, orderPhnNo } = useMemo(
extractProductMeta(productInfo), () => extractProductMeta(productInfo),
[productInfo] [productInfo]
); );
// FP: derive favorite flag from props with local override, avoid non-I/O useEffect // FP: derive favorite flag from props with local override, avoid non-I/O useEffect
const [favoriteOverride, setFavoriteOverride] = useState(null); const [favoriteOverride, setFavoriteOverride] = useState(null);
const favoriteFlag = useMemo(() => const favoriteFlag = useMemo(
deriveFavoriteFlag(favoriteOverride, productData), () => deriveFavoriteFlag(favoriteOverride, productData),
[favoriteOverride, productData] [favoriteOverride, productData]
); );
@@ -167,10 +194,12 @@ export default function ProductAllSection({
const showUserReviewsButton = false; // 임시 변경 - 버튼 숨김 const showUserReviewsButton = false; // 임시 변경 - 버튼 숨김
const showUserReviewsSection = true; // 임시 변경 - 섹션은 항상 표시 const showUserReviewsSection = true; // 임시 변경 - 섹션은 항상 표시
const reviewTotalCount = useSelector(pipe( const reviewTotalCount = useSelector(
get(["product", "reviewData", "reviewDetail", "totRvwCnt"]), pipe(
defaultTo(0) get(["product", "reviewData", "reviewDetail", "totRvwCnt"]),
)); defaultTo(0)
)
);
// User Reviews 스크롤 핸들러 추가 // User Reviews 스크롤 핸들러 추가
const handleUserReviewsClick = useCallback( const handleUserReviewsClick = useCallback(
@@ -181,13 +210,9 @@ export default function ProductAllSection({
const scrollContainerRef = useRef(null); const scrollContainerRef = useRef(null);
const { getScrollTo, scrollTop } = useScrollTo(); const { getScrollTo, scrollTop } = useScrollTo();
// FP: Pure function for mobile popup state change // FP: Pure function for mobile popup state change
const handleShopByMobileOpen = useCallback( const handleShopByMobileOpen = useCallback(
pipe( pipe(() => true, setMobileSendPopupOpen),
() => true,
setMobileSendPopupOpen
),
[] []
); );
@@ -237,7 +262,6 @@ export default function ProductAllSection({
[scrollToSection] [scrollToSection]
); );
return ( return (
<HorizontalContainer className={css.detailArea}> <HorizontalContainer className={css.detailArea}>
{/* Left Margin Section - 60px */} {/* Left Margin Section - 60px */}
@@ -277,7 +301,10 @@ export default function ProductAllSection({
<Container className={css.buttonContainer}> <Container className={css.buttonContainer}>
<TButton <TButton
spotlightId={SpotlightIds.DETAIL_SHOPBYMOBILE} spotlightId={SpotlightIds.DETAIL_SHOPBYMOBILE}
className={css.shopByMobileButton} className={classNames(
css.shopByMobileButton,
css.shopByMobileOne
)}
onClick={handleShopByMobileOpen} onClick={handleShopByMobileOpen}
onSpotlightUp={handleSpotlightUpToBackButton} onSpotlightUp={handleSpotlightUpToBackButton}
> >
@@ -293,6 +320,7 @@ export default function ProductAllSection({
selectedPrdtId={panelInfo && panelInfo.prdtId} selectedPrdtId={panelInfo && panelInfo.prdtId}
favoriteFlag={favoriteFlag} favoriteFlag={favoriteFlag}
onFavoriteFlagChanged={onFavoriteFlagChanged} onFavoriteFlagChanged={onFavoriteFlagChanged}
kind={"item_detail"}
/> />
</div> </div>
)} )}
@@ -324,14 +352,15 @@ export default function ProductAllSection({
{$L("PRODUCT DETAILS")} {$L("PRODUCT DETAILS")}
</TButton> </TButton>
{/* 🔧 [임시] 고객 데모용 조건 변경: showUserReviewsButton (원래: reviewTotalCount > 0) */} {/* 🔧 [임시] 고객 데모용 조건 변경: showUserReviewsButton (원래: reviewTotalCount > 0) */}
{showUserReviewsButton && ( {/* {showUserReviewsButton && ( */}
{reviewTotalCount > 0 && (
<TButton <TButton
className={css.userReviewsButton} className={css.userReviewsButton}
onClick={handleUserReviewsClick} onClick={handleUserReviewsClick}
spotlightId="user-reviews-button" spotlightId="user-reviews-button"
> >
{$L( {$L(
`USER REVIEWS (${reviewTotalCount > 100 ? "100" : reviewTotalCount || "0"})`, `USER REVIEWS (${reviewTotalCount > 100 ? "100" : reviewTotalCount || "0"})`
)} )}
</TButton> </TButton>
)} )}
@@ -344,7 +373,8 @@ export default function ProductAllSection({
</Container> </Container>
{panelInfo && {panelInfo &&
panelInfo && panelInfo.type === "theme" && panelInfo &&
panelInfo.type === "theme" &&
!openThemeItemOverlay && ( !openThemeItemOverlay && (
<TButton <TButton
className={css.themeButton} className={css.themeButton}
@@ -390,7 +420,8 @@ export default function ProductAllSection({
></div> ></div>
<LayoutSample onClick={handleLayoutSampleClick} /> <LayoutSample onClick={handleLayoutSampleClick} />
<div id="product-details-section"> <div id="product-details-section">
{productData?.imgUrls600 && productData.imgUrls600.length > 0 ? ( {productData?.imgUrls600 &&
productData.imgUrls600.length > 0 ? (
productData.imgUrls600.map((image, index) => ( productData.imgUrls600.map((image, index) => (
<ProductDetail <ProductDetail
key={`product-detail-${index}`} key={`product-detail-${index}`}
@@ -398,7 +429,7 @@ export default function ProductAllSection({
...productData, ...productData,
singleImage: image, singleImage: image,
imageIndex: index, imageIndex: index,
totalImages: productData.imgUrls600.length totalImages: productData.imgUrls600.length,
}} }}
/> />
)) ))
@@ -409,10 +440,16 @@ export default function ProductAllSection({
<div id="product-description-section"> <div id="product-description-section">
<ProductDescription productInfo={productData} /> <ProductDescription productInfo={productData} />
</div> </div>
<div id="scroll-marker-user-reviews" className={css.scrollMarker}></div> <div
id="scroll-marker-user-reviews"
className={css.scrollMarker}
></div>
{/* Description 바로 아래에 UserReviews 항상 표시 (조건 제거) */} {/* Description 바로 아래에 UserReviews 항상 표시 (조건 제거) */}
<div id="user-reviews-section"> <div id="user-reviews-section">
<UserReviews productInfo={productData} panelInfo={panelInfo} /> <UserReviews
productInfo={productData}
panelInfo={panelInfo}
/>
</div> </div>
</div> </div>
<div <div
@@ -420,13 +457,15 @@ export default function ProductAllSection({
className={css.scrollMarker} className={css.scrollMarker}
></div> ></div>
<div id="you-may-also-like-section"> <div id="you-may-also-like-section">
<YouMayAlsoLike productInfo={productData} panelInfo={panelInfo} /> <YouMayAlsoLike
productInfo={productData}
panelInfo={panelInfo}
/>
</div> </div>
</TScrollerDetail> </TScrollerDetail>
</div> </div>
</ContentContainer> </ContentContainer>
</div> </div>
</HorizontalContainer> </HorizontalContainer>
); );
} }

View File

@@ -35,7 +35,7 @@
position: absolute; position: absolute;
left: 60px; left: 60px;
top: 0; top: 0;
width: 645px; width: 650px;
height: 100%; height: 100%;
padding: 0; padding: 0;
margin: 0; margin: 0;
@@ -88,7 +88,9 @@
// gap 대신 margin 사용 (Chromium 68 호환성) // gap 대신 margin 사용 (Chromium 68 호환성)
> * { > * {
margin-bottom: 5px; margin-bottom: 5px;
&:last-child { margin-bottom: 0; } &:last-child {
margin-bottom: 0;
}
} }
} }
@@ -115,7 +117,6 @@
align-items: flex-start; align-items: flex-start;
position: relative; // 자식 absolute 요소의 기준점 position: relative; // 자식 absolute 요소의 기준점
// 스크롤러 오버라이드 (1210px = 30px + content + 스크롤바) // 스크롤러 오버라이드 (1210px = 30px + content + 스크롤바)
.scrollerOverride { .scrollerOverride {
width: 1210px; // 절대 크기 지정 width: 1210px; // 절대 크기 지정
@@ -139,17 +140,16 @@
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background: #9C9C9C; // 스크롤바 색상 background: #9c9c9c; // 스크롤바 색상
border-radius: 3px; // 스크롤바 둥근 모서리 border-radius: 3px; // 스크롤바 둥근 모서리
} }
// 스크롤바 thumb에 hover 효과 적용 // 스크롤바 thumb에 hover 효과 적용
&:hover::-webkit-scrollbar-thumb { &:hover::-webkit-scrollbar-thumb {
background: #C72054; background: #c72054;
} }
} }
// 내부 콘텐츠는 별도 너비 계산 없이 100%를 사용 // 내부 콘텐츠는 별도 너비 계산 없이 100%를 사용
> div { > div {
width: 100%; // 부모의 패딩을 제외한 나머지 공간(1114px)을 모두 사용 width: 100%; // 부모의 패딩을 제외한 나머지 공간(1114px)을 모두 사용
@@ -229,7 +229,6 @@
// (중복 제거됨) 최상위 스크롤러/섹션 정의는 .scrollerWrapper 중첩 내부로 이동 // (중복 제거됨) 최상위 스크롤러/섹션 정의는 .scrollerWrapper 중첩 내부로 이동
// ProductDetailCard 스타일 참고 - 크기/간격만 적용 // ProductDetailCard 스타일 참고 - 크기/간격만 적용
// 헤더 컨텐츠 영역 (태그, 별점) // 헤더 컨텐츠 영역 (태그, 별점)
@@ -237,7 +236,6 @@
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
} }
// 모바일 쇼핑 섹션 (mobileSection 참고) // 모바일 쇼핑 섹션 (mobileSection 참고)
@@ -250,7 +248,9 @@
> * { > * {
margin-right: 6px; margin-right: 6px;
&:last-child { margin-right: 0; } &:last-child {
margin-right: 0;
}
} }
} }
@@ -258,14 +258,17 @@
flex: 1 1 0 !important; flex: 1 1 0 !important;
width: auto !important; // flex로 크기 조정 width: auto !important; // flex로 크기 조정
height: 60px !important; height: 60px !important;
background: rgba(68, 68, 68, 0.50) !important; background: rgba(68, 68, 68, 0.5) !important;
border-radius: 6px !important; border-radius: 6px !important;
border: none !important; border: none !important;
padding: 0 !important; padding: 0 !important;
margin: 0 !important; margin: 0;
display: flex !important; display: flex !important;
align-items: center !important; align-items: center !important;
justify-content: center !important; justify-content: center !important;
&.shopByMobileOne {
margin: 0 10px 0 0;
}
.shopByMobileText { .shopByMobileText {
color: white !important; color: white !important;
@@ -308,7 +311,7 @@
align-items: center; align-items: center;
.callToOrderText { .callToOrderText {
color: #EAEAEA; color: #eaeaea;
font-size: 25px; font-size: 25px;
font-family: @baseFont; // LG Smart 폰트 사용 font-family: @baseFont; // LG Smart 폰트 사용
font-weight: 400; // Bold에서 Regular로 변경 font-weight: 400; // Bold에서 Regular로 변경
@@ -322,7 +325,9 @@
> * { > * {
margin-right: 10px; margin-right: 10px;
&:last-child { margin-right: 0; } &:last-child {
margin-right: 0;
}
} }
.phoneIconContainer { .phoneIconContainer {
@@ -337,7 +342,6 @@
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
background: #EAEAEA;
// 전화 아이콘 이미지 또는 CSS로 구현 // 전화 아이콘 이미지 또는 CSS로 구현
background-image: url("../../../../assets/images/icons/ic-gr-call-1.png"); background-image: url("../../../../assets/images/icons/ic-gr-call-1.png");
background-size: contain; background-size: contain;
@@ -347,9 +351,9 @@
} }
.phoneNumber { .phoneNumber {
color: #EAEAEA; color: #eaeaea;
font-size: 25px; font-size: 25px;
font-family: 'LG Smart UI'; font-family: "LG Smart UI";
font-weight: 700; font-weight: 700;
line-height: 35px; line-height: 35px;
} }
@@ -365,7 +369,9 @@
> * { > * {
margin-bottom: 5px; margin-bottom: 5px;
&:last-child { margin-bottom: 0; } &:last-child {
margin-bottom: 0;
}
} }
} }
@@ -381,14 +387,14 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: #EAEAEA; color: #eaeaea;
font-size: 25px; font-size: 25px;
font-family: @baseFont; // LG Smart 폰트 사용 font-family: @baseFont; // LG Smart 폰트 사용
font-weight: 400; // Bold에서 Regular로 변경 font-weight: 400; // Bold에서 Regular로 변경
line-height: 35px; line-height: 35px;
&:focus { &:focus {
background: #C72054; // 포커스시만 빨간색 background: #c72054; // 포커스시만 빨간색
} }
} }
@@ -400,7 +406,7 @@
margin-top: 10px; margin-top: 10px;
&:focus { &:focus {
background: #C72054; background: #c72054;
} }
} }
@@ -414,7 +420,9 @@
> * { > * {
margin-bottom: 10px; margin-bottom: 10px;
&:last-child { margin-bottom: 0; } &:last-child {
margin-bottom: 0;
}
} }
} }
@@ -430,37 +438,12 @@
// 내부 div (productInfoWrapper) // 내부 div (productInfoWrapper)
> div { > div {
align-self: stretch; align-self: stretch;
display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: flex-start; align-items: flex-start;
}
> * { > div:first-child {
margin-right: 15px; // ProductDetailCard와 동일한 간격 width: 380px;
&:last-child { margin-right: 0; } text-align: left;
}
// 가격 섹션 (flex로 남은 공간 차지)
> div:first-child {
flex: 1 1 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
// 이미지 섹션 (QR 포함, 고정 크기)
> div:last-child {
width: 240px;
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
> * {
margin-bottom: 10px;
&:last-child { margin-bottom: 0; }
}
}
} }
} }

View File

@@ -1,11 +1,17 @@
import React, { useCallback, useMemo } from "react"; import React, {
import { useSelector } from "react-redux"; useCallback,
import usePriceInfo from "../../../../hooks/usePriceInfo"; useMemo,
import css from "./ProductPriceDisplay.module.less"; } from 'react';
import { $L } from "../../../../utils/helperMethods";
import classNames from "classnames"; import classNames from 'classnames';
import ShopByMobilePriceDisplay from "./ShopByMobilePriceDisplay/ShopByMobilePriceDisplay"; import { useSelector } from 'react-redux';
import BuyNowPriceDisplay from "./BuyNowPriceDisplay/BuyNowPriceDisplay";
import usePriceInfo from '../../../../hooks/usePriceInfo';
import { $L } from '../../../../utils/helperMethods';
import BuyNowPriceDisplay from './BuyNowPriceDisplay/BuyNowPriceDisplay';
import css from './ProductPriceDisplay.module.less';
import ShopByMobilePriceDisplay
from './ShopByMobilePriceDisplay/ShopByMobilePriceDisplay';
export default function ProductPriceDisplay({ productType, productInfo }) { export default function ProductPriceDisplay({ productType, productInfo }) {
const webOSVersion = useSelector( const webOSVersion = useSelector(

View File

@@ -7,7 +7,7 @@
.partnerName { .partnerName {
font-weight: bold; font-weight: bold;
font-size: 36px; font-size: 36px;
color: @COLOR_BLACK; color: @COLOR_WHITE;
margin-bottom: 24px; margin-bottom: 24px;
} }
.flex(@alignCenter:flex-start,@direction:column); .flex(@alignCenter:flex-start,@direction:column);

View File

@@ -1,8 +1,13 @@
import React, { useCallback, useMemo } from "react"; import React, {
import usePriceInfo from "../../../../../hooks/usePriceInfo"; useCallback,
import { $L } from "../../../../../utils/helperMethods"; useMemo,
import css from "./ShopByMobilePriceDisplay.module.less"; } from 'react';
import classNames from "classnames";
import classNames from 'classnames';
import usePriceInfo from '../../../../../hooks/usePriceInfo';
import { $L } from '../../../../../utils/helperMethods';
import css from './ShopByMobilePriceDisplay.module.less';
export default function ShopByMobilePriceDisplay({ export default function ShopByMobilePriceDisplay({
priceData, priceData,
@@ -103,14 +108,14 @@ export default function ShopByMobilePriceDisplay({
return ( return (
<div className={css.wrapper}> <div className={css.wrapper}>
<div className={css.topLayer}> <div className={css.topLayer}>
{discountRate && Number(discountRate.replace("%", "")) > 4 && (
<div className={css.rateTag}>{discountRate}</div>
)}
<span className={css.name}> <span className={css.name}>
{patncNm {patncNm
? patncNm + " " + $L("Price") ? patncNm + " " + $L("Price")
: patnrName + $L("Price")} : patnrName + $L("Price")}
</span> </span>
{discountRate && Number(discountRate.replace("%", "")) > 4 && (
<div className={css.rateTag}>{discountRate}</div>
)}
</div> </div>
<div className={css.btmLayer}> <div className={css.btmLayer}>
<span className={css.price}> <span className={css.price}>

View File

@@ -7,7 +7,7 @@
.partnerName { .partnerName {
font-weight: bold; font-weight: bold;
font-size: 36px; font-size: 36px;
color: @COLOR_BLACK; color: @COLOR_WHITE;
margin-bottom: 24px; margin-bottom: 24px;
} }
.flex(@alignCenter:flex-start,@direction:column); .flex(@alignCenter:flex-start,@direction:column);
@@ -31,7 +31,8 @@
.name { .name {
font-weight: bold; font-weight: bold;
font-size: 36px; font-size: 36px;
color: @COLOR_GRAY07; color: @COLOR_WHITE;
width: 100%;
} }
.btmLayer { .btmLayer {
.flex(); .flex();

View File

@@ -1,23 +1,32 @@
import React, { useCallback, useEffect } from "react"; import React, {
useCallback,
useEffect,
} from 'react';
import classNames from "classnames"; import classNames from 'classnames';
import { useDispatch, useSelector } from "react-redux"; import {
useDispatch,
useSelector,
} from 'react-redux';
import Spotlight from "@enact/spotlight"; import Spotlight from '@enact/spotlight';
import { setHidePopup, setShowPopup } from "../../../actions/commonActions"; import {
setHidePopup,
setShowPopup,
} from '../../../actions/commonActions';
import { sendLogTotalRecommend } from '../../../actions/logActions';
import { import {
getMyFavoriteFlag, getMyFavoriteFlag,
setMainLikeCategory, setMainLikeCategory,
} from "../../../actions/mainActions"; } from '../../../actions/mainActions';
import { deleteMyFavorite } from "../../../actions/myPageActions"; import { deleteMyFavorite } from '../../../actions/myPageActions';
import TButton from "../../../components/TButton/TButton"; import TButton from '../../../components/TButton/TButton';
import TPopUp from "../../../components/TPopUp/TPopUp"; import TPopUp from '../../../components/TPopUp/TPopUp';
import * as Config from "../../../utils/Config"; import { disableNotification } from '../../../lunaSend';
import { $L } from "../../../utils/helperMethods"; import * as Config from '../../../utils/Config';
import css from "./FavoriteBtn.module.less"; import { $L } from '../../../utils/helperMethods';
import { disableNotification } from "../../../lunaSend"; import css from './FavoriteBtn.module.less';
import { sendLogTotalRecommend } from "../../../actions/logActions";
export default function FavoriteBtn({ export default function FavoriteBtn({
selectedPatnrId, selectedPatnrId,
@@ -25,6 +34,7 @@ export default function FavoriteBtn({
favoriteFlag, favoriteFlag,
onFavoriteFlagChanged, onFavoriteFlagChanged,
logMenu, logMenu,
kind,
}) { }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { popupVisible, activePopup } = useSelector( const { popupVisible, activePopup } = useSelector(
@@ -33,13 +43,13 @@ export default function FavoriteBtn({
const handleFavoriteClick = useCallback(() => { const handleFavoriteClick = useCallback(() => {
dispatch( dispatch(
sendLogTotalRecommend({ sendLogTotalRecommend({
menu: logMenu, menu: logMenu,
buttonTitle: "FAVORITE", buttonTitle: "FAVORITE",
contextName: Config.LOG_CONTEXT_NAME.DETAILPAGE, contextName: Config.LOG_CONTEXT_NAME.DETAILPAGE,
messageId: Config.LOG_MESSAGE_ID.BUTTONCLICK, messageId: Config.LOG_MESSAGE_ID.BUTTONCLICK,
}) })
); );
switch (favoriteFlag) { switch (favoriteFlag) {
case "N": case "N":
dispatch( dispatch(
@@ -61,7 +71,7 @@ export default function FavoriteBtn({
break; break;
} }
} }
}, [dispatch, favoriteFlag, selectedPatnrId, selectedPrdtId , logMenu]); }, [dispatch, favoriteFlag, selectedPatnrId, selectedPrdtId, logMenu]);
const PopUpOnClick = useCallback(() => { const PopUpOnClick = useCallback(() => {
setTimeout(() => Spotlight.focus("favoriteBtn")); setTimeout(() => Spotlight.focus("favoriteBtn"));
@@ -70,7 +80,12 @@ export default function FavoriteBtn({
}, [dispatch, favoriteFlag, onFavoriteFlagChanged]); }, [dispatch, favoriteFlag, onFavoriteFlagChanged]);
return ( return (
<div className={css.favorBtnContainer}> <div
className={classNames(
css.favorBtnContainer,
kind === "item_detail" ? css.smallSize : ""
)}
>
<TButton <TButton
className={classNames( className={classNames(
favoriteFlag === "N" ? css.favorBtn : css.favorUnableBtn favoriteFlag === "N" ? css.favorBtn : css.favorUnableBtn

View File

@@ -3,6 +3,29 @@
.favorBtnContainer { .favorBtnContainer {
height: 78px; height: 78px;
&.smallSize {
height: 60px;
.flex();
.favorBtn {
background-color: rgba(68, 68, 68, 0.5) !important;
min-width: 60px;
height: 60px;
background-image: url(../../../../assets/images/icons/ic_heart_3x.png);
.imgElement(29px, 25px, center, center);
&:focus {
background-color: @PRIMARY_COLOR_RED !important; // 포커스시 빨간색 배경
outline: 2px solid @PRIMARY_COLOR_RED !important;
background-image: url(../../../../assets/images/icons/ic_heart_3x.png);
}
}
.favorUnableBtn {
min-width: 60px;
height: 60px;
background-image: url(../../../../assets/images/icons/ic-heart-nor@3x.png);
.imgElement(54px, 54px, center, center);
}
}
.flex(); .flex();
.favorBtn { .favorBtn {
min-width: 78px; min-width: 78px;

View File

@@ -13,7 +13,6 @@
} }
.ProductBadge { .ProductBadge {
margin-left: auto;
height: 42px; height: 42px;
> span { > span {
height: 42px; height: 42px;

1
git-auto-commit Submodule

Submodule git-auto-commit added at d42d415623