Skip to content

Commit

Permalink
Merge pull request #156 from jihwooon/issue-84
Browse files Browse the repository at this point in the history
장바구니 담기 기능 및 도서 상세 페이지 개선
  • Loading branch information
jihwooon authored Mar 7, 2024
2 parents 8896892 + 27a340d commit 6cf77dd
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 2 deletions.
14 changes: 14 additions & 0 deletions client/src/api/cart.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { httpClient } from "./http";

interface AddCartParams {
book_id: number;
quantity: number;
}

const addCart = async (params: AddCartParams) => {
const response = await httpClient.post('/cart', params)

return response.data
};

export default addCart;
80 changes: 80 additions & 0 deletions client/src/components/book/AddToCart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import { useBook } from "../../hooks/useBook";
import { BookDetail } from "../../models/book.model";
import Button from "../common/Button";
import { InputText } from "../common/InputText";

interface Props {
book: BookDetail;
}

const AddToCart = ({ book }: Props) => {
const [quantity, setQuantity] = useState<number>(1)
const { addToCart, cartAdded } = useBook(book.id.toString());

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setQuantity(Number(e.target.value))
}

const handleIncrease = () => {
setQuantity(quantity + 1)
}

const handleDecrease = () => {
if (quantity === 1) return
setQuantity(quantity - 1)
}

return (
<AddToCartStyle $added={cartAdded}>
<div>
<InputText inputType="number" value={quantity} onChange={handleChange}/>
<Button size="medium" scheme="normal" onClick={handleIncrease}>
+
</Button>
<Button size="medium" scheme="normal" onClick={handleDecrease}>
-
</Button>
</div>
<Button size="medium" scheme="primary" onClick={() => addToCart(quantity)}>
장바구니 담기
</Button>
<div className="added">
<p>장바구니에 추가되었습니다.</p>
<Link to="/cart">장바구니 이동</Link>
</div>
</AddToCartStyle>
);
}

interface AddToCartStyleProps {
$added: boolean;
}

const AddToCartStyle = styled.div<AddToCartStyleProps>`
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.added {
position: absolute;
right: 0;
bottom: -90px;
background: ${({ theme }) => theme.color.background};
border-radius: ${({ theme }) => theme.borderRadius.default};
padding: 8px 12px;
opacity: ${({ $added }) => $added ? "1" : "0"};
transition: all 0.5s ease;
}
p {
padding: 0 0 8px 0;
margin: 0;
}
`;

export default AddToCart;
18 changes: 17 additions & 1 deletion client/src/hooks/useBook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import { fetchBook, likeBook, unlikeBook } from "../api/books.api";
import addCart from "../api/cart.api";
import { BookDetail } from "../models/book.model";
import { useAuthStore } from "../store/authStore";
import { useAlert } from "./useAlert";
Expand All @@ -8,6 +9,7 @@ export const useBook = (bookId: string | undefined) => {
const [book, setBook] = useState<BookDetail | null>(null);
const { isLoggedIn } = useAuthStore();
const showAlert = useAlert();
const [cartAdded, setCartAdded] = useState(false)

const likeToggle = () => {
if (!isLoggedIn) {
Expand Down Expand Up @@ -36,6 +38,20 @@ export const useBook = (bookId: string | undefined) => {
}
}

const addToCart = (quantity: number) => {
if (!book) return

addCart({
book_id: book.id,
quantity: quantity
}).then(() => {
setCartAdded(true)
setTimeout(() => {
setCartAdded(false)
}, 3000)
})
}

useEffect(() => {
if (!bookId) return;

Expand All @@ -44,5 +60,5 @@ export const useBook = (bookId: string | undefined) => {
})
}, [bookId])

return { book, likeToggle }
return { book, likeToggle, addToCart, cartAdded }
}
5 changes: 4 additions & 1 deletion client/src/pages/BookDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Link, useParams } from "react-router-dom";
import styled from "styled-components";
import AddToCart from "../components/book/AddToCart";
import LikeButton from "../components/book/LikeButton";
import EllipsisBox from "../components/common/EllipisisBox";
import Title from "../components/common/Title";
Expand Down Expand Up @@ -77,7 +78,9 @@ const BookDetail = () => {
<div className="like">
<LikeButton book={book} onClick={likeToggle} />
</div>
<div className="add-cart">Cart</div>
<div className="add-cart">
<AddToCart book={book}/>
</div>
</div>
</header>
<div className="content">
Expand Down

0 comments on commit 6cf77dd

Please sign in to comment.