diff --git a/client/src/api/books.api.ts b/client/src/api/books.api.ts
index fdf3b82..ece9433 100644
--- a/client/src/api/books.api.ts
+++ b/client/src/api/books.api.ts
@@ -36,3 +36,16 @@ export const fetchBook = async (bookId: string) => {
return response.data;
}
+
+export const likeBook = async (bookId: number) => {
+ const response = await httpClient.post(`/likes/${bookId}`)
+
+ return response.data;
+
+}
+
+export const unlikeBook = async (bookId: number) => {
+ const response = await httpClient.delete(`/likes/${bookId}`)
+
+ return response.data;
+}
\ No newline at end of file
diff --git a/client/src/components/book/LikeButton.tsx b/client/src/components/book/LikeButton.tsx
new file mode 100644
index 0000000..76ab422
--- /dev/null
+++ b/client/src/components/book/LikeButton.tsx
@@ -0,0 +1,34 @@
+import { FaHeart } from "react-icons/fa";
+import styled from "styled-components";
+import { BookDetail } from "../../models/book.model";
+import Button from "../common/Button";
+
+interface Props {
+ book: BookDetail;
+ onClick: () => void;
+}
+
+const LikeButton = ({book, onClick}: Props) => {
+ return (
+
+
+
+ );
+}
+
+const LikeButtonStyle = styled.div`
+ display: flex;
+ gap: 6px;
+
+ svg {
+ color: inherit;
+ * {
+ color: inherit;
+ }
+ }
+`;
+
+export default LikeButton;
diff --git a/client/src/components/common/Header.tsx b/client/src/components/common/Header.tsx
index 606414c..e3ab2de 100644
--- a/client/src/components/common/Header.tsx
+++ b/client/src/components/common/Header.tsx
@@ -1,13 +1,13 @@
-import styled from "styled-components";
-import { FaSignInAlt, FaRegUser } from "react-icons/fa";
-import logo from '../../assets/images/logo.png'
+import { FaRegUser, FaSignInAlt } from "react-icons/fa";
import { Link } from "react-router-dom";
+import styled from "styled-components";
+import logo from '../../assets/images/logo.png';
import { useCategory } from "../../hooks/useCategory";
import { useAuthStore } from "../../store/authStore";
const Header = () => {
const { category } = useCategory();
- const { isloggedIn, storeLogout } = useAuthStore();
+ const { isLoggedIn: isloggedIn, storeLogout } = useAuthStore();
return (
@@ -60,7 +60,7 @@ const HeaderStyle = styled.header`
width: 100%;
margin: 0 auto;
max-width: ${({ theme }) => theme.layout.width.large};
-
+
display: flex;
justify-content: space-between;
padding: 20px 0;
diff --git a/client/src/hooks/useBook.ts b/client/src/hooks/useBook.ts
index 06f466a..88fd7db 100644
--- a/client/src/hooks/useBook.ts
+++ b/client/src/hooks/useBook.ts
@@ -1,9 +1,40 @@
import { useEffect, useState } from "react";
-import { fetchBook } from "../api/books.api";
+import { fetchBook, likeBook, unlikeBook } from "../api/books.api";
import { BookDetail } from "../models/book.model";
+import { useAuthStore } from "../store/authStore";
+import { useAlert } from "./useAlert";
export const useBook = (bookId: string | undefined) => {
const [book, setBook] = useState(null);
+ const { isLoggedIn } = useAuthStore();
+ const showAlert = useAlert();
+
+ const likeToggle = () => {
+ if (!isLoggedIn) {
+ showAlert('로그인이 필요합니다.')
+ return;
+ }
+
+ if (!book) return;
+
+ if (book.liked) {
+ unlikeBook(book.id).then(() => {
+ setBook({
+ ...book,
+ liked: false,
+ likes: book.likes - 1,
+ })
+ })
+ } else {
+ likeBook(book.id).then(() => {
+ setBook({
+ ...book,
+ liked: true,
+ likes: book.likes + 1,
+ })
+ })
+ }
+ }
useEffect(() => {
if (!bookId) return;
@@ -13,5 +44,5 @@ export const useBook = (bookId: string | undefined) => {
})
}, [bookId])
- return { book }
+ return { book, likeToggle }
}
diff --git a/client/src/pages/BookDetail.tsx b/client/src/pages/BookDetail.tsx
index 7220e7b..95fbd19 100644
--- a/client/src/pages/BookDetail.tsx
+++ b/client/src/pages/BookDetail.tsx
@@ -1,5 +1,6 @@
import { Link, useParams } from "react-router-dom";
import styled from "styled-components";
+import LikeButton from "../components/book/LikeButton";
import EllipsisBox from "../components/common/EllipisisBox";
import Title from "../components/common/Title";
import { useBook } from "../hooks/useBook";
@@ -47,7 +48,7 @@ const bookInfoList = [
const BookDetail = () => {
const { bookId } = useParams();
- const { book } = useBook(bookId);
+ const { book, likeToggle } = useBook(bookId);
if (!book) return null;
@@ -73,8 +74,9 @@ const BookDetail = () => {
))}
{book.summary}
- Like
-
+
+
+
Cart
diff --git a/client/src/pages/Signin.tsx b/client/src/pages/Signin.tsx
index a0d9a21..5d9dc04 100644
--- a/client/src/pages/Signin.tsx
+++ b/client/src/pages/Signin.tsx
@@ -1,12 +1,12 @@
import { useForm } from 'react-hook-form'
-import Title from "../components/common/Title"
-import { InputText } from "../components/common/InputText"
-import Button from "../components/common/Button"
import { Link, useNavigate } from "react-router-dom"
-import { useAlert } from '../hooks/useAlert'
-import { SingupStyle } from './Signup'
import { signin } from '../api/auth.api'
+import Button from "../components/common/Button"
+import { InputText } from "../components/common/InputText"
+import Title from "../components/common/Title"
+import { useAlert } from '../hooks/useAlert'
import { useAuthStore } from '../store/authStore'
+import { SingupStyle } from './Signup'
export interface SigninProps {
email: string;
@@ -18,8 +18,8 @@ const Signin = () => {
const showAlert = useAlert();
const { register, handleSubmit, formState: { errors } } = useForm();
- const { isloggedIn, storeLogin } = useAuthStore();
-
+ const { isLoggedIn: isloggedIn, storeLogin } = useAuthStore();
+
const onSubmit = (data: SigninProps) => {
signin(data).then((res) => {
storeLogin(res.data)
@@ -36,16 +36,16 @@ const Signin = () => {