일반상품 옵션이 있을경우 로직 구현
This commit is contained in:
@@ -1,25 +1,17 @@
|
||||
import React, {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { memo, useCallback, useEffect, useState } from "react";
|
||||
|
||||
import classNames from 'classnames';
|
||||
import classNames from "classnames";
|
||||
|
||||
import Spottable from '@enact/spotlight/Spottable';
|
||||
import Spottable from "@enact/spotlight/Spottable";
|
||||
|
||||
import defaultimgHorizontal
|
||||
from '../../../assets/images/img-thumb-empty-hor@3x.png';
|
||||
import defaultImageItem
|
||||
from '../../../assets/images/img-thumb-empty-product@3x.png';
|
||||
import defaultimgVertical
|
||||
from '../../../assets/images/img-thumb-empty-ver@3x.png';
|
||||
import IcLiveShow from '../../../assets/images/tag/tag-liveshow.png';
|
||||
import usePriceInfo from '../../hooks/usePriceInfo';
|
||||
import { $L } from '../../utils/helperMethods';
|
||||
import CustomImage from '../CustomImage/CustomImage';
|
||||
import css from './TItemCard.module.less';
|
||||
import defaultimgHorizontal from "../../../assets/images/img-thumb-empty-hor@3x.png";
|
||||
import defaultImageItem from "../../../assets/images/img-thumb-empty-product@3x.png";
|
||||
import defaultimgVertical from "../../../assets/images/img-thumb-empty-ver@3x.png";
|
||||
import IcLiveShow from "../../../assets/images/tag/tag-liveshow.png";
|
||||
import usePriceInfo from "../../hooks/usePriceInfo";
|
||||
import { $L } from "../../utils/helperMethods";
|
||||
import CustomImage from "../CustomImage/CustomImage";
|
||||
import css from "./TItemCard.module.less";
|
||||
|
||||
const SpottableComponent = Spottable("div");
|
||||
|
||||
@@ -67,6 +59,7 @@ export default memo(function TItemCard({
|
||||
rank,
|
||||
soldoutFlag,
|
||||
spotlightId,
|
||||
isSpotlightDisable,
|
||||
nonPosition = false,
|
||||
type = TYPES.vertical,
|
||||
...rest
|
||||
@@ -132,6 +125,7 @@ export default memo(function TItemCard({
|
||||
onClick={_onClick}
|
||||
onFocus={_onFocus}
|
||||
spotlightId={spotlightId ?? "spotlightId-" + removeDotAndColon(productId)}
|
||||
spotlightDisable={isSpotlightDisable}
|
||||
{...rest}
|
||||
>
|
||||
<div className={css.imageWrap}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import classNames from "classnames";
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function TPopUp({
|
||||
text,
|
||||
options,
|
||||
optionClick,
|
||||
selectedOptIdx,
|
||||
selectedIndex,
|
||||
...rest
|
||||
}) {
|
||||
useEffect(() => {
|
||||
@@ -88,6 +88,7 @@ export default function TPopUp({
|
||||
const _optionClick = useCallback(
|
||||
(e, idx) => {
|
||||
if (optionClick) {
|
||||
console.log("#optionClick", optionClick);
|
||||
optionClick(e, idx);
|
||||
}
|
||||
},
|
||||
@@ -113,7 +114,7 @@ export default function TPopUp({
|
||||
);
|
||||
const selectedOptClick = useCallback(
|
||||
(index) => (e) => {
|
||||
_optionClick(e, index);
|
||||
_optionClick(index);
|
||||
},
|
||||
[_optionClick]
|
||||
);
|
||||
@@ -165,7 +166,8 @@ export default function TPopUp({
|
||||
)}
|
||||
>
|
||||
{options.map((option, index) => {
|
||||
const { prodOptCval, optImgUrl, optPrc, optStkQty } = option;
|
||||
const { prodOptCval, optImgUrl, optPrc, optStkQty, optNm } =
|
||||
option;
|
||||
const optStock = Number(optStkQty);
|
||||
|
||||
return (
|
||||
@@ -173,20 +175,20 @@ export default function TPopUp({
|
||||
{...rest}
|
||||
className={classNames(
|
||||
css.option,
|
||||
index === selectedOptIdx && css.selectedOption,
|
||||
index === selectedIndex && css.selectedOption,
|
||||
|
||||
index == selectedIndex && css.focused,
|
||||
optStock <= 0 && css.optionSoldOut
|
||||
)}
|
||||
spotlightId={
|
||||
index === selectedOptIdx ? "selectedOptionBtn" : null
|
||||
}
|
||||
onClick={optStock >= 1 && selectedOptClick(index)}
|
||||
spotlightId={`selectedOptionBtn-${index}`}
|
||||
onClick={selectedOptClick(index)}
|
||||
key={`option: ${index}`}
|
||||
spotlightDisabled={optStock && optStock <= 0}
|
||||
// spotlightDisabled={optStock && optStock <= 0}
|
||||
>
|
||||
{optImgUrl && (
|
||||
<img src={optImgUrl} alt="" className={css.img} />
|
||||
)}
|
||||
<span>{prodOptCval}</span>
|
||||
<span>{optNm ? optNm : prodOptCval}</span>
|
||||
{optPrc && optStock !== 0 && `($${optPrc})`}
|
||||
</SpottableComponent>
|
||||
);
|
||||
|
||||
@@ -9,11 +9,12 @@ import {
|
||||
getThemeHotelDetailInfo,
|
||||
} from "../../actions/homeActions";
|
||||
import { getMainCategoryDetail } from "../../actions/mainActions";
|
||||
import { popPanel } from "../../actions/panelActions";
|
||||
import { popPanel, resetPanels } from "../../actions/panelActions";
|
||||
import { getProductGroup } from "../../actions/productActions";
|
||||
import TBody from "../../components/TBody/TBody";
|
||||
import THeader from "../../components/THeader/THeader";
|
||||
import TPanel from "../../components/TPanel/TPanel";
|
||||
import { panel_names } from "../../utils/Config";
|
||||
import css from "./DetailPanel.module.less";
|
||||
import GroupProduct from "./GroupProduct/GroupProduct";
|
||||
import SingleProduct from "./SingleProduct/SingleProduct";
|
||||
@@ -47,7 +48,9 @@ export default function ItemDetail() {
|
||||
if (panels[i].name === "detailpanel") {
|
||||
setSelectedPatnrId(panels[i].panelInfo.patnrId);
|
||||
setSelectedPrtdId(panels[i].panelInfo.prdtId);
|
||||
if (panels[0].name == "hotpickpanel") {
|
||||
setSelectedCurationId(panels[i].panelInfo.curationId);
|
||||
setThemeType(panels[i].panelInfo.type);
|
||||
if (panels[0].name === "hotpickpanel") {
|
||||
setSelectedPatnrId(panels[i].panelInfo.patnrId);
|
||||
setSelectedCurationId(panels[i].panelInfo.curationId);
|
||||
setThemeType(panels[i].panelInfo.type);
|
||||
@@ -89,10 +92,6 @@ export default function ItemDetail() {
|
||||
}, [dispatch, selectedPatnrId, selectedPrdtId, panels]);
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
setSelectedPrtdId("");
|
||||
setSelectedPatnrId("");
|
||||
setSelectedCurationId("");
|
||||
setCategoryId("");
|
||||
dispatch(popPanel());
|
||||
}, [dispatch]);
|
||||
|
||||
|
||||
@@ -52,15 +52,19 @@ export default function SingleOption({
|
||||
(state) => state.common.appStatus.loginUserData
|
||||
);
|
||||
const { loginUserData } = useSelector((state) => state.common.appStatus);
|
||||
const [hasProductOptionArray, setHasProductOptionArray] = useState(true);
|
||||
const [isOption, setIsOption] = useState(false);
|
||||
const [promotions, setPromotions] = useState([]);
|
||||
const [selectedBtnOptIdx, setSelectedBtnOptIdx] = useState(0);
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
const [selectedCoupon, setSelectedCoupon] = useState();
|
||||
const [selectedOptionIdx, setSelectedOptionsIdx] = useState([]);
|
||||
const [selectedOptions, setsSelectedOptions] = useState([]);
|
||||
const [selectedOptionItemIndex, setSelectedOptionItemIndex] = useState(0);
|
||||
const [selectedOptions, setSelectedOptions] = useState([]);
|
||||
const [couponTypes, setCouponTypes] = useState(null);
|
||||
const [couponCodes, setCouponCodes] = useState("");
|
||||
const [selectedOptionInfo, setSelectedOptionInfo] = useState();
|
||||
const [downloadCouponArr, setDownloadCouponArr] = useState([]);
|
||||
const [focusIndex, setFocusIndex] = useState(0);
|
||||
const { priceInfo, shippingCharge } = productInfo || productData;
|
||||
const { originalPrice, discountedPrice, discountRate } =
|
||||
usePriceInfo(priceInfo) || {};
|
||||
@@ -85,50 +89,43 @@ export default function SingleOption({
|
||||
prdtId: selectedPrdtId,
|
||||
})
|
||||
);
|
||||
|
||||
dispatch(
|
||||
getProductCouponSearch({
|
||||
patnrId: selectedPatnrId,
|
||||
prdtId: selectedPrdtId,
|
||||
mbrNo: userInfo,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
dispatch(
|
||||
getProductCouponSearch({
|
||||
patnrId: selectedPatnrId,
|
||||
prdtId: selectedPrdtId,
|
||||
mbrNo: userInfo,
|
||||
})
|
||||
);
|
||||
}, [dispatch, selectedPatnrId]);
|
||||
|
||||
console.log("#productData", productData);
|
||||
console.log("#productOptionInfos", productOptionInfos);
|
||||
|
||||
const handleOptionsClick = useCallback(
|
||||
(e, optionValIdx) => {
|
||||
setsSelectedOptions((prevOptions) => {
|
||||
const updatedOptions = [...prevOptions];
|
||||
updatedOptions[selectedBtnOptIdx] =
|
||||
productOptionInfos[selectedBtnOptIdx].prdtOptDtl[optionValIdx];
|
||||
return updatedOptions;
|
||||
});
|
||||
setSelectedOptionsIdx((prevOptions) => {
|
||||
const updatedOptions = [...prevOptions];
|
||||
updatedOptions[selectedBtnOptIdx] = optionValIdx;
|
||||
return updatedOptions;
|
||||
});
|
||||
|
||||
Spotlight.focus(`optionBtn-${selectedBtnOptIdx}`);
|
||||
const handleOptionClick = useCallback(
|
||||
(optionValIdx) => {
|
||||
console.log("#optionValIdx", optionValIdx);
|
||||
setSelectedBtnOptIdx(optionValIdx);
|
||||
onClose();
|
||||
},
|
||||
[selectedBtnOptIdx, productOptionInfos]
|
||||
[selectedBtnOptIdx]
|
||||
);
|
||||
|
||||
const handleOptionItemClick = useCallback(
|
||||
(index) => {
|
||||
setSelectedOptionItemIndex(index);
|
||||
onClose();
|
||||
},
|
||||
[selectedOptionItemIndex]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedOptionIdx || selectedOptionIdx.length < 0) {
|
||||
setsSelectedOptions((prevOptions) => {
|
||||
const updatedOptions = [...prevOptions];
|
||||
updatedOptions[selectedBtnOptIdx] =
|
||||
productOptionInfos[selectedBtnOptIdx].prdtOptDtl[0];
|
||||
return updatedOptions;
|
||||
});
|
||||
if (productOptionInfos && productOptionInfos.length > 0) {
|
||||
setSelectedOptions(
|
||||
productOptionInfos[selectedBtnOptIdx].prdtOptDtl[
|
||||
selectedOptionItemIndex
|
||||
]
|
||||
);
|
||||
}
|
||||
}, [selectedOptions]);
|
||||
}, [selectedBtnOptIdx, selectedOptionItemIndex]);
|
||||
|
||||
const handleIncrement = useCallback(() => {
|
||||
setQuantity(quantity + 1);
|
||||
@@ -139,14 +136,17 @@ export default function SingleOption({
|
||||
else setQuantity(quantity - 1);
|
||||
}, [quantity]);
|
||||
|
||||
const handleOptionBtnClick = useCallback(
|
||||
(idx) => {
|
||||
const handleOptionPopUpOpen = useCallback(
|
||||
(OptionInfo, isProductOptionInfoArray) => {
|
||||
setSelectedOptionInfo(OptionInfo);
|
||||
setHasProductOptionArray(isProductOptionInfoArray);
|
||||
dispatch(setShowPopup(Config.ACTIVE_POPUP.optionPopup));
|
||||
setSelectedBtnOptIdx(idx);
|
||||
},
|
||||
[dispatch, selectedBtnOptIdx]
|
||||
);
|
||||
|
||||
console.log("#selectedOptionItemIndex", selectedOptionItemIndex);
|
||||
// Spotlight.focus(`selectedOptionBtn-2`);
|
||||
},
|
||||
[dispatch, selectedOptionItemIndex, activePopup]
|
||||
);
|
||||
const handleLoginPopup = useCallback(() => {
|
||||
if (!loginUserData.userInfo) {
|
||||
dispatch(setShowPopup(Config.ACTIVE_POPUP.loginPopup));
|
||||
@@ -155,20 +155,12 @@ export default function SingleOption({
|
||||
pushPanel({
|
||||
name: Config.panel_names.CHECKOUT_PANEL,
|
||||
panelInfo: {
|
||||
cartList: [
|
||||
{
|
||||
patnrId: selectedPatnrId,
|
||||
prdtId: selectedPrdtId,
|
||||
prodOptCdCval:
|
||||
selectedOptions[selectedBtnOptIdx]?.prodOptCdCval,
|
||||
prodQty: quantity,
|
||||
},
|
||||
],
|
||||
// quantity: quantity,
|
||||
// patnrId: selectedPatnrId,
|
||||
// prdtId: selectedPrdtId,
|
||||
// price: discountedPrice ? discountedPrice : originalPrice,
|
||||
// selectedOption: selectedOptions,
|
||||
cartList: {
|
||||
patnrId: selectedPatnrId,
|
||||
prdtId: selectedPrdtId,
|
||||
prodOptCdCval: selectedOptions.prodOptCdCval,
|
||||
prodQty: quantity,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -198,25 +190,58 @@ export default function SingleOption({
|
||||
}, [selectedCoupon, userInfo, couponCodes]);
|
||||
|
||||
const onClose = useCallback(() => {
|
||||
console.log(
|
||||
"########################CLOSE!!!!!!!!!!",
|
||||
hasProductOptionArray
|
||||
);
|
||||
if (hasProductOptionArray) {
|
||||
Spotlight.focus("selectedOptionBox-1");
|
||||
} else {
|
||||
Spotlight.focus("selectedOptionBox-0");
|
||||
}
|
||||
|
||||
dispatch(setHidePopup());
|
||||
}, [dispatch]);
|
||||
}, [dispatch, productOptionInfos]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedCoupon) {
|
||||
getCouponCode();
|
||||
}
|
||||
}, [selectedCoupon]);
|
||||
|
||||
//디테일패널 최초 진입시 옵션이 있으면 포커스 없으면 백버튼 포커스
|
||||
useEffect(() => {
|
||||
if (!isSpotlight) {
|
||||
return;
|
||||
}
|
||||
if (productOptionInfos && productOptionInfos.length > 0) {
|
||||
Spotlight.focus("optionBtn-0");
|
||||
Spotlight.focus("selectedOptionBox-0");
|
||||
if (productOptionInfos.length === 1) {
|
||||
Spotlight.focus("selectedOptionBox-1");
|
||||
}
|
||||
} else if (productData && productData.soldoutFlag === "Y") {
|
||||
Spotlight.focus("spotlightId_backBtn");
|
||||
}
|
||||
}, [productOptionInfos, productData]);
|
||||
|
||||
//옵션이 있을 경우 selectedOption에 첫번째 옵션을 강제로 담음 ( 들어오자마자 BUYNOW 클릭시 체크아웃으로 상품 넘어감 )
|
||||
useEffect(() => {
|
||||
if (productOptionInfos && productOptionInfos.length > 0) {
|
||||
setSelectedOptions(
|
||||
productOptionInfos[selectedBtnOptIdx].prdtOptDtl[
|
||||
selectedOptionItemIndex
|
||||
]
|
||||
);
|
||||
}
|
||||
}, [productOptionInfos]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSpotlight) {
|
||||
return;
|
||||
}
|
||||
Spotlight.focus(`selectedOptionBox-${selectedBtnOptIdx}`);
|
||||
}, [selectedBtnOptIdx]);
|
||||
|
||||
const getCouponCode = () => {
|
||||
const snoArray = [];
|
||||
|
||||
@@ -227,19 +252,19 @@ export default function SingleOption({
|
||||
setCouponCodes(snoArray.join(", "));
|
||||
};
|
||||
|
||||
// Option Name을 렌더링하는 함수
|
||||
const renderOptionName = (optionInfo) => {
|
||||
return optionInfo?.optNm || null;
|
||||
};
|
||||
|
||||
// Option Value를 렌더링하는 함수
|
||||
const renderOptionValue = (optionInfo) => {
|
||||
if (
|
||||
optionInfo &&
|
||||
optionInfo.prdtOptDtl &&
|
||||
optionInfo.prdtOptDtl.length > 0
|
||||
) {
|
||||
return optionInfo.prdtOptDtl[0]?.prodOptCval || null;
|
||||
return (
|
||||
optionInfo.prdtOptDtl[selectedOptionItemIndex]?.prodOptCval || null
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -323,24 +348,46 @@ export default function SingleOption({
|
||||
<div className={css.detailContainer}>
|
||||
<Container>
|
||||
<TScroller verticalScrollbar="auto" className={css.detailScroll}>
|
||||
<div className={css.optionLayer}>
|
||||
{/* OPTION */}
|
||||
<span>{$L("OPTION")}</span>
|
||||
<TButton
|
||||
className={css.optionBtn}
|
||||
onClick={() => {
|
||||
handleOptionBtnClick();
|
||||
}}
|
||||
>
|
||||
<span className={css.optionValue}>
|
||||
{productOptionInfos &&
|
||||
productOptionInfos.length > 0 &&
|
||||
(productOptionInfos.length > 1
|
||||
? renderOptionName(productOptionInfos[0])
|
||||
: renderOptionValue(productOptionInfos[0]))}
|
||||
</span>
|
||||
</TButton>
|
||||
</div>
|
||||
{productOptionInfos && productOptionInfos.length > 0 && (
|
||||
<>
|
||||
{productOptionInfos.length !== 1 && (
|
||||
<div className={css.optionLayer}>
|
||||
{/* OPTION 1 */}
|
||||
<span>{$L("OPTION")}</span>
|
||||
<TButton
|
||||
className={css.optionBtn}
|
||||
onClick={() =>
|
||||
handleOptionPopUpOpen(productOptionInfos, true)
|
||||
}
|
||||
spotlightId={"selectedOptionBox-0"}
|
||||
>
|
||||
<span className={css.optionValue}>
|
||||
{renderOptionName(productOptionInfos[selectedBtnOptIdx])}
|
||||
</span>
|
||||
</TButton>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={css.optionLayer}>
|
||||
{/* OPTION 2 */}
|
||||
<span>{$L("OPTION")}</span>
|
||||
<TButton
|
||||
className={css.optionBtn}
|
||||
onClick={() =>
|
||||
handleOptionPopUpOpen(
|
||||
productOptionInfos[selectedBtnOptIdx]?.prdtOptDtl,
|
||||
false
|
||||
)
|
||||
}
|
||||
spotlightId={"selectedOptionBox-1"}
|
||||
>
|
||||
<span className={css.optionValue}>
|
||||
{renderOptionValue(productOptionInfos[selectedBtnOptIdx])}
|
||||
</span>
|
||||
</TButton>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* QUANTITY */}
|
||||
<Container className={css.quantityLayer}>
|
||||
@@ -454,23 +501,19 @@ export default function SingleOption({
|
||||
{activePopup === Config.ACTIVE_POPUP.optionPopup && (
|
||||
<TPopUp
|
||||
kind="optionPopup"
|
||||
options={
|
||||
productOptionInfos &&
|
||||
productOptionInfos[selectedBtnOptIdx].prdtOptDtl
|
||||
}
|
||||
options={selectedOptionInfo}
|
||||
onClose={onClose}
|
||||
open={popupVisible}
|
||||
optionClick={handleOptionsClick}
|
||||
optionClick={
|
||||
hasProductOptionArray ? handleOptionClick : handleOptionItemClick
|
||||
}
|
||||
hasButton
|
||||
hasText
|
||||
title={$L(productOptionInfos[selectedBtnOptIdx].optNm.toUpperCase())}
|
||||
title={$L("OPTION")}
|
||||
button1Text={$L("CLOSE")}
|
||||
className={css.productOptionPopup}
|
||||
selectedOptIdx={
|
||||
selectedOptions[selectedBtnOptIdx] === null ||
|
||||
selectedOptions[selectedBtnOptIdx] === undefined
|
||||
? 0
|
||||
: selectedOptions[selectedBtnOptIdx]
|
||||
selectedIndex={
|
||||
hasProductOptionArray ? selectedBtnOptIdx : selectedOptionItemIndex
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -46,6 +46,7 @@ export default function SingleProduct({
|
||||
<SingleOption
|
||||
selectedPatnrId={selectedPatnrId}
|
||||
selectedPrdtId={selectedPrdtId}
|
||||
isSpotlight
|
||||
/>
|
||||
</ProductOption>
|
||||
</div>
|
||||
|
||||
@@ -96,6 +96,7 @@ export default function YouMayLike({ isUnable, lgCatCd }) {
|
||||
offerInfo={offerInfo}
|
||||
productName={prdtNm}
|
||||
onClick={handleItemClick}
|
||||
isSpotlightDisable
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -172,8 +172,6 @@ export default function ThemeIndicator({
|
||||
);
|
||||
}, [dispatch, productInfo, selectedIndex]);
|
||||
|
||||
console.log("#productInfo", productInfo[selectedIndex]);
|
||||
console.log("#selectedIndex", selectedIndex);
|
||||
const renderThumbnail = useCallback(() => {
|
||||
const hasMediaUrl = getProductMediaUrlStatus();
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user