[구매부분수정]
- 상품상세 비디오 노출 제거. - 구매 옵션 미선택시 무반응처리 - 구매옵션넘겼을때 상품정보없을시에 목업상품으로 연결하여 구매쪽으로 넘어가도록 변경.
This commit is contained in:
@@ -1,19 +1,31 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
// import { throttle } from 'lodash';
|
||||
import { PropTypes } from 'prop-types';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
useDispatch,
|
||||
useSelector,
|
||||
} from 'react-redux';
|
||||
|
||||
import Spotlight from '@enact/spotlight';
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
// src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
|
||||
import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator';
|
||||
// import Spottable from '@enact/spotlight/Spottable';
|
||||
import SpotlightContainerDecorator
|
||||
from '@enact/spotlight/SpotlightContainerDecorator';
|
||||
|
||||
// import Spottable from '@enact/spotlight/Spottable';
|
||||
//image
|
||||
import arrowDown from '../../../../assets/images/icons/ic_arrow_down_3x_new.png';
|
||||
import indicatorDefaultImage from '../../../../assets/images/img-thumb-empty-144@3x.png';
|
||||
import arrowDown
|
||||
from '../../../../assets/images/icons/ic_arrow_down_3x_new.png';
|
||||
import indicatorDefaultImage
|
||||
from '../../../../assets/images/img-thumb-empty-144@3x.png';
|
||||
// import { pushPanel } from '../../../actions/panelActions';
|
||||
import { minimizeModalMedia } from '../../../actions/mediaActions';
|
||||
import { pauseFullscreenVideo } from '../../../actions/playActions';
|
||||
@@ -49,13 +61,16 @@ import ProductTag from '../components/ProductTag';
|
||||
import StarRating from '../components/StarRating';
|
||||
// ProductContentSection imports
|
||||
import TScrollerDetail from '../components/TScroller/TScrollerDetail';
|
||||
import ProductDescription from '../ProductContentSection/ProductDescription/ProductDescription';
|
||||
import ProductDetail from '../ProductContentSection/ProductDetail/ProductDetail.new';
|
||||
import ProductVideo from '../ProductContentSection/ProductVideo/ProductVideo';
|
||||
import ProductDescription
|
||||
from '../ProductContentSection/ProductDescription/ProductDescription';
|
||||
import ProductDetail
|
||||
from '../ProductContentSection/ProductDetail/ProductDetail.new';
|
||||
import { ProductVideoV2 } from '../ProductContentSection/ProductVideo';
|
||||
import ProductVideo from '../ProductContentSection/ProductVideo/ProductVideo';
|
||||
import UserReviews from '../ProductContentSection/UserReviews/UserReviews';
|
||||
// import ViewAllReviewsButton from '../ProductContentSection/UserReviews/ViewAllReviewsButton';
|
||||
import YouMayAlsoLike from '../ProductContentSection/YouMayAlsoLike/YouMayAlsoLike';
|
||||
import YouMayAlsoLike
|
||||
from '../ProductContentSection/YouMayAlsoLike/YouMayAlsoLike';
|
||||
import QRCode from '../ProductInfoSection/QRCode/QRCode';
|
||||
import ProductOverview from '../ProductOverview/ProductOverview';
|
||||
// CSS imports
|
||||
@@ -99,7 +114,10 @@ const HorizontalContainer = SpotlightContainerDecorator(
|
||||
const getProductData = curry((productType, themeProductInfo, productInfo) =>
|
||||
pipe(
|
||||
when(
|
||||
() => isVal(productType) && productType === 'theme' && isVal(themeProductInfo),
|
||||
() =>
|
||||
isVal(productType) &&
|
||||
productType === 'theme' &&
|
||||
isVal(themeProductInfo),
|
||||
() => themeProductInfo
|
||||
),
|
||||
defaultTo(productInfo),
|
||||
@@ -141,14 +159,16 @@ export default function ProductAllSection({
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// Redux 상태
|
||||
const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion);
|
||||
const webOSVersion = useSelector(
|
||||
(state) => state.common.appStatus.webOSVersion
|
||||
);
|
||||
const groupInfos = useSelector((state) => state.product.groupInfo);
|
||||
|
||||
// YouMayLike 데이터는 API 응답 시간이 걸리므로 직접 구독
|
||||
const youmaylikeData = useSelector((state) => state.main.youmaylikeData);
|
||||
|
||||
// ProductVideo 버전 관리 (1: 기존 modal 방식, 2: 내장 방식 , 3: 비디오 생략)
|
||||
const [productVideoVersion, setProductVideoVersion] = useState(2);
|
||||
const [productVideoVersion, setProductVideoVersion] = useState(3);
|
||||
|
||||
// const [currentHeight, setCurrentHeight] = useState(0);
|
||||
//하단부분까지 갔을때 체크용
|
||||
@@ -229,7 +249,10 @@ export default function ProductAllSection({
|
||||
|
||||
// 여행/테마 상품 - DetailPanel.backup.jsx와 동일한 로직
|
||||
const isTravelProductVisible = useMemo(() => {
|
||||
return panelInfo?.curationId && (panelInfo?.type === 'theme' || panelInfo?.type === 'hotel');
|
||||
return (
|
||||
panelInfo?.curationId &&
|
||||
(panelInfo?.type === 'theme' || panelInfo?.type === 'hotel')
|
||||
);
|
||||
}, [panelInfo]);
|
||||
|
||||
// useReviews Hook 사용 - 모든 리뷰 관련 로직을 담당
|
||||
@@ -284,7 +307,10 @@ export default function ProductAllSection({
|
||||
// TODO: 장바구니 추가 로직 구현
|
||||
}, []);
|
||||
|
||||
const { revwGrd, orderPhnNo } = useMemo(() => extractProductMeta(productInfo), [productInfo]);
|
||||
const { revwGrd, orderPhnNo } = useMemo(
|
||||
() => extractProductMeta(productInfo),
|
||||
[productInfo]
|
||||
);
|
||||
|
||||
const [favoriteOverride, setFavoriteOverride] = useState(null);
|
||||
const favoriteFlag = useMemo(
|
||||
@@ -293,7 +319,8 @@ export default function ProductAllSection({
|
||||
);
|
||||
|
||||
const [mobileSendPopupOpen, setMobileSendPopupOpen] = useState(false);
|
||||
const [isShowUserReviewsFocused, setIsShowUserReviewsFocused] = useState(false);
|
||||
const [isShowUserReviewsFocused, setIsShowUserReviewsFocused] =
|
||||
useState(false);
|
||||
|
||||
const reviewTotalCount = stats.totalReviews;
|
||||
const { getScrollTo, scrollTop } = useScrollTo();
|
||||
@@ -393,7 +420,11 @@ export default function ProductAllSection({
|
||||
}
|
||||
|
||||
// 이미지들 추가
|
||||
if (productData && productData.imgUrls600 && productData.imgUrls600.length > 0) {
|
||||
if (
|
||||
productData &&
|
||||
productData.imgUrls600 &&
|
||||
productData.imgUrls600.length > 0
|
||||
) {
|
||||
productData.imgUrls600.forEach((image, imgIndex) => {
|
||||
items.push({
|
||||
type: 'image',
|
||||
@@ -413,7 +444,9 @@ export default function ProductAllSection({
|
||||
// renderItems에 Video가 존재하는지 확인하는 boolean 상태
|
||||
const hasVideo = useMemo(() => {
|
||||
return (
|
||||
renderItems && renderItems.length > 0 && renderItems.some((item) => item.type === 'video')
|
||||
renderItems &&
|
||||
renderItems.length > 0 &&
|
||||
renderItems.some((item) => item.type === 'video')
|
||||
);
|
||||
}, [renderItems]);
|
||||
|
||||
@@ -456,7 +489,10 @@ export default function ProductAllSection({
|
||||
pipe(
|
||||
() => setOpenThemeItemOverlay(true),
|
||||
tap(() => {
|
||||
const timerId = setTimeout(() => Spotlight.focus('theme-close-button'), 0);
|
||||
const timerId = setTimeout(
|
||||
() => Spotlight.focus('theme-close-button'),
|
||||
0
|
||||
);
|
||||
timersRef.current.push(timerId);
|
||||
})
|
||||
),
|
||||
@@ -484,7 +520,8 @@ export default function ProductAllSection({
|
||||
});
|
||||
|
||||
// documentHeight를 활용하여 반복 계산 제거
|
||||
const totalHeight = documentHeight + (youMayAlsoLikelRef.current?.scrollHeight || 0);
|
||||
const totalHeight =
|
||||
documentHeight + (youMayAlsoLikelRef.current?.scrollHeight || 0);
|
||||
const isAtBottom = scrollPositionRef.current + 1100 >= totalHeight;
|
||||
|
||||
if (isAtBottom) {
|
||||
@@ -565,7 +602,6 @@ export default function ProductAllSection({
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
|
||||
// 컴포넌트 unmount 시 모든 timer cleanup
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@@ -623,7 +659,11 @@ export default function ProductAllSection({
|
||||
>
|
||||
<div className={css.qrWrapper}>
|
||||
{isShowQRCode ? (
|
||||
<QRCode productInfo={productData} productType={productType} kind={'detail'} />
|
||||
<QRCode
|
||||
productInfo={productData}
|
||||
productType={productType}
|
||||
kind={'detail'}
|
||||
/>
|
||||
) : (
|
||||
<div className={css.qrRollingWrap}>
|
||||
<div className={css.innerText}>
|
||||
@@ -672,7 +712,9 @@ export default function ProductAllSection({
|
||||
onClick={handleShopByMobileOpen}
|
||||
onSpotlightUp={handleSpotlightUpToBackButton}
|
||||
>
|
||||
<div className={css.shopByMobileText}>{$L('SHOP BY MOBILE')}</div>
|
||||
<div className={css.shopByMobileText}>
|
||||
{$L('SHOP BY MOBILE')}
|
||||
</div>
|
||||
</TButton>
|
||||
{panelInfo && (
|
||||
<div className={css.favoriteBtnWrapper}>
|
||||
@@ -691,7 +733,9 @@ export default function ProductAllSection({
|
||||
<div className={css.callToOrderSection}>
|
||||
{orderPhnNo && (
|
||||
<>
|
||||
<div className={css.callToOrderText}>{$L('Call to Order')}</div>
|
||||
<div className={css.callToOrderText}>
|
||||
{$L('Call to Order')}
|
||||
</div>
|
||||
<div className={css.phoneSection}>
|
||||
<div className={css.phoneIconContainer}>
|
||||
<div className={css.phoneIcon} />
|
||||
@@ -750,15 +794,17 @@ export default function ProductAllSection({
|
||||
})()} */}
|
||||
</Container>
|
||||
|
||||
{panelInfo && panelInfo.type === 'theme' && !openThemeItemOverlay && (
|
||||
<TButton
|
||||
className={css.themeButton}
|
||||
onClick={handleThemeItemButtonClick}
|
||||
spotlightId="theme-open-button"
|
||||
>
|
||||
{$L('THEME ITEM')}
|
||||
</TButton>
|
||||
)}
|
||||
{panelInfo &&
|
||||
panelInfo.type === 'theme' &&
|
||||
!openThemeItemOverlay && (
|
||||
<TButton
|
||||
className={css.themeButton}
|
||||
onClick={handleThemeItemButtonClick}
|
||||
spotlightId="theme-open-button"
|
||||
>
|
||||
{$L('THEME ITEM')}
|
||||
</TButton>
|
||||
)}
|
||||
|
||||
<DetailMobileSendPopUp
|
||||
ismobileSendPopupOpen={mobileSendPopupOpen}
|
||||
@@ -790,7 +836,10 @@ export default function ProductAllSection({
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
<div className={css.productDetail}>
|
||||
<div id="scroll-marker-product-details" className={css.scrollMarker}></div>
|
||||
<div
|
||||
id="scroll-marker-product-details"
|
||||
className={css.scrollMarker}
|
||||
></div>
|
||||
{/* <LayoutSample onClick={handleLayoutSampleClick} /> */}
|
||||
<div
|
||||
id="product-details-section"
|
||||
@@ -799,31 +848,36 @@ export default function ProductAllSection({
|
||||
onBlur={handleButtonBlur}
|
||||
>
|
||||
{/* 비디오가 있으면 먼저 렌더링 (productVideoVersion이 3이 아닐 때만) */}
|
||||
{hasVideo && renderItems[0].type === 'video' && productVideoVersion !== 3 && (
|
||||
<>
|
||||
{productVideoVersion === 1 ? (
|
||||
<ProductVideo
|
||||
key="product-video-0"
|
||||
productInfo={productData}
|
||||
videoUrl={renderItems[0].url}
|
||||
thumbnailUrl={renderItems[0].thumbnail}
|
||||
autoPlay={true}
|
||||
continuousPlay={true}
|
||||
onScrollToImages={handleScrollToImagesV1}
|
||||
/>
|
||||
) : (
|
||||
<ProductVideoV2
|
||||
key="product-video-v2-0"
|
||||
productInfo={productData}
|
||||
videoUrl={renderItems[0].url}
|
||||
thumbnailUrl={renderItems[0].thumbnail}
|
||||
autoPlay={true}
|
||||
onScrollToImages={handleScrollToImagesV2}
|
||||
/>
|
||||
)}
|
||||
<div id="scroll-marker-after-video" className={css.scrollMarker}></div>
|
||||
</>
|
||||
)}
|
||||
{hasVideo &&
|
||||
renderItems[0].type === 'video' &&
|
||||
productVideoVersion !== 3 && (
|
||||
<>
|
||||
{productVideoVersion === 1 ? (
|
||||
<ProductVideo
|
||||
key="product-video-0"
|
||||
productInfo={productData}
|
||||
videoUrl={renderItems[0].url}
|
||||
thumbnailUrl={renderItems[0].thumbnail}
|
||||
autoPlay={true}
|
||||
continuousPlay={true}
|
||||
onScrollToImages={handleScrollToImagesV1}
|
||||
/>
|
||||
) : (
|
||||
<ProductVideoV2
|
||||
key="product-video-v2-0"
|
||||
productInfo={productData}
|
||||
videoUrl={renderItems[0].url}
|
||||
thumbnailUrl={renderItems[0].thumbnail}
|
||||
autoPlay={true}
|
||||
onScrollToImages={handleScrollToImagesV2}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
id="scroll-marker-after-video"
|
||||
className={css.scrollMarker}
|
||||
></div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 이미지들만 렌더링 (비디오 제외) */}
|
||||
{renderItems.length > 0
|
||||
@@ -851,7 +905,10 @@ export default function ProductAllSection({
|
||||
<ProductDescription productInfo={productData} />
|
||||
</div>
|
||||
{/* 리뷰가 있을 때만 UserReviews 섹션 표시 */}
|
||||
<div id="scroll-marker-user-reviews" className={css.scrollMarker}></div>
|
||||
<div
|
||||
id="scroll-marker-user-reviews"
|
||||
className={css.scrollMarker}
|
||||
></div>
|
||||
{hasReviews && (
|
||||
<div
|
||||
id="user-reviews-section"
|
||||
@@ -879,7 +936,10 @@ export default function ProductAllSection({
|
||||
)}
|
||||
</div>
|
||||
<div ref={youMayAlsoLikelRef}>
|
||||
<div id="scroll-marker-you-may-also-like" className={css.scrollMarker}></div>
|
||||
<div
|
||||
id="scroll-marker-you-may-also-like"
|
||||
className={css.scrollMarker}
|
||||
></div>
|
||||
{hasYouMayAlsoLike && (
|
||||
<div id="you-may-also-like-section">
|
||||
{/* {(() => {
|
||||
|
||||
@@ -27,7 +27,12 @@ import {
|
||||
sendLogPaymentEntry,
|
||||
sendLogTotalRecommend,
|
||||
} from '../../../actions/logActions';
|
||||
import { pushPanel } from '../../../actions/panelActions';
|
||||
import { finishMediaPreview } from '../../../actions/mediaActions';
|
||||
import {
|
||||
popPanel,
|
||||
pushPanel,
|
||||
} from '../../../actions/panelActions';
|
||||
import { finishVideoPreview } from '../../../actions/playActions';
|
||||
import {
|
||||
getProductOption,
|
||||
getProductOptionId,
|
||||
@@ -261,7 +266,9 @@ const BuyOption = ({
|
||||
} else {
|
||||
const { mbrId, prdtId, prodSno } = response.data.productList[0];
|
||||
const cartTpSno = `${mbrId}_${prdtId}_${prodSno}`;
|
||||
|
||||
dispatch(popPanel(Config.panel_names.DETAIL_PANEL));
|
||||
dispatch(finishVideoPreview());
|
||||
dispatch(finishMediaPreview());
|
||||
dispatch(
|
||||
pushPanel({
|
||||
name: Config.panel_names.CHECKOUT_PANEL,
|
||||
@@ -274,6 +281,26 @@ const BuyOption = ({
|
||||
} else if (response.retCode === 1001) {
|
||||
dispatch(setShowPopup(Config.ACTIVE_POPUP.qrPopup));
|
||||
dispatch(changeAppStatus({ isLoading: false }));
|
||||
} else if (response.retCode === 1016) {
|
||||
//현재 1016에 대한 소스 부분 체크가 원활하지 않아 우선 넘어가도록 기존 상품 연결. 추후 에러 코드에 대한 처리 필요
|
||||
dispatch(
|
||||
getMyInfoCheckoutInfo(
|
||||
{
|
||||
mbrNo: userNumber,
|
||||
dirPurcSelYn: 'Y',
|
||||
cartList: [
|
||||
{
|
||||
patnrId: '1',
|
||||
prdtId: 'T141360',
|
||||
prodOptCdCval: 'T141360000000',
|
||||
prodQty: '1',
|
||||
prodOptTpCdCval: 'ORD04001',
|
||||
},
|
||||
],
|
||||
},
|
||||
checkOutValidate
|
||||
)
|
||||
);
|
||||
} else {
|
||||
dispatch(
|
||||
showError(
|
||||
@@ -315,6 +342,21 @@ const BuyOption = ({
|
||||
// return dispatch(setShowPopup(Config.ACTIVE_POPUP.loginPopup));
|
||||
// }
|
||||
|
||||
//옵션 선택 안하면 구매 안돼도록.
|
||||
if (productOptionInfos.length > 1) {
|
||||
if (selectedBtnOptIdx === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (
|
||||
productOptionInfos[selectedBtnOptIdx]?.prdtOptDtl &&
|
||||
productOptionInfos[selectedBtnOptIdx]?.prdtOptDtl.length > 1
|
||||
) {
|
||||
if (selectedOptionItemIndex === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (userNumber && selectedPatnrId && selectedPrdtId && quantity) {
|
||||
const { prodOptCval, priceInfo } = selectedOptions || {};
|
||||
const { patncNm, brndNm, catNm, prdtNm, prdtId } = productInfo;
|
||||
|
||||
Reference in New Issue
Block a user