{title.map((name, index) => (
-
-
+
+
{name}
-
+
{index !== title.length - 1 && }
))}
From a7b092fada0d9ec233c1e90a1ff1e52c730143db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 00:25:10 +0900
Subject: [PATCH 04/11] refactor(member): restructured `bookLoanRecord`
hooks(#112)
---
apps/member/src/api/book.ts | 84 ++++++++++---------
.../BookDetailSection/BookDetailSection.tsx | 5 +-
.../components/panels/BookPanel/BookPanel.tsx | 8 +-
.../hooks/queries/book-loan-record/index.ts | 6 ++
.../useBookLoanBorrowMutation.ts} | 29 ++++---
.../useBookLoanExtendMutation.ts} | 8 +-
.../useBookLoanRecordApproveMutation.ts | 30 +++++++
.../useBookLoanRecordConditions.ts | 8 +-
.../useBookLoanRecordOverdue.ts | 6 +-
.../useBookLoanReturnMutation.ts} | 9 +-
apps/member/src/hooks/queries/index.ts | 2 +-
apps/member/src/pages/MyPage/MyPage.tsx | 2 +-
12 files changed, 120 insertions(+), 77 deletions(-)
create mode 100644 apps/member/src/hooks/queries/book-loan-record/index.ts
rename apps/member/src/hooks/queries/{useBookLoanBorrowMutation.tsx => book-loan-record/useBookLoanBorrowMutation.ts} (56%)
rename apps/member/src/hooks/queries/{useBookLoanExtendMutation.tsx => book-loan-record/useBookLoanExtendMutation.ts} (82%)
create mode 100644 apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts
rename apps/member/src/hooks/queries/{ => book-loan-record}/useBookLoanRecordConditions.ts (80%)
rename apps/member/src/hooks/queries/{ => book-loan-record}/useBookLoanRecordOverdue.ts (85%)
rename apps/member/src/hooks/queries/{useBookLoanReturnMutation.tsx => book-loan-record/useBookLoanReturnMutation.ts} (84%)
diff --git a/apps/member/src/api/book.ts b/apps/member/src/api/book.ts
index 195e1e96..246a02a4 100644
--- a/apps/member/src/api/book.ts
+++ b/apps/member/src/api/book.ts
@@ -1,9 +1,8 @@
import { END_POINT } from '@constants/api';
-import { createCommonPagination } from '@utils/api';
+import { createCommonPagination, createPath } from '@utils/api';
import type {
BaseResponse,
- PaginationPramsType,
PaginationType,
WithPaginationPrams,
} from '@type/api';
@@ -15,12 +14,12 @@ import type {
import { server } from './server';
-export interface BorrowerBookInfo {
+export interface BookLoanRequestData {
bookId: number;
borrowerId: string;
}
-export interface GetBookLoanRecordConditionsPrams extends PaginationPramsType {
+export interface BookLoanRecordSearchOptions extends WithPaginationPrams {
bookId?: number;
borrowerId?: string;
isReturned?: boolean;
@@ -28,79 +27,78 @@ export interface GetBookLoanRecordConditionsPrams extends PaginationPramsType {
/**
* 도서 목록 조회
*/
-export const getBooks = async (page: number, size: number) => {
- const params = { page, size };
+export async function getBooks(page: number, size: number) {
const { data } = await server.get
>({
- url: createCommonPagination(END_POINT.BOOK, params),
+ url: createCommonPagination(END_POINT.BOOK, { page, size }),
});
return data;
-};
+}
/**
* 도서 상세 조회
*/
-export const getBookDetail = async (id: number) => {
+export async function getBookDetail(id: number) {
const { data } = await server.get>({
url: END_POINT.BOOK_DETAIL(id),
});
return data;
-};
+}
/**
* 나의 대출내역 조회
*/
-export const getMyBooks = async (id: string, page: number, size: number) => {
- const params = { page, size };
+export async function getMyBooks(id: string, page: number, size: number) {
const { data } = await server.get>({
- url: createCommonPagination(END_POINT.BOOK, params),
+ url: createCommonPagination(END_POINT.BOOK, { page, size }),
});
return data.items.filter((book) => book.borrowerId === id);
-};
+}
/**
* 도서 대출
*/
-export const postBorrowBook = async (body: BorrowerBookInfo) => {
- const borrowUrl = END_POINT.BOOK_LOAN_BORROW;
- const { data } = await server.post>({
- url: borrowUrl,
+export async function postBorrowBook(body: BookLoanRequestData) {
+ return server.post>({
+ url: END_POINT.BOOK_LOAN_BORROW,
body,
});
-
- return data;
-};
+}
/**
* 도서 반납
*/
-export const postReturnBook = async (body: BorrowerBookInfo) => {
- const { data } = await server.post>({
- url: END_POINT.BOOK_LOAN_RETURN,
- body,
- });
+export async function postReturnBook(body: BookLoanRequestData) {
+ const { data } = await server.post>(
+ {
+ url: END_POINT.BOOK_LOAN_RETURN,
+ body,
+ },
+ );
return data;
-};
+}
/**
* 도서 연장
*/
-export const postExtendBook = async (body: BorrowerBookInfo) => {
- const { data } = await server.post>({
- url: END_POINT.BOOK_LOAN_EXTEND,
- body,
- });
+export async function postExtendBook(body: BookLoanRequestData) {
+ const { data } = await server.post>(
+ {
+ url: END_POINT.BOOK_LOAN_EXTEND,
+ body,
+ },
+ );
return data;
-};
+}
/**
* 도서 대출 내역 조회
*/
-export const getBookLoanRecordConditions = async ({
+export async function getBookLoanRecordConditions({
bookId,
borrowerId,
isReturned,
page = 0,
size = 20,
-}: GetBookLoanRecordConditionsPrams) => {
+}: BookLoanRecordSearchOptions) {
const { data } = await server.get<
PaginationType
>({
@@ -114,14 +112,14 @@ export const getBookLoanRecordConditions = async ({
});
return data;
-};
+}
/**
* 도서 연체자 조회
*/
-export const getBookLoanRecordOverdue = async ({
+export async function getBookLoanRecordOverdue({
page,
size,
-}: WithPaginationPrams) => {
+}: WithPaginationPrams) {
const { data } = await server.get<
PaginationType
>({
@@ -132,4 +130,12 @@ export const getBookLoanRecordOverdue = async ({
});
return data;
-};
+}
+/**
+ * 도서 대출 승인
+ */
+export async function patchBookLoanRecordApprove(id: number) {
+ return server.patch>({
+ url: createPath(END_POINT.BOOK_LOAN_RECORD_APPROVE, id),
+ });
+}
diff --git a/apps/member/src/components/library/BookDetailSection/BookDetailSection.tsx b/apps/member/src/components/library/BookDetailSection/BookDetailSection.tsx
index 5afd8eed..7e590bd0 100644
--- a/apps/member/src/components/library/BookDetailSection/BookDetailSection.tsx
+++ b/apps/member/src/components/library/BookDetailSection/BookDetailSection.tsx
@@ -8,8 +8,7 @@ import Section from '@components/common/Section/Section';
import { BOOK_STORE_URL } from '@constants/path';
import { SELECT_DEFAULT_OPTION } from '@constants/select';
import { BOOK_STATE } from '@constants/state';
-import { useBookLoanBorrowMutation } from '@hooks/queries/useBookLoanBorrowMutation';
-import { useMyProfile } from '@hooks/queries/useMyProfile';
+import { useBookLoanBorrowMutation, useMyProfile } from '@hooks/queries';
import { createImageUrl } from '@utils/api';
import { bookReviewParser, toBookstore } from '@utils/string';
@@ -69,7 +68,7 @@ const BookDetailSection = ({ data }: BookDetailSectionProps) => {
const handleTabsChange = (value: string) => {
const bookStore = toBookstore(value as BookstoreKorean);
const url = bookReviewParser(reviewLinks);
- const targetUrl = url[bookStore] || `${BOOK_STORE_URL[bookStore]}${title}`;
+ const targetUrl = url[bookStore] ?? `${BOOK_STORE_URL[bookStore]}${title}`;
window.open(targetUrl, '_blank');
};
diff --git a/apps/member/src/components/panels/BookPanel/BookPanel.tsx b/apps/member/src/components/panels/BookPanel/BookPanel.tsx
index 45bef1c3..d420bf31 100644
--- a/apps/member/src/components/panels/BookPanel/BookPanel.tsx
+++ b/apps/member/src/components/panels/BookPanel/BookPanel.tsx
@@ -5,9 +5,11 @@ import ProgressBar from '@components/common/ProgressBar/ProgressBar';
import Select from '@components/common/Select/Select';
import useModal from '@hooks/common/useModal';
-import { useBookLoanRecordConditions } from '@hooks/queries';
-import { useBookLoanExtendMutation } from '@hooks/queries/useBookLoanExtendMutation';
-import { useBookLoanReturnMutation } from '@hooks/queries/useBookLoanReturnMutation';
+import {
+ useBookLoanExtendMutation,
+ useBookLoanRecordConditions,
+ useBookLoanReturnMutation,
+} from '@hooks/queries';
import { checkDueDate, checkExtendProgress } from '@utils/date';
import { BookItem } from '@type/book';
diff --git a/apps/member/src/hooks/queries/book-loan-record/index.ts b/apps/member/src/hooks/queries/book-loan-record/index.ts
new file mode 100644
index 00000000..d187aec1
--- /dev/null
+++ b/apps/member/src/hooks/queries/book-loan-record/index.ts
@@ -0,0 +1,6 @@
+export * from './useBookLoanBorrowMutation';
+export * from './useBookLoanExtendMutation';
+export * from './useBookLoanRecordApproveMutation';
+export * from './useBookLoanRecordConditions';
+export * from './useBookLoanRecordOverdue';
+export * from './useBookLoanReturnMutation';
diff --git a/apps/member/src/hooks/queries/useBookLoanBorrowMutation.tsx b/apps/member/src/hooks/queries/book-loan-record/useBookLoanBorrowMutation.ts
similarity index 56%
rename from apps/member/src/hooks/queries/useBookLoanBorrowMutation.tsx
rename to apps/member/src/hooks/queries/book-loan-record/useBookLoanBorrowMutation.ts
index dd685803..b50d2c1a 100644
--- a/apps/member/src/hooks/queries/useBookLoanBorrowMutation.tsx
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanBorrowMutation.ts
@@ -1,53 +1,52 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { postBorrowBook } from '@api/book';
+import { HTTP_ERROR_MESSAGE } from '@constants/api';
import { QUERY_KEY } from '@constants/key';
+import { ERROR_MESSAGE } from '@constants/message';
import useToast from '@hooks/common/useToast';
/**
* 도서 대출을 요청합니다.
*/
-export const useBookLoanBorrowMutation = () => {
+export function useBookLoanBorrowMutation() {
const queryClient = useQueryClient();
const toast = useToast();
const bookBorrowMutation = useMutation({
mutationFn: postBorrowBook,
- onSuccess: (data, variables) => {
- if (data) {
+ onSuccess: ({ success, errorMessage }, { bookId, borrowerId }) => {
+ if (success) {
queryClient.invalidateQueries({
- queryKey: [QUERY_KEY.BOOK_DETAIL, variables.bookId],
+ queryKey: [QUERY_KEY.BOOK_DETAIL, bookId],
});
queryClient.invalidateQueries({
- queryKey: [
- QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS,
- variables.borrowerId,
- ],
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, bookId],
});
queryClient.invalidateQueries({
- queryKey: [QUERY_KEY.MY_BOOK, variables.borrowerId],
+ queryKey: [QUERY_KEY.MY_BOOK, borrowerId],
});
queryClient.invalidateQueries({
- queryKey: [QUERY_KEY.BOOK_LOAN_RECORD, variables.borrowerId],
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD, borrowerId],
});
toast({
state: 'success',
- message: '성공적으로 도서를 대출했습니다.',
+ message: '해당 도서를 대여 신청했어요.',
});
- } else {
+ } else if (errorMessage) {
toast({
state: 'error',
- message: '도서 대출에 실패했습니다.',
+ message: HTTP_ERROR_MESSAGE[errorMessage],
});
}
},
onError: () => {
toast({
state: 'error',
- message: '도서 대출에 실패했습니다.',
+ message: ERROR_MESSAGE.NETWORK,
});
},
});
return { bookBorrowMutate: bookBorrowMutation.mutate };
-};
+}
diff --git a/apps/member/src/hooks/queries/useBookLoanExtendMutation.tsx b/apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts
similarity index 82%
rename from apps/member/src/hooks/queries/useBookLoanExtendMutation.tsx
rename to apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts
index 92ae0dce..9cfa2e9a 100644
--- a/apps/member/src/hooks/queries/useBookLoanExtendMutation.tsx
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts
@@ -7,7 +7,7 @@ import useToast from '@hooks/common/useToast';
/**
* 대출한 도서를 연장합니다.
*/
-export const useBookLoanExtendMutation = () => {
+export function useBookLoanExtendMutation() {
const queryClient = useQueryClient();
const toast = useToast();
@@ -26,16 +26,16 @@ export const useBookLoanExtendMutation = () => {
});
toast({
state: 'success',
- message: '성공적으로 연장되었습니다.',
+ message: '해당 도서 대여 기간을 연장했어요.',
});
} else {
toast({
state: 'error',
- message: '대여 연장은 최대 2회까지 가능합니다.',
+ message: '도서 대여 연장은 최대 2회까지 가능해요.',
});
}
},
});
return { bookExtendMutate: bookExtendMutation.mutate };
-};
+}
diff --git a/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts
new file mode 100644
index 00000000..768291d8
--- /dev/null
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts
@@ -0,0 +1,30 @@
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+
+import { patchBookLoanRecordApprove } from '@api/book';
+import { QUERY_KEY } from '@constants/key';
+import useToast from '@hooks/common/useToast';
+
+/**
+ * 도서 대여를 승인합니다.
+ */
+export function useBookLoanRecordApproveMutation() {
+ const queryClient = useQueryClient();
+ const toast = useToast();
+
+ const bookLoanRecordApprove = useMutation({
+ mutationFn: patchBookLoanRecordApprove,
+ onSuccess: (data, variables) => {
+ if (data.success) {
+ queryClient.invalidateQueries({
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, variables],
+ });
+ toast({
+ state: 'success',
+ message: '해당 도서 대여를 승인했어요, 대여자에게 안내를 해주세요.',
+ });
+ }
+ },
+ });
+
+ return { bookLoanRecordApproveMutate: bookLoanRecordApprove.mutate };
+}
diff --git a/apps/member/src/hooks/queries/useBookLoanRecordConditions.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts
similarity index 80%
rename from apps/member/src/hooks/queries/useBookLoanRecordConditions.ts
rename to apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts
index c8344990..57ba9e51 100644
--- a/apps/member/src/hooks/queries/useBookLoanRecordConditions.ts
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts
@@ -14,13 +14,13 @@ interface UseBookLoanRecordConditionsPrams extends PaginationPramsType {
/**
* 도서 대출 내역을 조회합니다.
*/
-export const useBookLoanRecordConditions = ({
+export function useBookLoanRecordConditions({
bookId,
borrowerId,
isReturned,
page = 0,
size = 20,
-}: UseBookLoanRecordConditionsPrams) => {
+}: UseBookLoanRecordConditionsPrams) {
return useSuspenseQuery({
queryFn: () =>
getBookLoanRecordConditions({
@@ -30,6 +30,6 @@ export const useBookLoanRecordConditions = ({
page,
size,
}),
- queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, borrowerId, size],
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, bookId],
});
-};
+}
diff --git a/apps/member/src/hooks/queries/useBookLoanRecordOverdue.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordOverdue.ts
similarity index 85%
rename from apps/member/src/hooks/queries/useBookLoanRecordOverdue.ts
rename to apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordOverdue.ts
index 00851ee4..52da606e 100644
--- a/apps/member/src/hooks/queries/useBookLoanRecordOverdue.ts
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordOverdue.ts
@@ -10,10 +10,10 @@ interface UseBookLoanRecordOverduePrams extends WithPaginationPrams {}
/**
* 도서 연체자를 조회합니다.
*/
-export const useBookLoanRecordOverdue = ({
+export function useBookLoanRecordOverdue({
page = 0,
size = 20,
-}: UseBookLoanRecordOverduePrams = {}) => {
+}: UseBookLoanRecordOverduePrams = {}) {
return useSuspenseQuery({
queryFn: () =>
getBookLoanRecordOverdue({
@@ -22,4 +22,4 @@ export const useBookLoanRecordOverdue = ({
}),
queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_OVERDUE, { page, size }],
});
-};
+}
diff --git a/apps/member/src/hooks/queries/useBookLoanReturnMutation.tsx b/apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts
similarity index 84%
rename from apps/member/src/hooks/queries/useBookLoanReturnMutation.tsx
rename to apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts
index 33363124..f891fb64 100644
--- a/apps/member/src/hooks/queries/useBookLoanReturnMutation.tsx
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts
@@ -2,12 +2,13 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import { postReturnBook } from '@api/book';
import { QUERY_KEY } from '@constants/key';
+import { ERROR_MESSAGE } from '@constants/message';
import useToast from '@hooks/common/useToast';
/**
* 대출한 도서를 반납합니다.
*/
-export const useBookLoanReturnMutation = () => {
+export function useBookLoanReturnMutation() {
const queryClient = useQueryClient();
const toast = useToast();
@@ -29,16 +30,16 @@ export const useBookLoanReturnMutation = () => {
});
toast({
state: 'success',
- message: '정상적으로 반납이 되었습니다.',
+ message: '도서 대여가 반납되었어요.',
});
} else {
toast({
state: 'error',
- message: '반납에 실패했습니다.',
+ message: ERROR_MESSAGE.NETWORK,
});
}
},
});
return { bookReturnMutate: bookReturnMutation.mutate };
-};
+}
diff --git a/apps/member/src/hooks/queries/index.ts b/apps/member/src/hooks/queries/index.ts
index 91cf3e4a..f8c3851c 100644
--- a/apps/member/src/hooks/queries/index.ts
+++ b/apps/member/src/hooks/queries/index.ts
@@ -35,4 +35,4 @@ export * from './useScheduleAddMutation';
export * from './useScheduleDeleteMutation';
export * from './useUserInfoMutation';
export * from './useActivityGroupMemberMy';
-export * from './useBookLoanRecordConditions';
+export * from './book-loan-record';
diff --git a/apps/member/src/pages/MyPage/MyPage.tsx b/apps/member/src/pages/MyPage/MyPage.tsx
index f1591723..f936532b 100644
--- a/apps/member/src/pages/MyPage/MyPage.tsx
+++ b/apps/member/src/pages/MyPage/MyPage.tsx
@@ -8,12 +8,12 @@ import MyProfileSection from '@components/my/MyProfileSection/MyProfileSection';
import {
useActivityGroupMemberMy,
+ useBookLoanRecordConditions,
useMembershipFee,
useMyBoards,
useMyComments,
useMyNotifications,
} from '@hooks/queries';
-import { useBookLoanRecordConditions } from '@hooks/queries/useBookLoanRecordConditions';
import { useMyProfile } from '@hooks/queries/useMyProfile';
const MyPage = () => {
From d118ea7b78b1ce18e1c06f46835a596fe6b1cbae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:13:46 +0900
Subject: [PATCH 05/11] =?UTF-8?q?refactor(member):=20=EB=8F=84=EC=84=9C=20?=
=?UTF-8?q?=EB=8C=80=EC=97=AC=20=EC=8A=B9=EC=9D=B8=20=EC=A0=88=EC=B0=A8=20?=
=?UTF-8?q?=EC=B6=94=EA=B0=80=20(#112)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ManageLibrarySection.tsx | 39 ++++++++++++++-----
apps/member/src/constants/head.ts | 2 +-
.../useBookLoanRecordApproveMutation.ts | 14 +++++--
apps/member/src/types/book.ts | 15 +++++--
4 files changed, 52 insertions(+), 18 deletions(-)
diff --git a/apps/member/src/components/manage/ManageLibrarySection/ManageLibrarySection.tsx b/apps/member/src/components/manage/ManageLibrarySection/ManageLibrarySection.tsx
index aafd4a06..8fb032a7 100644
--- a/apps/member/src/components/manage/ManageLibrarySection/ManageLibrarySection.tsx
+++ b/apps/member/src/components/manage/ManageLibrarySection/ManageLibrarySection.tsx
@@ -1,17 +1,21 @@
import { useCallback, useState } from 'react';
-import { Badge, Menubar, MenubarItem, Table } from '@clab/design-system';
+import { Menubar, MenubarItem, Table } from '@clab/design-system';
import ActionButton from '@components/common/ActionButton/ActionButton';
import Pagination from '@components/common/Pagination/Pagination';
import { Section } from '@components/common/Section';
+import BookLoanConditionStatusBadge from '@components/library/BookLoanConditionStatusBadge/BookLoanConditionStatusBadge';
import MemberInfoModal from '@components/modal/MemberInfoModal/MemberInfoModal';
import { TABLE_HEAD } from '@constants/head';
import useModal from '@hooks/common/useModal';
import { usePagination } from '@hooks/common/usePagination';
-import { useBookLoanRecordConditions } from '@hooks/queries';
-import { useBookLoanRecordOverdue } from '@hooks/queries/useBookLoanRecordOverdue';
+import {
+ useBookLoanRecordApproveMutation,
+ useBookLoanRecordConditions,
+ useBookLoanRecordOverdue,
+} from '@hooks/queries';
import { calculateDDay, formattedDate } from '@utils/date';
type Mode = 'condition' | 'overdue';
@@ -22,6 +26,7 @@ const ManageLibrarySection = () => {
const [mode, setMode] = useState('condition');
+ const { bookLoanRecordApproveMutate } = useBookLoanRecordApproveMutation();
const { data: bookLoanRecordCondition } = useBookLoanRecordConditions({
isReturned: false,
page,
@@ -34,6 +39,13 @@ const ManageLibrarySection = () => {
const handleMenubarItemClick = useCallback((mode: Mode) => setMode(mode), []);
+ const handleApproveButtonClick = useCallback(
+ (id: number) => {
+ bookLoanRecordApproveMutate(id);
+ },
+ [bookLoanRecordApproveMutate],
+ );
+
const handleContactButtonClick = useCallback(
(id: string) => {
return openModal({
@@ -46,9 +58,10 @@ const ManageLibrarySection = () => {
const renderMode = {
condition: (
-
+
{bookLoanRecordCondition.items.map(
({
+ bookLoanRecordId,
bookTitle,
borrowerId,
borrowerName,
@@ -56,17 +69,25 @@ const ManageLibrarySection = () => {
borrowedAt,
returnedAt,
}) => (
-
+
{bookTitle}
{`${borrowerName} (${borrowerId})`}
{formattedDate(borrowedAt)}
{formattedDate(dueDate)}
-
- {returnedAt ? '반납완료' : '대여중'}
-
+
-
+
+ {dueDate === null && (
+ handleApproveButtonClick(bookLoanRecordId)}
+ >
+ 승인
+
+ )}
handleContactButtonClick(borrowerId)}
>
diff --git a/apps/member/src/constants/head.ts b/apps/member/src/constants/head.ts
index 3cae4606..6ee77215 100644
--- a/apps/member/src/constants/head.ts
+++ b/apps/member/src/constants/head.ts
@@ -2,7 +2,7 @@ export const TABLE_HEAD = {
ACTIVITY_GROUP_PARTICIPANTS: ['번호', '학번', '이름'],
ACTIVITY_GROUP_APPLIES: ['번호', '학번', '이름', '상태', '기능'],
SUPPORT_HISTORY: ['번호', '상태', '구분', '요청자', '신청일'],
- BOOK_LOAN_RECORD: ['대여자', '대여일', '반납 예정일', '상태', '기능'],
+ BOOK_LOAN_RECORD: ['대여자', '대여일', '반납 예정일', '상태'],
COMMUNITY_DETAIL: ['번호', '제목', '작성자', '작성일'],
BOOK_LOAN_RECORDS_OVERDUE: [
'도서명',
diff --git a/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts
index 768291d8..9c404c06 100644
--- a/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordApproveMutation.ts
@@ -1,6 +1,7 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { patchBookLoanRecordApprove } from '@api/book';
+import { HTTP_ERROR_MESSAGE } from '@constants/api';
import { QUERY_KEY } from '@constants/key';
import useToast from '@hooks/common/useToast';
@@ -13,15 +14,20 @@ export function useBookLoanRecordApproveMutation() {
const bookLoanRecordApprove = useMutation({
mutationFn: patchBookLoanRecordApprove,
- onSuccess: (data, variables) => {
- if (data.success) {
+ onSuccess: ({ success, errorMessage }) => {
+ if (success) {
queryClient.invalidateQueries({
- queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, variables],
+ queryKey: [QUERY_KEY.MY_BOOK],
+ });
+ queryClient.invalidateQueries({
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS],
});
toast({
state: 'success',
- message: '해당 도서 대여를 승인했어요, 대여자에게 안내를 해주세요.',
+ message: '해당 도서 대여를 승인했어요.',
});
+ } else if (errorMessage) {
+ toast({ state: 'error', message: HTTP_ERROR_MESSAGE[errorMessage] });
}
},
});
diff --git a/apps/member/src/types/book.ts b/apps/member/src/types/book.ts
index 24dfbcd2..ceee5080 100644
--- a/apps/member/src/types/book.ts
+++ b/apps/member/src/types/book.ts
@@ -1,6 +1,12 @@
export type Bookstore = 'kyobobook' | 'yes24' | 'aladin';
export type BookstoreKorean = '교보문고' | '예스24' | '알라딘';
+export type BookConditionStatus =
+ | 'PENDING'
+ | 'APPROVED'
+ | 'REJECTED'
+ | 'RETURNED';
+
export interface BookItem {
id: number;
borrowerId: string | null;
@@ -17,16 +23,17 @@ export interface BookItem {
}
export interface BookLoanRecordConditionType {
+ bookLoanRecordId: number;
bookId: number;
borrowerId: string;
borrowerName: string;
- dueDate: string;
- borrowedAt: string;
- returnedAt: string | null;
+ dueDate: string | null;
bookTitle: string;
bookImageUrl: string;
+ borrowedAt: string | null;
+ returnedAt: string | null;
loanExtensionCount: number | null;
- loanExtensionDate?: string;
+ status: BookConditionStatus;
}
export interface BookLoanRecordOverDueResponse {
From c41ff81916480e05d4eef1417bd32e56002a5705 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:22:54 +0900
Subject: [PATCH 06/11] feat(member): add BookLoanConditionStatusBadge
Component (#112)
---
.../BookLoanConditionStatusBadge.tsx | 22 +++++++++++
.../BookLoanHistorySection.tsx | 39 +++++++++++--------
2 files changed, 44 insertions(+), 17 deletions(-)
create mode 100644 apps/member/src/components/library/BookLoanConditionStatusBadge/BookLoanConditionStatusBadge.tsx
diff --git a/apps/member/src/components/library/BookLoanConditionStatusBadge/BookLoanConditionStatusBadge.tsx b/apps/member/src/components/library/BookLoanConditionStatusBadge/BookLoanConditionStatusBadge.tsx
new file mode 100644
index 00000000..750bcb83
--- /dev/null
+++ b/apps/member/src/components/library/BookLoanConditionStatusBadge/BookLoanConditionStatusBadge.tsx
@@ -0,0 +1,22 @@
+import { Badge, BadgeColorType } from '@clab/design-system';
+
+import type { BookLoanRecordConditionType } from '@type/book';
+
+interface BookLoanConditionStatusBadgeProps
+ extends Pick {}
+
+const BookLoanConditionStatusBadge = ({
+ borrowedAt,
+ returnedAt,
+}: BookLoanConditionStatusBadgeProps) => {
+ const text = !borrowedAt ? '대기' : !returnedAt ? '대여중' : '반납완료';
+ const color: BadgeColorType = !borrowedAt
+ ? 'red'
+ : !returnedAt
+ ? 'yellow'
+ : 'green';
+
+ return {text};
+};
+
+export default BookLoanConditionStatusBadge;
diff --git a/apps/member/src/components/library/BookLoanHistorySection/BookLoanHistorySection.tsx b/apps/member/src/components/library/BookLoanHistorySection/BookLoanHistorySection.tsx
index dcd27ad0..d2b1d9cb 100644
--- a/apps/member/src/components/library/BookLoanHistorySection/BookLoanHistorySection.tsx
+++ b/apps/member/src/components/library/BookLoanHistorySection/BookLoanHistorySection.tsx
@@ -1,4 +1,4 @@
-import { Badge, Table } from '@clab/design-system';
+import { Table } from '@clab/design-system';
import Section from '@components/common/Section/Section';
@@ -6,6 +6,8 @@ import { TABLE_HEAD } from '@constants/head';
import { useBookLoanRecordConditions } from '@hooks/queries';
import { formattedDate } from '@utils/date';
+import BookLoanConditionStatusBadge from '../BookLoanConditionStatusBadge/BookLoanConditionStatusBadge';
+
interface BookLoanHistorySectionProps {
id: number;
}
@@ -18,22 +20,25 @@ const BookLoanHistorySection = ({ id }: BookLoanHistorySectionProps) => {
- {data.items.map(({ borrowerId, dueDate, borrowedAt, returnedAt }) => (
-
- {borrowerId}
- {formattedDate(borrowedAt)}
-
- {returnedAt
- ? formattedDate(returnedAt)
- : `${formattedDate(dueDate)} (예정)`}
-
-
-
- {returnedAt ? '반납완료' : '대여중'}
-
-
-
- ))}
+ {data.items.map(
+ ({ borrowerName, borrowerId, dueDate, borrowedAt, returnedAt }) => (
+
+ {`${borrowerName} (${borrowerId})`}
+ {formattedDate(borrowedAt)}
+
+ {returnedAt
+ ? formattedDate(returnedAt)
+ : formattedDate(dueDate)}
+
+
+
+
+
+ ),
+ )}
From 47a8923f46412097a52f7bd3a4ffc2a9cd60bf33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:25:15 +0900
Subject: [PATCH 07/11] refactor(member): handle null and undefined values in
`formattedDate` (#112)
---
apps/member/src/utils/date.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/apps/member/src/utils/date.ts b/apps/member/src/utils/date.ts
index 12dcfee2..260772c8 100644
--- a/apps/member/src/utils/date.ts
+++ b/apps/member/src/utils/date.ts
@@ -35,10 +35,11 @@ export function calculateDDay(date: string): number {
/**
* 주어진 날짜를 'YY.MM.DD(dd) HH:mm' 형식으로 포맷합니다.
*
- * @param {Date|string|number} date - 포맷할 날짜. Date 객체, 문자열 또는 타임스탬프일 수 있습니다.
+ * @param {string | undefined | null} date - 포맷할 날짜. Date 객체, 문자열 또는 타임스탬프일 수 있습니다.
* @returns {string} 포맷된 날짜 문자열.
*/
-export function formattedDate(date: string | undefined): string {
+export function formattedDate(date: string | undefined | null): string {
+ if (!date) return '-';
return dayjs(date).format('YY.MM.DD(dd) HH:mm');
}
/**
From f0f1c5fd8bc090998aaea95fe86a120ff20c70ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:26:40 +0900
Subject: [PATCH 08/11] =?UTF-8?q?refactor(member):=20=EB=8F=84=EC=84=9C=20?=
=?UTF-8?q?=EB=8C=80=EC=97=AC=20=EA=B4=80=EB=A0=A8=20=EC=BF=BC=EB=A6=AC?=
=?UTF-8?q?=ED=82=A4=20=EB=AC=B4=ED=9A=A8=20=EA=B0=9C=EC=84=A0=20(#112)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../useBookLoanExtendMutation.ts | 16 +++++++---------
.../useBookLoanRecordConditions.ts | 2 +-
.../useBookLoanReturnMutation.ts | 3 +++
3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts
index 9cfa2e9a..11641978 100644
--- a/apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanExtendMutation.ts
@@ -1,6 +1,7 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { postExtendBook } from '@api/book';
+import { HTTP_ERROR_MESSAGE } from '@constants/api';
import { QUERY_KEY } from '@constants/key';
import useToast from '@hooks/common/useToast';
@@ -13,25 +14,22 @@ export function useBookLoanExtendMutation() {
const bookExtendMutation = useMutation({
mutationFn: postExtendBook,
- onSuccess: (data, variables) => {
- if (data) {
+ onSuccess: ({ success, errorMessage }, { borrowerId }) => {
+ if (success) {
queryClient.invalidateQueries({
- queryKey: [QUERY_KEY.MY_BOOK, variables.borrowerId],
+ queryKey: [QUERY_KEY.MY_BOOK, borrowerId],
});
queryClient.invalidateQueries({
- queryKey: [
- QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS,
- variables.borrowerId,
- ],
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, borrowerId],
});
toast({
state: 'success',
message: '해당 도서 대여 기간을 연장했어요.',
});
- } else {
+ } else if (errorMessage) {
toast({
state: 'error',
- message: '도서 대여 연장은 최대 2회까지 가능해요.',
+ message: HTTP_ERROR_MESSAGE[errorMessage],
});
}
},
diff --git a/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts
index 57ba9e51..b73ace76 100644
--- a/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanRecordConditions.ts
@@ -30,6 +30,6 @@ export function useBookLoanRecordConditions({
page,
size,
}),
- queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, bookId],
+ queryKey: [QUERY_KEY.BOOK_LOAN_RECORD_CONDITIONS, bookId || borrowerId],
});
}
diff --git a/apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts b/apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts
index f891fb64..7a0e517f 100644
--- a/apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts
+++ b/apps/member/src/hooks/queries/book-loan-record/useBookLoanReturnMutation.ts
@@ -16,6 +16,9 @@ export function useBookLoanReturnMutation() {
mutationFn: postReturnBook,
onSuccess: (data, variables) => {
if (data) {
+ queryClient.invalidateQueries({
+ queryKey: [QUERY_KEY.BOOK],
+ });
queryClient.invalidateQueries({
queryKey: [QUERY_KEY.BOOK_DETAIL, variables.bookId],
});
From cbc3d310c48019cc540d93139d27d54aca5318f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:28:13 +0900
Subject: [PATCH 09/11] =?UTF-8?q?refactor(member):=20=EC=BD=94=EB=93=9C=20?=
=?UTF-8?q?=EB=B6=88=EC=9D=BC=EC=B9=98=20=EA=B0=9C=EC=84=A0=20(#112)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/member/src/api/book.ts | 16 ++++++----------
.../LibraryDetailPage/LibraryDetailPage.tsx | 5 +++--
apps/member/src/types/api.ts | 9 +++++----
3 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/apps/member/src/api/book.ts b/apps/member/src/api/book.ts
index 246a02a4..4c85e2ba 100644
--- a/apps/member/src/api/book.ts
+++ b/apps/member/src/api/book.ts
@@ -79,15 +79,11 @@ export async function postReturnBook(body: BookLoanRequestData) {
/**
* 도서 연장
*/
-export async function postExtendBook(body: BookLoanRequestData) {
- const { data } = await server.post>(
- {
- url: END_POINT.BOOK_LOAN_EXTEND,
- body,
- },
- );
-
- return data;
+export function postExtendBook(body: BookLoanRequestData) {
+ return server.post>({
+ url: END_POINT.BOOK_LOAN_EXTEND,
+ body,
+ });
}
/**
* 도서 대출 내역 조회
@@ -134,7 +130,7 @@ export async function getBookLoanRecordOverdue({
/**
* 도서 대출 승인
*/
-export async function patchBookLoanRecordApprove(id: number) {
+export function patchBookLoanRecordApprove(id: number) {
return server.patch>({
url: createPath(END_POINT.BOOK_LOAN_RECORD_APPROVE, id),
});
diff --git a/apps/member/src/pages/LibraryDetailPage/LibraryDetailPage.tsx b/apps/member/src/pages/LibraryDetailPage/LibraryDetailPage.tsx
index 2ad4b257..afbb7a25 100644
--- a/apps/member/src/pages/LibraryDetailPage/LibraryDetailPage.tsx
+++ b/apps/member/src/pages/LibraryDetailPage/LibraryDetailPage.tsx
@@ -6,6 +6,7 @@ import BookDetailSection from '@components/library/BookDetailSection/BookDetailS
import BookLoanHistorySection from '@components/library/BookLoanHistorySection/BookLoanHistorySection';
import { LIBRARY_MESSAGE } from '@constants/message';
+import { PATH } from '@constants/path';
import { useBookDetails } from '@hooks/queries/useBookDetails';
const LibraryDetailPage = () => {
@@ -19,9 +20,9 @@ const LibraryDetailPage = () => {
return (
-
+
-
+
);
};
diff --git a/apps/member/src/types/api.ts b/apps/member/src/types/api.ts
index 1c42a17f..72843cd4 100644
--- a/apps/member/src/types/api.ts
+++ b/apps/member/src/types/api.ts
@@ -1,6 +1,9 @@
+import { HTTP_ERROR_MESSAGE } from '@constants/api';
+
export interface BaseResponse {
success: boolean;
data: T;
+ errorMessage?: keyof typeof HTTP_ERROR_MESSAGE;
}
export interface Pagination {
@@ -22,11 +25,9 @@ export interface PaginationPramsType {
}
/**
* `PaginationPramsType`를 대체하기 위한 페이지네이션 파라미터 타입입니다.
+ * `PaginationPramsType`를 대체하고 삭제해주세요. -> Params를 Options로 변경
*/
-export interface WithPaginationPrams {
- page?: number;
- size?: number;
-}
+export interface WithPaginationPrams extends PaginationPramsType {}
export type IDType = string | number;
From b345ff7fb908a6a06f1feea23fbd878292233877 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:28:39 +0900
Subject: [PATCH 10/11] =?UTF-8?q?feat(member):=20=ED=86=B5=EC=8B=A0=20?=
=?UTF-8?q?=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=B6=94?=
=?UTF-8?q?=EA=B0=80=20(#112)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/member/src/constants/api.ts | 10 ++++++++++
apps/member/src/constants/message.ts | 1 +
2 files changed, 11 insertions(+)
diff --git a/apps/member/src/constants/api.ts b/apps/member/src/constants/api.ts
index cb35598e..8f6e718a 100644
--- a/apps/member/src/constants/api.ts
+++ b/apps/member/src/constants/api.ts
@@ -31,6 +31,7 @@ export const END_POINT = {
BOOK_LOAN_EXTEND: `/v1/book-loan-records/extend`,
BOOK_LOAN_RETURN: `/v1/book-loan-records/return`,
BOOK_LOAN_OVERDUE: `/v1/book-loan-records/overdue`,
+ BOOK_LOAN_RECORD_APPROVE: `/v1/book-loan-records/approve`,
// -- 블로그
BLOG: `/v1/blogs`,
BLOG_DETAIL: (id: number) => `/v1/blogs/${id}`,
@@ -87,3 +88,12 @@ export const HTTP_STATUS_CODE = {
INTERNAL_SERVER_ERROR: 500,
CLAB_AUTH_SUCCESS: 1200,
} as const;
+/**
+ * 에러 발생에 대한 사용자에게 안내할 메세지를 정의합니다.
+ * Server팀과 협의하여 정의합니다.
+ */
+export const HTTP_ERROR_MESSAGE = {
+ BOOKALREADYAPPLIEDFORLOANEXCEPTION: '이미 대여 신청한 도서이에요.',
+ BOOKALREADYBORROWEDEXCEPTION: '해당 도서는 대여 상태에요.',
+ OVERDUEEXCEPTION: '도서 대여 연장은 최대 2회까지 가능해요.',
+} as const;
diff --git a/apps/member/src/constants/message.ts b/apps/member/src/constants/message.ts
index f8a9d7cb..8e4b7dfd 100644
--- a/apps/member/src/constants/message.ts
+++ b/apps/member/src/constants/message.ts
@@ -1,5 +1,6 @@
export const ERROR_MESSAGE = {
DEFAULT: '오류가 발생했어요. 잠시후에 다시 시도해주세요.',
+ NETWORK: '네트워크 오류가 발생했어요. 잠시후에 다시 시도해주세요.',
NOT_FOUND: '잘못된 접근이에요.',
NO_FILE: '파일이 없어요.',
NO_DATA: '모든 항목을 입력해주세요.',
From 7fcafe37d72396e0516b234150954add55916110 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?=
<39869096+gwansikk@users.noreply.github.com>
Date: Sat, 27 Apr 2024 02:29:28 +0900
Subject: [PATCH 11/11] =?UTF-8?q?refactor(member):=20image=20component=20?=
=?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0=20(#112)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/common/Image/Image.tsx | 54 +++++++++----------
.../LibraryNewBooksSection.tsx | 12 +++--
2 files changed, 34 insertions(+), 32 deletions(-)
diff --git a/apps/member/src/components/common/Image/Image.tsx b/apps/member/src/components/common/Image/Image.tsx
index ecfa4ab5..845374a6 100644
--- a/apps/member/src/components/common/Image/Image.tsx
+++ b/apps/member/src/components/common/Image/Image.tsx
@@ -1,59 +1,57 @@
-import { SyntheticEvent, useState } from 'react';
+import { ComponentPropsWithRef, SyntheticEvent, useState } from 'react';
import { NOT_FOUND_IMG } from '@constants/path';
-import classNames from 'classnames';
+import { cn } from '@utils/string';
-interface ImageProps {
- src?: string;
- alt: string;
+interface ImageProps extends ComponentPropsWithRef<'img'> {
width?: string;
height?: string;
- className?: string;
- onClick?: () => void;
overflow?: boolean;
}
+type Status = 'loading' | 'error' | 'loaded';
+
const Image = ({
- src,
- alt,
width,
height,
+ src,
+ overflow,
className,
onClick,
- overflow,
+ ...rest
}: ImageProps) => {
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(false);
-
- if (!src) src = NOT_FOUND_IMG;
+ const [status, setStatus] = useState('loading');
- const _width = width ? width : 'w-full';
- const _height = height ? height : 'h-full';
+ const _width = width ?? 'w-full';
+ const _height = height ?? 'h-full';
const handleError = (e: SyntheticEvent) => {
e.currentTarget.src = NOT_FOUND_IMG;
- setError(true);
- setLoading(false);
+ setStatus('error');
};
return (
setLoading(false)}
+ className={cn(
+ {
+ 'animate-pulse bg-gray-200': status === 'loading',
+ 'bg-gray-50': status === 'error',
+ },
+ _width,
+ _height,
+ className,
+ )}
+ src={src ?? NOT_FOUND_IMG}
+ onLoad={() => setStatus('loaded')}
onError={handleError}
loading="lazy"
+ {...rest}
/>
);
diff --git a/apps/member/src/components/library/LibraryNewBooksSection/LibraryNewBooksSection.tsx b/apps/member/src/components/library/LibraryNewBooksSection/LibraryNewBooksSection.tsx
index 6770d0b3..23bd80ae 100644
--- a/apps/member/src/components/library/LibraryNewBooksSection/LibraryNewBooksSection.tsx
+++ b/apps/member/src/components/library/LibraryNewBooksSection/LibraryNewBooksSection.tsx
@@ -23,11 +23,15 @@ const LibraryNewBooksSection = ({ data }: LibraNewBooksSectionProps) => {
-
-
-
+