diff --git a/src/Home/api/getLecueBook.ts b/src/Home/api/getLecueBook.ts
index 336d2a2b..28a38c07 100644
--- a/src/Home/api/getLecueBook.ts
+++ b/src/Home/api/getLecueBook.ts
@@ -2,7 +2,7 @@ import { api } from '../../libs/api';
const getLecueBook = async () => {
const { data } = await api.get('/api/common/home');
- return data;
+ return data.data;
};
export default getLecueBook;
diff --git a/src/Home/components/LecueBookList/LecueBookList.style.ts b/src/Home/components/LecueBookList/LecueBookList.style.ts
index 411e6889..d1079d34 100644
--- a/src/Home/components/LecueBookList/LecueBookList.style.ts
+++ b/src/Home/components/LecueBookList/LecueBookList.style.ts
@@ -25,11 +25,11 @@ export const Title = styled.header`
export const LecueBookList = styled.section`
display: grid;
- gap: 2.2rem;
+ gap: 2em 2.4rem;
grid-template-columns: repeat(3, 1fr);
width: 100%;
- padding: 3rem 1.6rem 2.2rem;
+ padding: 3rem 1.6rem;
`;
export const LecueBook = styled.li`
@@ -38,13 +38,19 @@ export const LecueBook = styled.li`
justify-content: center;
align-items: center;
flex-direction: column;
+ position: relative;
width: 100%;
- height: 14rem;
cursor: pointer;
`;
+export const IconWrapper = styled.button`
+ position: absolute;
+ top: 0;
+ left: 0.1rem;
+`;
+
export const BookImage = styled.img`
width: 9.8rem;
height: 9.8rem;
diff --git a/src/Home/components/LecueBookList/index.tsx b/src/Home/components/LecueBookList/index.tsx
index 0bad82f7..4eda671e 100644
--- a/src/Home/components/LecueBookList/index.tsx
+++ b/src/Home/components/LecueBookList/index.tsx
@@ -1,8 +1,10 @@
-// import { useNavigate } from 'react-router-dom';
-
-import { useNavigate } from 'react-router-dom';
+import { useNavigate } from 'react-router';
+import { IcHomeFavorite } from '../../../assets';
+import useDeleteFavorite from '../../../libs/hooks/useDeleteFavorite';
+import useGetFavorite from '../../../libs/hooks/useGetFavorite';
import useGetLecueBook from '../../hooks/useGetLecueBook';
+import NoBookmarkList from '../NoBookmarkList';
import * as S from './LecueBookList.style';
interface BookProps {
@@ -12,29 +14,51 @@ interface BookProps {
favoriteName: string;
}
-function LecueBookList() {
- const { data } = useGetLecueBook();
+interface LecueBookListProps {
+ title: string;
+}
+
+function LecueBookList({ title }: LecueBookListProps) {
const navigate = useNavigate();
+ const deleteMutation = useDeleteFavorite();
+ const isBookmark = title.includes('즐겨찾기');
+ const { data } = isBookmark ? useGetFavorite() : useGetLecueBook();
const handleClickLecueBook = (uuid: string) => {
navigate(`/lecue-book/${uuid}`);
};
+ const handleClickFavoriteIcon = (bookId: number) => {
+ deleteMutation.mutate(bookId);
+ };
+
return (
- 인기 레큐북 구경하기
-
- {data &&
- data.data.map((book: BookProps) => (
- handleClickLecueBook(book.bookUuid)}
- >
-
+ {title}
+ {data && data.length !== 0 ? (
+
+ {data.map((book: BookProps) => (
+
+ {isBookmark && (
+ handleClickFavoriteIcon(book.bookId)}
+ >
+
+
+ )}
+
+ handleClickLecueBook(book.bookUuid)}
+ />
{book.favoriteName}
))}
-
+
+ ) : (
+
+ )}
);
}
diff --git a/src/Home/components/NavigateLecueBook/NavigateLecueBook.style.ts b/src/Home/components/NavigateLecueBook/NavigateLecueBook.style.ts
index 3af55d88..03fbf33a 100644
--- a/src/Home/components/NavigateLecueBook/NavigateLecueBook.style.ts
+++ b/src/Home/components/NavigateLecueBook/NavigateLecueBook.style.ts
@@ -8,32 +8,30 @@ export const MainWrapper = styled.div`
export const IconWrapper = styled.section`
display: flex;
- gap: 15.7rem;
- justify-content: space-between;
+
+ /* 바뀔 수 있을 것 같으니 디자인 나오면 다시 확인해보기 ! */
+ gap: 16rem;
align-items: baseline;
width: 100%;
- padding: 6rem 1.6rem 5rem;
+ margin: 4rem 1.8rem 3.5rem 1.6rem;
`;
-export const ButtonWrapper = styled.section`
- display: flex;
- gap: 1rem;
- flex-direction: column;
+export const DummyGraphic = styled.div`
+ width: 37.5rem;
+ height: 20rem;
- padding: 0 9.5rem 4.9rem 0;
+ background-color: ${({ theme }) => theme.colors.LG};
`;
-export const Button = styled.button<{ variant?: boolean }>`
- width: 28rem;
- height: 6.4rem;
+export const Button = styled.button`
+ padding: 2.1rem 9.4rem 2.2rem 8.8rem;
+ margin: 2rem 0 4rem;
border: 0.1rem solid ${({ theme }) => theme.colors.BG};
border-radius: 0 0.2rem 0.2rem 0;
border-left: none;
- background-color: ${({ theme, variant }) =>
- variant ? theme.colors.white : theme.colors.BG};
- color: ${({ theme, variant }) =>
- variant ? theme.colors.BG : theme.colors.white};
+ background-color: ${({ theme }) => theme.colors.BG};
+ color: ${({ theme }) => theme.colors.white};
${({ theme }) => theme.fonts.Title1_SB_16}
`;
diff --git a/src/Home/components/NavigateLecueBook/index.tsx b/src/Home/components/NavigateLecueBook/index.tsx
index 29b9e660..6215939f 100644
--- a/src/Home/components/NavigateLecueBook/index.tsx
+++ b/src/Home/components/NavigateLecueBook/index.tsx
@@ -1,18 +1,23 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
-import { IcNotice, ImgLogoLecue } from '../../../assets';
+import { IcProfile, ImgLogoLecue } from '../../../assets';
import CommonModal from '../../../components/common/Modal/CommonModal';
import * as S from './NavigateLecueBook.style';
function NavigateLecueBook() {
- const NAVIGATE_CATEGORY = ['레큐북 만들기', '내 기록 보기'];
const navigate = useNavigate();
const [modalOn, setModalOn] = useState(false);
- const handleClickNavBtn = (idx: number) => {
+ const handleClickIcProfile = () => {
+ const token = localStorage.getItem('token');
+
+ navigate('/mypage', { state: token });
+ };
+
+ const handleClickNavBtn = () => {
if (localStorage.getItem('token')) {
- idx === 0 ? navigate('/target') : navigate('/mypage');
+ navigate('/target');
} else {
setModalOn(true);
}
@@ -22,29 +27,16 @@ function NavigateLecueBook() {
-
-
-
+
+
-
- {NAVIGATE_CATEGORY.map((category, idx) => {
- return (
- handleClickNavBtn(idx)}
- >
- {category}
-
- );
- })}
-
+ {/* 임시로 넣은 것! 추후 새로운 그래픽으로 수정 */}
+
+
+
+ 레큐북 만들기
+
{modalOn && (
theme.colors.BG};
+ ${({ theme }) => theme.fonts.Body2_M_14};
+`;
+
+export const NavigateBtn = styled.button`
+ padding: 0.8rem 2.8rem;
+
+ border: 0.1rem solid ${({ theme }) => theme.colors.BG};
+ border-radius: 0.6rem;
+ background-color: ${({ theme }) => theme.colors.white};
+ color: ${({ theme }) => theme.colors.BG};
+ ${({ theme }) => theme.fonts.Body4_SB_14};
+`;
diff --git a/src/Home/components/NoBookmarkList/index.tsx b/src/Home/components/NoBookmarkList/index.tsx
new file mode 100644
index 00000000..c2c43909
--- /dev/null
+++ b/src/Home/components/NoBookmarkList/index.tsx
@@ -0,0 +1,28 @@
+import { useNavigate } from 'react-router';
+
+import * as S from './NoBookmarkList.style';
+
+const NoBookmarkList = () => {
+ const navigate = useNavigate();
+
+ const handleClickNavigateBtn = () => {
+ navigate('/mypage');
+ };
+
+ return (
+
+
+ 아직 즐겨찾기한 레큐북이 없어요.
+
+ 자주 보고 싶은 레큐북을 즐겨찾기 해보세요.
+
+
+
+
+ 레큐북 보러가기
+
+
+ );
+};
+
+export default NoBookmarkList;
diff --git a/src/Home/hooks/.gitkeep b/src/Home/hooks/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/Home/hooks/useGetLecueBook.ts b/src/Home/hooks/useGetLecueBook.ts
index 0fa4627e..a43b43ea 100644
--- a/src/Home/hooks/useGetLecueBook.ts
+++ b/src/Home/hooks/useGetLecueBook.ts
@@ -6,14 +6,14 @@ import getLecueBook from '../api/getLecueBook';
const useGetLecueBook = () => {
const navigate = useNavigate();
- const { isLoading, data } = useQuery({
+ const { isLoading: isLoadingLecueBook, data: lecueBook } = useQuery({
queryKey: ['get-lecue-book'],
queryFn: () => getLecueBook(),
onError: () => navigate('/error'),
refetchOnWindowFocus: false,
});
- return { isLoading, data };
+ return { isLoading: isLoadingLecueBook, data: lecueBook };
};
export default useGetLecueBook;
diff --git a/src/Home/page/index.tsx b/src/Home/page/index.tsx
index 1c4c3db5..9d640380 100644
--- a/src/Home/page/index.tsx
+++ b/src/Home/page/index.tsx
@@ -8,18 +8,21 @@ import useGetLecueBook from '../hooks/useGetLecueBook';
import * as S from './Home.style';
function Home({ handleStep }: StepProps) {
- const { isLoading } = useGetLecueBook();
+ const token = localStorage.getItem('token');
+ const { isLoading: isLoadingLecueBook } = useGetLecueBook();
useEffect(() => {
handleStep(1);
}, []);
- return isLoading ? (
+ return isLoadingLecueBook ? (
) : (
-
+
+ {token && }
+
);
}
diff --git a/src/assets/icon/ic_alert_o.svg b/src/assets/icon/ic_alert_o.svg
new file mode 100644
index 00000000..a8163791
--- /dev/null
+++ b/src/assets/icon/ic_alert_o.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/assets/icon/ic_alert_x.svg b/src/assets/icon/ic_alert_x.svg
new file mode 100644
index 00000000..6d3e3628
--- /dev/null
+++ b/src/assets/icon/ic_alert_x.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/assets/icon/ic_home_favorite.svg b/src/assets/icon/ic_home_favorite.svg
new file mode 100644
index 00000000..d8b3cc7c
--- /dev/null
+++ b/src/assets/icon/ic_home_favorite.svg
@@ -0,0 +1,23 @@
+
diff --git a/src/assets/icon/ic_profile.svg b/src/assets/icon/ic_profile.svg
new file mode 100644
index 00000000..0b5f53f7
--- /dev/null
+++ b/src/assets/icon/ic_profile.svg
@@ -0,0 +1,29 @@
+
diff --git a/src/assets/index.ts b/src/assets/index.ts
index 48d600dd..5d5b41fe 100644
--- a/src/assets/index.ts
+++ b/src/assets/index.ts
@@ -6,6 +6,8 @@ import BtnFloatingStickerOrange from './button/btn_floating_sticker_orange.svg?r
import BtnFloatingWrite from './button/btn_floating_write.svg?react';
import BtnFloatingWriteOrange from './button/btn_floating_write_orange.svg?react';
import BtnKakaologin from './button/btn_kakaologin.svg?react';
+import IcAlertO from './icon/ic_alert_o.svg?react';
+import IcAlertX from './icon/ic_alert_x.svg?react';
import IcArrowLeftBlack from './icon/ic_arrow_left_black.svg?react';
import IcArrowLeftWhite from './icon/ic_arrow_left_white.svg?react';
import IcCamera from './icon/ic_camera.svg?react';
@@ -15,7 +17,9 @@ import IcCheck from './icon/ic_check.svg?react';
import IcCrown from './icon/ic_crown.svg?react';
import IcDate from './icon/ic_date.svg?react';
import IcHome from './icon/ic_home.svg?react';
+import IcHomeFavorite from './icon/ic_home_favorite.svg?react';
import IcNotice from './icon/ic_notice.svg?react';
+import IcProfile from './icon/ic_profile.svg?react';
import IcSharing from './icon/ic_sharing.svg?react';
import IcWaste from './icon/ic_waste.svg?react';
import IcX from './icon/ic_x.svg?react';
@@ -56,6 +60,8 @@ export {
BtnFloatingWrite,
BtnFloatingWriteOrange,
BtnKakaologin,
+ IcAlertO,
+ IcAlertX,
IcArrowLeftBlack,
IcArrowLeftWhite,
IcCamera,
@@ -65,7 +71,9 @@ export {
IcCrown,
IcDate,
IcHome,
+ IcHomeFavorite,
IcNotice,
+ IcProfile,
IcSharing,
IcWaste,
IcX,
diff --git a/src/libs/api/deleteFavorite.ts b/src/libs/api/deleteFavorite.ts
new file mode 100644
index 00000000..d47d7c76
--- /dev/null
+++ b/src/libs/api/deleteFavorite.ts
@@ -0,0 +1,16 @@
+import { api } from '../../libs/api';
+
+const deleteFavorite = async (bookId: number) => {
+ const token = localStorage.getItem('token');
+ const { data } = await api.delete('/api/favorite', {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ data: { bookId: bookId },
+ });
+
+ return data;
+};
+
+export default deleteFavorite;
diff --git a/src/libs/api/getFavorite.ts b/src/libs/api/getFavorite.ts
new file mode 100644
index 00000000..7c7122d7
--- /dev/null
+++ b/src/libs/api/getFavorite.ts
@@ -0,0 +1,14 @@
+import { api } from '../../libs/api';
+
+const getFavorite = async () => {
+ const token = localStorage.getItem('token');
+ const { data } = await api.get('/api/favorite', {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ });
+ return data.data;
+};
+
+export default getFavorite;
diff --git a/src/libs/hooks/.keep b/src/libs/hooks/.keep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/libs/hooks/useDeleteFavorite.ts b/src/libs/hooks/useDeleteFavorite.ts
new file mode 100644
index 00000000..81a364e1
--- /dev/null
+++ b/src/libs/hooks/useDeleteFavorite.ts
@@ -0,0 +1,21 @@
+import { useMutation, useQueryClient } from 'react-query';
+import { useNavigate } from 'react-router-dom';
+
+import deleteFavorite from '../api/deleteFavorite';
+
+const useDeleteFavorite = () => {
+ const navigate = useNavigate();
+ const queryClient = useQueryClient();
+ const mutation = useMutation({
+ mutationFn: (bookId: number) => {
+ return deleteFavorite(bookId);
+ },
+ onError: () => navigate('/error'),
+ onSuccess: () => {
+ queryClient.refetchQueries(['get-favorite'], { exact: true });
+ },
+ });
+ return mutation;
+};
+
+export default useDeleteFavorite;
diff --git a/src/libs/hooks/useGetFavorite.ts b/src/libs/hooks/useGetFavorite.ts
new file mode 100644
index 00000000..fc48f529
--- /dev/null
+++ b/src/libs/hooks/useGetFavorite.ts
@@ -0,0 +1,19 @@
+import { useQuery } from 'react-query';
+import { useNavigate } from 'react-router-dom';
+
+import getFavorite from '../api/getFavorite';
+
+const useGetFavorite = () => {
+ const navigate = useNavigate();
+
+ const { isLoading: isLoadingFavorite, data: favorite } = useQuery({
+ queryKey: ['get-favorite'],
+ queryFn: () => getFavorite(),
+ onError: () => navigate('/error'),
+ refetchOnWindowFocus: false,
+ });
+
+ return { isLoading: isLoadingFavorite, data: favorite };
+};
+
+export default useGetFavorite;