-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #157 from jihwooon/issue-85
장바구니 기능 구현
- Loading branch information
Showing
14 changed files
with
244 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,25 @@ | ||
import { Cart } from "src/models/cart.model"; | ||
import { httpClient } from "./http"; | ||
|
||
interface AddCartParams { | ||
book_id: number; | ||
quantity: number; | ||
} | ||
|
||
const addCart = async (params: AddCartParams) => { | ||
export const addCart = async (params: AddCartParams) => { | ||
const response = await httpClient.post('/cart', params) | ||
|
||
return response.data | ||
}; | ||
|
||
export default addCart; | ||
export const fetchCart = async () => { | ||
const response = await httpClient.get<Cart[]>("/carts") | ||
|
||
return response.data | ||
}; | ||
|
||
export const deleteCart = async (cartId: number) => { | ||
const response = await httpClient.delete(`/carts/${cartId}`) | ||
|
||
return response.data; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { useMemo } from "react"; | ||
import { useAlert } from "src/hooks/useAlert"; | ||
import { Cart } from "src/models/cart.model"; | ||
import { formatNumber } from "src/utils/format"; | ||
import styled from "styled-components"; | ||
import Button from "../common/Button"; | ||
import Title from "../common/Title"; | ||
import CheckIconButton from "./CheckIconButton"; | ||
|
||
interface Props { | ||
cart: Cart; | ||
checkedItems: number[]; | ||
onCheck: (id: number) => void; | ||
onDelete: (id: number) => void; | ||
} | ||
|
||
const CartItem = ({cart, checkedItems, onCheck, onDelete}: Props) => { | ||
const { showConfirm } = useAlert() | ||
|
||
const isChecked = useMemo(() => { | ||
return checkedItems.includes(cart.id) | ||
}, [checkedItems, cart.id]) | ||
|
||
const handleCheck = () => { | ||
onCheck(cart.id) | ||
} | ||
|
||
const handleDelete = () => { | ||
showConfirm('정말 삭제하시겠습니까?', () => { | ||
onDelete(cart.id) | ||
}) | ||
} | ||
|
||
return ( | ||
<CartItemStyle> | ||
<div className="info"> | ||
<div><CheckIconButton isChecked={isChecked} onCheck={handleCheck}/></div> | ||
<div> | ||
<Title size="medium">{cart.title}</Title> | ||
<p className="summary">{cart.summary}</p> | ||
<p className="price">{formatNumber(cart.price)}원</p> | ||
<p className="price">{cart.quantity}권</p> | ||
</div> | ||
</div> | ||
<Button size="medium" scheme="normal" onClick={handleDelete}> | ||
장바구니 삭제 | ||
</Button> | ||
</CartItemStyle> | ||
); | ||
} | ||
|
||
const CartItemStyle = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: start; | ||
border: ${({ theme }) => theme.color.border}; | ||
border-radius: ${({ theme }) => theme.borderRadius.default}; | ||
padding: 12px; | ||
p { | ||
padding: 0 0 8px 0; | ||
margin: 0; | ||
} | ||
`; | ||
|
||
export default CartItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { FaRegCheckCircle, FaRegCircle } from "react-icons/fa"; | ||
import styled from "styled-components"; | ||
|
||
interface Props { | ||
isChecked: boolean; | ||
onCheck: () => void; | ||
} | ||
|
||
const CheckIconButton = ({ isChecked, onCheck }: Props) => { | ||
return ( | ||
<CheckIconButtonStyle onClick={onCheck}> | ||
{ | ||
isChecked ? <FaRegCircle /> : <FaRegCheckCircle /> | ||
} | ||
</CheckIconButtonStyle> | ||
); | ||
} | ||
|
||
const CheckIconButtonStyle = styled.button` | ||
background-color: none; | ||
border: 0; | ||
cursor: pointer; | ||
svg { | ||
width: 24px; | ||
height: 24px; | ||
} | ||
`; | ||
|
||
export default CheckIconButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,15 @@ | ||
import { useCallback } from "react" | ||
import { useCallback } from "react"; | ||
|
||
export const useAlert = () => { | ||
const showAlert = useCallback((message: string) => { | ||
window.alert(message) | ||
window.alert(message) | ||
}, []) | ||
|
||
return showAlert; | ||
const showConfirm = useCallback((message: string, onConfirm: () => void) => { | ||
if (window.confirm(message)) { | ||
onConfirm(); | ||
} | ||
}, []); | ||
|
||
return { showAlert, showConfirm }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { useEffect, useState } from "react"; | ||
import { deleteCart, fetchCart } from "src/api/cart.api"; | ||
import { Cart } from "src/models/cart.model"; | ||
|
||
export const useCart = () => { | ||
const [carts, setCarts] = useState<Cart[]>([]); | ||
const [isEmpty, setIsEmpty] = useState(true) | ||
|
||
const deleteCartItem = (id: number) => { | ||
deleteCart(id).then(() => { | ||
setCarts(carts.filter((cart) => cart.id !== id)) | ||
}) | ||
} | ||
|
||
useEffect(() => { | ||
fetchCart().then((carts) => { | ||
setCarts(carts) | ||
setIsEmpty(carts.length === 0) | ||
}) | ||
}, []) | ||
|
||
return { carts, isEmpty, deleteCartItem } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { useState } from "react"; | ||
import CartItem from "src/components/cart/CartItem"; | ||
import Title from "src/components/common/Title"; | ||
import { useCart } from "src/hooks/useCart"; | ||
import styled from "styled-components"; | ||
|
||
const Cart = () => { | ||
const { carts, deleteCartItem } = useCart() | ||
const [checkedItems, setCheckedItems] = useState<number[]>([30]) | ||
|
||
const handleCheckItem = (id: number) => { | ||
if (checkedItems.includes(id)) { | ||
setCheckedItems(checkedItems.filter((item) => item !== id)); | ||
} else { | ||
setCheckedItems([ | ||
...checkedItems, | ||
id | ||
]) | ||
} | ||
} | ||
|
||
const handleItemDelete = (id: number) => { | ||
deleteCartItem(id) | ||
} | ||
|
||
return ( | ||
<> | ||
<Title size="large">장바구니</Title> | ||
<CartStyle> | ||
<div className="content"> | ||
{ | ||
carts.map((item) => ( | ||
<CartItem | ||
key={item.id} | ||
cart={item} | ||
checkedItems={checkedItems} | ||
onCheck={handleCheckItem} | ||
onDelete={handleItemDelete} | ||
/> | ||
)) | ||
} | ||
</div> | ||
</CartStyle> | ||
</> | ||
); | ||
} | ||
|
||
const CartStyle = styled.div``; | ||
|
||
export default Cart; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.