์ด์ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉฐ ์ด๋ ค์ ๋ ์ ์ ๋จ๊ฒจ๋ณผ๊น ํ๋ค.
ํด๋ก ํ ๊ธฐ์กด์ ์ฌ์ดํธ์ ์ฅ๋ฐ๊ตฌ๋์ ๊ฒฐ์ ํ์ด์ง์ ๋ ์ด์์์ด ๋ ๋ฎ์๋ค.
๊ฐ์ ๋ ์ด์์ ๊ฐ์ CSS๋ฅผ ์ํด ํ์ผ์ ๋๊ฐ์ฉ ๋ ๋ง๋ค๊ณ ํ๋ ๊ฒ์ด ๊ต์ฅํ ๋นํจ์จ์ ์ด๋ผ๊ณ ์๊ฐํ์ฌ,
๊ฐ์ ํ์ด์ง ๋ด์์ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํตํด ํจ์จ์ ์ธ ๊ตฌ์ฑ์ ๋ชฉํ๋ก ์ฝ๋ฉ์ ํ๊ฒ ๋์๋ค.
react-router
์ useParams
ํ
์ ์ด์ฉํ์ฌ cart ํ์ด์ง์ checkout ํ์ด์ง๋ฅผ ๊ตฌ๋ถํ ์ ์๋๋ก ํ์๊ณ ,
๊ทธ์ ๋ฐ๋ผ ์กฐ๊ฑด๋ถ๋ก ๋ทฐ๋ฅผ ๋ํ๋ผ ์ ์๋๋ก ์ฒ๋ฆฌ๋ฅผ ํ์๋ค.
import React, { useCallback, useEffect, useState } from 'react';
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom';
import Button from '../../components/Button/Button';
import Goods from './Goods/Goods';
import { API_ADDRESS } from '../../apiConfig';
import './Order.scss';
const Order = () => {
const [cartList, setCartList] = useState([]);
const { pageType } = useParams();
// ...
useEffect(() => {
if (pageType === 'cart') {
(async () => {
setIsOrderLoading(true);
await fetchCartData();
setIsOrderLoading(false);
})();
} else {
setCartList(() => location.state.cartList);
setTotalPrice(() => 0);
location.state.cartList.forEach(({ price, quantity }) => {
setTotalPrice(prev => prev + price * quantity);
});
}
}, [fetchCartData, pageType, location]);
// ...
return (
<div className="order">
<div className="pageTitleArea">
<div className="progressNav">
<ul className="progress">
<li className="stepOne">
<p>01 ์ฅ๋ฐ๊ตฌ๋</p>
{pageType === 'cart' && <span className="line" />}
</li>
<li className="stepTwo">
<p>02 ๊ฒฐ์ ์งํ</p>
{pageType === 'check' && <span className="line" />}
</li>
<li className="stepThree">
<p>03 ์ฃผ๋ฌธ์๋ฃ</p>
</li>
</ul>
</div>
<div className="pageTitle">
<h1 className="orderTitle">
{pageType === 'cart' && '์ฅ๋ฐ๊ตฌ๋'}
{pageType === 'check' && '๊ฒฐ์ ์งํ'}
</h1>
</div>
</div>
<div className="pageContent">
{// ...}
<div className="orderTotal">
{pageType !== 'cart' && (
<div className="orderInfoContainer">
<div className="selectBox">
<button className="selectedValue">์ ์ฉ์นด๋</button>
<ul className="valueList">
<li>์ ์ฉ์นด๋</li>
<li>์นด์นด์คํ์ด</li>
<li>๋ค์ด๋ฒํ์ด</li>
<li>ํด๋ํฐ๊ฒฐ์ </li>
<li>ํฌ์ธํธ</li>
</ul>
</div>
<div className="mustCheck">
<input
className="checkBox"
type="checkbox"
value={isTermsChecked}
onChange={() => setIsTermsChecked(prev => !prev)}
/>
<label className="label" htmlFor="agree">
๊ตฌ๋งคํ์ค ์ํ์ ํ๋งค์กฐ๊ฑด์ ๋ช
ํํ ํ์ธํ์์ผ๋ฉฐ, ์ด์
๋์ํฉ๋๋ค.
<br />
(์ ์์๊ฑฐ๋๋ฒ ์ 8์กฐ 2ํญ)
</label>
</div>
</div>
)}
<div className="orderCheckButtonWrapper">
{pageType === 'cart' ? (
<Link to="/order/check" state={{ cartList }}>
<Button>์ฅ๋ฐ๊ตฌ๋ ์ํ ์ฃผ๋ฌธ</Button>
</Link>
) : (
<Button btnOnClick={onOrder}>๊ฒฐ์ ํ๊ธฐ</Button>
)}
</div>
</div>
</div>
</div>
);
};
export default Order;
๋ฌผ๋ก ์ฅ๋ฐ๊ตฌ๋ ํน์ ๊ฒฐ์ ์์ ๋ด๊ฒจ์๋ ์ํ์ ๋ํ๋ด๋ ์ปดํฌ๋ํธ <Goods />
๋ํ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ๊ฑธ์ด์ฃผ์๋ค.
import React from 'react';
import NumBtn from '../../../components/ProductInfoBox/NumBtn/NumBtn';
import { ReactComponent as Xbutton } from '../../../assets/Xbutton.svg';
import './Goods.scss';
const Goods = ({
product: { cart_id, korean_name, thumbnail_image_url, price, quantity },
pageType,
deleteGoods,
adjustTotalPrice,
adjustCart,
}) => {
const adjustQuantity = operator => {
if (operator === 'minus') {
if (quantity > 1) {
adjustCart(cart_id, quantity - 1);
adjustTotalPrice(operator, price);
}
} else if (operator === 'plus') {
adjustCart(cart_id, quantity + 1);
adjustTotalPrice(operator, price);
}
};
return (
<tbody className="goods">
<tr className="tableRow">
<td className="tableBody image">
<div className="imageContainer">
<img
className="goodsImage"
alt="example_goods"
src={thumbnail_image_url}
/>
</div>
</td>
<td className="tableBody goods">
<p>{korean_name}</p>
</td>
<td className="tableBody quantity">
{pageType === 'cart' ? (
<NumBtn
minusOne={() => adjustQuantity('minus')}
plusOne={() => adjustQuantity('plus')}
numValue={quantity}
/>
) : (
quantity
)}
</td>
<td className="tableBody price">
<p>{price * quantity}์</p>
</td>
<td className="tableBody goodsButton">
{pageType === 'cart' && (
<button
className="deleteButton"
onClick={() => deleteGoods(cart_id)}
>
<Xbutton />
</button>
)}
</td>
</tr>
</tbody>
);
};
export default Goods;
์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง์ผ ๊ฒฝ์ฐ ์ญ์ ๋ฒํผ์ด ํ์ฑํ ๋ ์ ์๋๋ก ํ์๊ณ ,
๊ฒฐ์ ์งํ๋ฒํผ์ผ ๋๋ ๋จ์ํ ์ปดํฌ๋ํธ๋ก ์๋ํ๋๋ก ํ์๋ค.
ํ๋ก์ ํธ ์ต์ข Merge ํ ์๊ฐ ์ ๋ฐฑ์๋์ ์ ํ๋์ด ๋ง์ง๋ง ๊ฒฐ์ ์ ๋ณด๋ฅผ ๋ฐ๋ ๋ก์ง์ ๋ณ๊ฒฝ์ด ์๊ฒจ์ ์๋จ์์๋ ์์ ์ ํด์ฃผ์ค ์ ์๊ฒ ๋๋ ์ง๋ฌธ์ ํ์ จ๋ค.
์๊ฐ์ด ์ด๋ฐํ์ง๋ง, ์ฐ๋ฆฌํ ๋ฐฑ์๋๋ฅผ ์ํด์ ์ข๋ง ๋ ํ๋ด๊ธฐ๋ก ํ๋ค.
const onOrder = async () => {
if (isTermsChecked) {
const orderTable = cartList.map(product => ({
product_id: product.product_id,
quantity: product.quantity,
}));
const data = await fetch(API_ADDRESS.order_checkout, {
method: 'POST',
headers: {
Authorization: token,
},
body: JSON.stringify(orderTable),
});
const res = await data.json();
navigate(`/order/confirm?order=${res.message}`);
} else {
window.alert('์ฝ๊ด์ ๋์ํด์ฃผ์
์ผ ๊ฒฐ์ ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.');
}
};
์๋ ๊ฒฐ์ ์ดํ ๊ฒฐ์ ์ ๋ณด๋ฅผ ๋ฐ๋ ํ์ด์ง์์ ํด๋น ์ ์ ์ ๊ฐ์ฅ ์ต๊ทผ ๊ฒฐ์ ์ ๋ณด๋ฅผ ๋ฐ์์ค๋ ๋ฐฉ์์ด์์ง๋ง,
์ ๋ณด๋ฅผ ์ ํํ๊ฒ ๋ณด๋ด์ค ์ ์๋๋ก ๋ฐฑ์๋์ ์์ ์ด ์์๋ค.
๊ทธ๊ฒ์ ์ ํํ๊ฒ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ฟผ๋ฆฌ์คํธ๋ง์ผ๋ก ๊ฒฐ์ ์ ๋ณด ํ ์ด๋ธ์ ํด๋น ๊ฒฐ์ ์ ๋ณด id๋ฅผ ๋ฐ์ ๊ฒฐ์ ์๋ฃ ํ์ด์ง๋ก ๋๊ฒจ์ค ์ ์๋๋ก ์์ ์ ํ์๋ค.
์ด ํ ๊ฒฐ์ ์๋ฃ ํ์ด์ง์์๋ id๋ฅผ ์ด์ฉํด ๊ฒฐ์ ์ ๋ณด ํ ์ด๋ธ์์ ํด๋นํ๋ ๊ฒฐ์ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋๋ก ํ์๋ค.
๋์ฐ๋ ์งฑ