목표: 상품관리 REST API 클론 프로젝트
상품추가
App.js
const [items, setItems] = useState([]); //기본상태
const handleAddClicked = (id) => {
//같은 아이디 찾기
const product = products.find((v) => v.id === id);
const found = items.find((v) => v.id === id);
const updatedItems =
//상품확인...모든속성 복사, 개수 +1/없으면 기존 아이템 반환
//기존것 복사 + 새로운 상품 추가
found
? items.map((v) => (v.id === id ? { ...v, count: v.count + 1 } : v))
: [
...items,
{
...product,
count: 1,
},
];
setItems(updatedItems);
};
<ProductList products={products} onAddClick {handleAddClicked} />
ProductList.js
<ul className="list-group products">
{products.map((v) => (
<li key={v.id} className="list-group-item d-flex mt-3">
{/*
프로퍼티같으면 ...표현(스프레드연산자)
productName={v.productName}
category={v.category}
price={v.price}
*/}
<Product {...v} onAddClick={onAddClick} />
</li>
))}
</ul>
Product.js
export function Product(props) {
const id = props.id;
const productName = props.productName;
const category = props.category;
const price = props.price;
const handleAddBtnClicked = (e) => {
props.onAddClick(id);
};
return (
<>
<div className="col">
<div className="row text-muted">{category}</div>
<div className="row">{productName}</div>
</div>
<div className="col text-center price">{price}원</div>
<div className="col text-end action">
<button
onClick={handleAddBtnClicked}
className="btn btn-small btn-outline-dark"
>
추가
</button>
</div>
</>
);
상품목록 가져오기
App.js
//컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 Hook
//비동기작업은 여기서
useEffect(() => {
axios
.get("http://localhost:8080/api/v1/products")
.then((v) => setProducts(v.data));
}, []); //빈배열 딱 한번 실행
주문하기
App.js
const handleOrderSubmit = (order) => {
if (items.length === 0) {
alert("아이템을 추가해 주세요!");
} else {
axios
.post("http://localhost:8080/api/v1/orders", {
email: order.email,
address: order.address,
postcode: order.postcode,
orderItems: items.map((v) => ({
productId: v.productId,
category: v.category,
price: v.price,
quantity: v.count,
})),
})
.then(
(v) => alert("주문이 정상적으로 접수되었습니다."),
(e) => {
alert("서버 장애");
console.error(e);
}
);
}
};
<Summary items={items} onOrderSubmit={handleOrderSubmit} />;
Summary.js
export function Summary({ items = [], onOrderSubmit }) {
const totalPrice = items.reduce(
(prev, curr) => prev + curr.price * curr.count,
0
);
const [order, setOrder] = useState({ email: "" });
const handleEmailInputChanged = (e) =>
setOrder({ ...order, email: e.target.value });
const handleSubmit = (e) => {
if (order.address === "" || order.email === "" || order.postcode === "") {
alert("입력값을 확인해주세요!");
} else {
onOrderSubmit(order);
}
};
return (
<>
<div>
<h5 className="m-0 p-0">
<b>Summary</b>
</h5>
</div>
<hr />
{items.map((v) => (
<SummaryItem
key={v.productId}
count={v.count}
productName={v.productName}
/>
))}
<form>
<div className="mb-3">
<label htmlFor="email" className="form-label">
이메일
</label>
<input
type="email"
className="form-control mb-1"
id="email"
value={order.email}
onChange={handleEmailInputChanged}
/>
</div>
</form>
<div className="row pt-2 pb-2 border-top">
<h5 className="col">총금액</h5>
<h5 className="col text-end">{totalPrice}원</h5>
</div>
<button className="btn btn-dark col-12" onClick={handleSubmit}>
결제하기
</button>
</>
);
}
SummaryItem.js
export function SummaryItem({ productName, count }) {
return (
<div className="row">
<h6 className="p-0">
{productName} <span className="badge bg-dark text-">{count}개</span>
</h6>
</div>
);
}
@프로그래머스 미니 데브코스 & CNU SW Academy 강의 내용 정리
'모각코' 카테고리의 다른 글
[모각코 10회차] 네이버 지역검색 API 활용 맛집 리스트 만들기 (0) | 2022.09.08 |
---|---|
[모각코 8회차] Spring Security with JWT (0) | 2022.08.25 |
[모각코 7회차] Spring Security Internals (0) | 2022.08.19 |
[모각코 6회차] 주문관리 API (0) | 2022.08.11 |
[모각코 5회차] SPA와 CORS (0) | 2022.08.04 |