[checkoutPanel] confirmPanel UI 작업 및 checkoutPanel 예외 처리

This commit is contained in:
hyunwoo93.cha
2024-06-10 23:06:30 +09:00
parent af929c95bf
commit 7866666b59
7 changed files with 434 additions and 29 deletions

View File

@@ -8,23 +8,26 @@ import Spotlight from "@enact/spotlight";
import {
getCheckoutTotalAmtDummy,
getMyInfoCheckoutInfo,
getTaxInfos,
resetCheckoutData,
} from "../../actions/checkoutActions";
import { changeAppStatus } from "../../actions/commonActions";
import {
changeAppStatus,
setHidePopup,
setShowPopup,
} from "../../actions/commonActions";
import { getShoptimeTerms } from "../../actions/empActions";
import { popPanel } from "../../actions/panelActions";
import TBody from "../../components/TBody/TBody";
import TButtonScroller from "../../components/TButtonScroller/TButtonScroller";
import TButtonTab from "../../components/TButtonTab/TButtonTab";
import TFullPopup from "../../components/TFullPopup/TFullPopup";
import THeader from "../../components/THeader/THeader";
import TPanel from "../../components/TPanel/TPanel";
import TScroller from "../../components/TScroller/TScroller";
import TPopUp from "../../components/TPopUp/TPopUp";
import useScrollTo from "../../hooks/useScrollTo";
import { $L } from "../../utils/helperMethods";
import * as Config from "../../utils/Config";
import { $L, scaleH, scaleW } from "../../utils/helperMethods";
import css from "./CheckOutPanel.module.less";
import CheckoutQRCode from "./components/CheckoutQRCode";
import CheckOutTerms from "./components/CheckOutTerms";
import PinCode from "./components/PinCode";
import PinCodeInput from "./components/PinCodeInput";
import FixedSideBar from "./container/FixedSideBar";
import InformationContainer from "./container/InformationContainer";
@@ -49,11 +52,19 @@ export default function CheckOutPanel() {
const selectedCoupons = useSelector(
(state) => state.checkout.selectedCoupons
);
const empTermsData = useSelector((state) => state.emp.empTermsData.terms);
const { popupVisible, activePopup } = useSelector(
(state) => state.common.popup
);
const [orderSideBarOpen, setOrderSideBarOpen] = useState(false);
const [offerSideBarOpen, setOfferSideBarOpen] = useState(false);
const [placeOrderPopup, setPlaceOrderPopup] = useState(false);
const [loading, setLoading] = useState(true);
const [currentTerms, setCurrentTerms] = useState(null);
const [tabList, setTabList] = useState([]);
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
const [resetScroll, setResetScroll] = useState(false);
const isMounted = useRef(true);
@@ -149,6 +160,18 @@ export default function CheckOutPanel() {
}
}, [dispatch, infoForCheckoutData, productData, userNumber, selectedCoupons]);
useEffect(() => {
const newTabList = [];
if (empTermsData) {
empTermsData.forEach((term) => {
newTabList.push(term.termsTypeName);
});
setTabList(newTabList);
}
}, [empTermsData]);
useEffect(() => {
return () => {
dispatch(resetCheckoutData());
@@ -180,6 +203,53 @@ export default function CheckOutPanel() {
setPlaceOrderPopup(false);
}, []);
const onCloseTermsPopup = useCallback(() => {
dispatch(setHidePopup());
}, [dispatch]);
const handleTermsClick = useCallback(
(termsID) => {
if (empTermsData) {
const selectedTerms = empTermsData.find(
(term) => term.termsID === termsID
);
setCurrentTerms(selectedTerms);
dispatch(setShowPopup(Config.ACTIVE_POPUP.termsPopup));
const selectedIndex = empTermsData.findIndex(
(term) => term.termsID === termsID
);
setSelectedTabIndex(selectedIndex);
setResetScroll(true);
}
},
[empTermsData, dispatch]
);
const handleTabClick = useCallback(({ index }) => {
setSelectedTabIndex(index);
setResetScroll(true);
}, []);
useEffect(() => {
if (empTermsData && empTermsData[selectedTabIndex]) {
setCurrentTerms(empTermsData[selectedTabIndex]);
setResetScroll(true);
}
}, [selectedTabIndex, empTermsData]);
useEffect(() => {
if (resetScroll) {
setResetScroll(false);
}
}, [resetScroll]);
useEffect(() => {
Spotlight.focus();
}, [popupVisible]);
return (
<>
<TPanel
@@ -194,14 +264,17 @@ export default function CheckOutPanel() {
onClick={onBackClick}
/>
<div className={css.Wrap}>
<SummaryContainer setPlaceOrderPopup={setPlaceOrderPopup} />
<SummaryContainer
setPlaceOrderPopup={setPlaceOrderPopup}
empTermsData={empTermsData}
handleTermsClick={handleTermsClick}
/>
<InformationContainer
toggleOrderSideBar={toggleOrderSideBar}
toggleOfferSideBar={toggleOfferSideBar}
scrollTopBody={scrollTopBody}
/>
</div>
{/* <CheckoutQRCode open={false} /> */}
</TBody>
</TPanel>
@@ -210,6 +283,42 @@ export default function CheckOutPanel() {
)}
{offerSideBarOpen && <FixedSideBar closeSideBar={toggleOfferSideBar} />}
{activePopup === Config.ACTIVE_POPUP.termsPopup && (
<TPopUp
kind="introTermsPopup"
open={popupVisible}
onClose={onCloseTermsPopup}
hasButton
button1Text={$L("OK")}
>
{currentTerms && (
<div className={css.termsConts}>
<TButtonTab
className={css.tab}
selectedIndex={selectedTabIndex}
onItemClick={handleTabClick}
contents={tabList}
role="button"
/>
<TButtonScroller
boxHeight={scaleH(300)}
width={scaleW(980)}
className={css.termsDescription}
resetScrollPosition={resetScroll}
forcedFocus={false}
>
<div
className={css.termsDesc}
dangerouslySetInnerHTML={{
__html: currentTerms && currentTerms.termContent,
}}
></div>
</TButtonScroller>
</div>
)}
</TPopUp>
)}
<TFullPopup
open={placeOrderPopup}
className={css.pinCodePopup}

View File

@@ -22,3 +22,29 @@
position: fixed;
background-color: rgba(0, 0, 0, 0.3);
}
.termsConts {
background-color: #f8f8f8;
> div:nth-child(2) {
background-color: @COLOR_WHITE;
.border-solid(1px,@COLOR_GRAY02);
width: 980px;
height: 300px;
}
.termsDesc {
padding: 30px;
min-height: 300px;
color: @COLOR_GRAY03;
font-size: 24px;
line-height: 1.27;
letter-spacing: normal;
text-align: left;
.flex( @direction:column, @justifyCenter:flex-start,@alignCenter:flex-start);
}
.tab {
width: 980px;
}
}

View File

@@ -38,6 +38,7 @@ export default function PinCodeInput({ setPlaceOrderPopup }) {
const userNumber = useSelector(
(state) => state.common.appStatus.loginUserData.userNumber
);
const addrInfo = useSelector((state) => state.checkout?.infoForCheckoutData);
const selectedCoupons = useSelector(
(state) => state.checkout?.selectedCoupons
@@ -45,6 +46,9 @@ export default function PinCodeInput({ setPlaceOrderPopup }) {
const productList = useSelector(
(state) => state.checkout?.checkoutData?.productList?.[0]
);
const auctProdYn = useSelector(
(state) => state.checkout?.checkoutData?.productList?.[0].auctProdYn
);
const [pin, setPin] = useState(["", "", "", ""]);
const [errorMsg, setErrorMsg] = useState("");
@@ -173,12 +177,14 @@ export default function PinCodeInput({ setPlaceOrderPopup }) {
if (!isMounted.current) return;
if (response.data.retCode === 0) {
dispatch(resetPanels());
setPlaceOrderPopup(false);
dispatch(
pushPanel({
name: Config.panel_names.CONFIRM_PANEL,
panelInfos: response.data.data,
panelInfo: {
orderInfo: response.data.data,
auctProdYn: auctProdYn,
},
})
);
} else {
@@ -209,6 +215,7 @@ export default function PinCodeInput({ setPlaceOrderPopup }) {
selectedCoupons,
productList,
isMounted,
auctProdYn,
dispatch,
]);

View File

@@ -54,7 +54,7 @@
display: flex;
justify-content: space-between;
padding: 31px 59px 0 61px;
margin-bottom: 147px;
margin-bottom: 120px;
> div {
font-weight: bold;
font-size: 30px;
@@ -69,19 +69,31 @@
.bottom {
padding: 0 60px;
.checkboxWrap {
.termsWrap {
.termsList {
margin-bottom: 30px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.checkbox {
}
.contents {
font-weight: normal;
font-size: 24px;
.termsTypeName {
display: inline-block;
.font(@fontFamily: @baseFont, @fontSize: 24px);
color: #009cff;
text-decoration: underline;
transform: translateY(-3px);
.elip(@clamp: 1);
width: 332px;
}
.viewAllButton {
margin-left: 25px;
min-width: unset;
max-width: unset;
width: 124px;
height: 40px;
font-size: 24px;
line-height: 40px;
}
}
}

View File

@@ -4,7 +4,10 @@ import { useDispatch, useSelector } from "react-redux";
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
import { setShowPopup } from "../../../actions/commonActions";
import TButton from "../../../components/TButton/TButton";
import * as Config from "../../../utils/Config";
import { $L } from "../../../utils/helperMethods";
import css from "./SummaryContainer.module.less";
const Container = SpotlightContainerDecorator(
@@ -12,7 +15,11 @@ const Container = SpotlightContainerDecorator(
"div"
);
export default function SummaryContainer({ setPlaceOrderPopup }) {
export default function SummaryContainer({
setPlaceOrderPopup,
empTermsData,
handleTermsClick,
}) {
const dispatch = useDispatch();
const priceTotalData = useSelector(
@@ -54,12 +61,31 @@ export default function SummaryContainer({ setPlaceOrderPopup }) {
<div className={css.price}>{priceTotalData?.ordPmtReqAmt || "-"}</div>
</div>
<div className={css.bottom}>
<ul className={css.termsWrap}>
{empTermsData &&
empTermsData.length > 0 &&
empTermsData.map((term) => {
const { termsID, termsTypeName } = term;
return (
<li key={termsID} className={css.termsList}>
<span className={css.termsTypeName}>{termsTypeName}</span>
<TButton
className={css.viewAllButton}
onClick={() => handleTermsClick(termsID)}
>
{$L("View All")}
</TButton>
</li>
);
})}
</ul>
<TButton
className={css.tButton}
onClick={handleClickOrder}
spotlightId="spotlightId_placeOrderBtn"
>
{"PLACE ORDER"}
{$L("PLACE ORDER")}
</TButton>
</div>
</Container>

View File

@@ -1,12 +1,141 @@
import React from "react";
import React, { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { popPanel, pushPanel, resetPanels } from "../../actions/panelActions";
import TButton from "../../components/TButton/TButton";
import TPanel from "../../components/TPanel/TPanel";
import * as Config from "../../utils/Config";
import { $L } from "../../utils/helperMethods";
import css from "./ConfirmPanel.module.less";
export default function ConfirmPanel({spotlightId}) {
export default function ConfirmPanel({ spotlightId }) {
const dispatch = useDispatch();
const panels = useSelector((state) => state.panels.panels);
const panelInfo = panels.find(
(panel) => panel.name === "confirmpanel"
)?.panelInfo;
const {
bilCityNm,
bilCtpt,
bilDtlAddr,
bilEmalAddr,
bilOdrFnm,
bilOdrLnm,
bilStatNm,
bilZpcd,
cardKnd,
dlvrCityNm,
dlvrCtpt,
dlvrDate,
dlvrDtlAddr,
dlvrEmalAddr,
dlvrOdrFnm,
dlvrOdrLnm,
dlvrZpcd,
ordNo,
realTotAmt,
totDlvrAmt,
} = panelInfo?.orderInfo || {};
const auctProdYn = panelInfo?.auctProdYn || {};
const handleCancel = useCallback((e) => {
if (e && typeof e.preventDefault === "function") {
e.preventDefault();
}
if (e && typeof e.stopPropagation === "function") {
e.stopPropagation();
}
}, []);
const handleReviewClick = useCallback(() => {
dispatch(resetPanels());
dispatch(
pushPanel({
name: Config.panel_names.MY_PAGE_PANEL,
panelInfo: {
menuNm: "My Orders",
menuOrd: 4,
},
})
);
}, [dispatch]);
const handleContinueClick = useCallback(() => {
dispatch(resetPanels());
dispatch(popPanel());
}, [dispatch]);
return (
<TPanel className={css.confirmPanel} isTabActivated={false} spotlightId={spotlightId}>
OK!
<TPanel
className={css.confirmPanel}
isTabActivated={false}
spotlightId={spotlightId}
handleCancel={(e) => handleCancel(e)}
>
<div className={css.title}>
<h2>{$L("THANK YOU.")}</h2>
<h2>{$L("Your Order Has Been Placed")}</h2>
</div>
{panelInfo && (
<div className={css.contentsBox}>
<div className={css.topContents}>
<p className={css.topContentsTitle}>{$L("ESTIMATED DELEVERY")}</p>
<span className={css.topContentsDesc}>{dlvrDate}</span>
</div>
<ul className={css.midContents}>
<li>
<p>{$L("ORDER NUMBER")}</p>
<span>{ordNo}</span>
</li>
<li>
<p className={css.shippingAddressTitle}>
{$L("SHIPPING ADDRESS")}
</p>
<span>
{dlvrCityNm}
<br />
{dlvrDtlAddr}
<br />
{dlvrZpcd}
</span>
</li>
<li>
<p>{$L("FULL NAME")}</p>
<span>
{dlvrOdrFnm} {dlvrOdrLnm}
</span>
</li>
<li>
<p>{$L("PHONE NUMBER")}</p>
<span>{dlvrCtpt}</span>
</li>
<li>
<p>{$L("EMAIL")}</p>
<span>{dlvrEmalAddr}</span>
</li>
</ul>
<div className={css.bottomContents}>
<p className={css.bottomContentsTitle}>{$L("ESTIMATED TOTAL")}</p>
{auctProdYn && auctProdYn === "Y" ? (
<span>
{$L("Purchased products will be paid at the final price.")}
</span>
) : (
<span className={css.bottomContentsDesc}>
{realTotAmt} ({cardKnd})
</span>
)}
</div>
</div>
)}
<div className={css.buttonWrap}>
<TButton onClick={handleReviewClick}>{$L("REVIEW ORDER")}</TButton>
<TButton onClick={handleContinueClick}>
{$L("CONTINUE SHOPPING")}
</TButton>
</div>
</TPanel>
);
}

View File

@@ -0,0 +1,96 @@
@import "../../style/CommonStyle.module.less";
@import "../../style/utils.module.less";
.confirmPanel {
background-color: @BG_COLOR_01;
padding-top: 100px;
.title {
.font(@fontSize: 48px, @fontFamily: @baseFont);
font-weight: bold;
line-height: 1.17;
color: @COLOR_GRAY07;
text-align: center;
}
.contentsBox {
background: @COLOR_WHITE;
.size(@w: 1080px, @h: auto);
margin: 30px auto;
padding: 40px 0 90px 60px;
border: 1px solid #dadada;
border-radius: 12px;
.topContents {
margin-bottom: 27px;
.topContentsTitle {
.font(@fontSize: 30px, @fontFamily: @baseFont);
font-weight: bold;
color: @COLOR_GRAY07;
width: 330px;
display: inline-block;
}
.topContentsDesc {
.font(@fontSize: 30px, @fontFamily: @baseFont);
font-weight: bold;
color: @PRIMARY_COLOR_RED;
width: 600px;
display: inline-block;
}
}
.midContents {
li {
p {
display: inline-block;
width: 330px;
font-size: 24px;
color: @COLOR_GRAY03;
line-height: 1.33;
margin-bottom: 27px;
.shippingAddressTitle {
vertical-align: top;
}
}
span {
display: inline-block;
width: 600px;
font-size: 24px;
color: @COLOR_GRAY03;
line-height: 1.33;
margin-bottom: 27px;
}
}
}
.bottomContents {
margin-top: 27px;
.bottomContentsTitle {
.font(@fontSize: 30px, @fontFamily: @baseFont);
font-weight: bold;
color: @COLOR_GRAY07;
width: 330px;
display: inline-block;
}
.bottomContentsDesc {
.font(@fontSize: 30px, @fontFamily: @baseFont);
font-weight: bold;
color: @PRIMARY_COLOR_RED;
width: 600px;
display: inline-block;
}
}
}
.buttonWrap {
width: 100%;
text-align: center;
margin: 0 auto;
}
}