Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

도서관 사용자 피드백 개선 (OPEN-BETA) #118

Merged
merged 9 commits into from
May 3, 2024
24 changes: 13 additions & 11 deletions apps/member/src/components/library/BookCard/BookCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Image from '@components/common/Image/Image';

import { PATH_FINDER } from '@constants/path';
import { BOOK_STATE } from '@constants/state';
import classNames from 'classnames';
import { cn } from '@utils/string';

import type { BookItem } from '@type/book';

Expand All @@ -28,29 +28,31 @@ const BookCard = ({
<Image
src={imageUrl}
alt={title}
width="w-full"
height="h-[200px]"
className="border-b object-cover transition-transform ease-in-out group-hover:scale-110"
overflow
/>
<div className="flex grow flex-col justify-between p-2 text-sm">
<div>
<p className="font-semibold group-hover:underline">{title}</p>
<p className="text-gray-500">
{author} | {publisher}
<div className="break-keep">
<p className="line-clamp-2 font-semibold group-hover:underline">
{title}
</p>
<div className="text-gray-500">
<p className="line-clamp-1">{author}</p>
<p className="line-clamp-1">{publisher}</p>
</div>
</div>
<div className="mt-2 flex items-center gap-1">
<span
className={classNames(
'h-1.5 w-1.5 rounded-full',
borrowerId ? 'bg-green-600' : 'bg-pink-600',
className={cn(
'size-1.5 rounded-full',
borrowerId ? 'bg-pink-600' : 'bg-green-600',
)}
/>
<span
className={classNames(
className={cn(
'text-xs',
borrowerId ? 'text-green-600' : 'text-pink-600',
borrowerId ? 'text-pink-600' : 'text-green-600',
)}
>
{borrowerId ? BOOK_STATE.BORROWED : BOOK_STATE.AVAILABLE}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,11 @@ const BookDetailSection = ({ data }: BookDetailSectionProps) => {
<Section>
<Grid gap="lg" className="lg:grid-cols-2">
<Image
width="p-4"
src={createImageUrl(imageUrl)}
alt={title}
className="object-cover drop-shadow-lg"
width="w-[420px]"
height="h-[520px]"
className="object-cover p-4 drop-shadow-lg"
/>
<div className="flex flex-col justify-between gap-4">
<div className="space-y-4">
Expand All @@ -94,17 +95,16 @@ const BookDetailSection = ({ data }: BookDetailSectionProps) => {
</Badge>
</DetailsList.Item>
</DetailsList>
<Tabs
value={SELECT_DEFAULT_OPTION}
options={options}
onChange={handleTabsChange}
/>
<div>
<label className="mb-1 ml-1 text-xs">온라인 서점 바로가기</label>
<Tabs
value={SELECT_DEFAULT_OPTION}
options={options}
onChange={handleTabsChange}
/>
</div>
</div>
<Button disabled={!!borrowerId} onClick={() => handleBorrowClick(id)}>
{borrowerId
? '이미 대여된 도서예요! 조금만 기다려주세요'
: '대여하기'}
</Button>
<Button onClick={() => handleBorrowClick(id)}>대여 신청하기</Button>
</div>
</Grid>
</Section>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Badge, BadgeColorType } from '@clab/design-system';

import { BOOK_STATE } from '@constants/state';

import type { BookLoanRecordConditionType } from '@type/book';

interface BookLoanConditionStatusBadgeProps
Expand All @@ -9,7 +11,11 @@ const BookLoanConditionStatusBadge = ({
borrowedAt,
returnedAt,
}: BookLoanConditionStatusBadgeProps) => {
const text = !borrowedAt ? '대기' : !returnedAt ? '대여중' : '반납완료';
const text = !borrowedAt
? BOOK_STATE.WAIT
: !returnedAt
? BOOK_STATE.BORROWED
: BOOK_STATE.RETURN;
const color: BadgeColorType = !borrowedAt
? 'red'
: !returnedAt
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Pagination from '@components/common/Pagination/Pagination';
import { Section } from '@components/common/Section';

import { usePagination } from '@hooks/common/usePagination';
import { useBooks } from '@hooks/queries/book';

import BookCard from '../BookCard/BookCard';

const LibraryBooksSection = () => {
const { page, size, handlePageChange } = usePagination(16);

const { data } = useBooks(page, size);

return (
<Section>
<Section.Header
title="둘러보기"
description="소장 도서를 둘러볼 수 있어요"
/>
<Section.Body>
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
{data.items.map(({ id, ...rest }) => (
<BookCard key={id} id={id} {...rest} />
))}
</div>
<Pagination
className="mt-4 justify-center"
totalItems={data.totalItems}
postLimit={size}
onChange={handlePageChange}
page={page}
/>
</Section.Body>
</Section>
);
};
export default LibraryBooksSection;
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,32 @@ import Image from '@components/common/Image/Image';
import Section from '@components/common/Section/Section';

import { PATH_FINDER } from '@constants/path';
import { useBooks } from '@hooks/queries/book';

import { BookItem } from '@type/book';
const LibraryNewBooksSection = () => {
const { data } = useBooks(0, 4);

interface LibraNewBooksSectionProps {
data: BookItem[];
}

const LibraryNewBooksSection = ({ data }: LibraNewBooksSectionProps) => {
return (
<Section>
<Section.Header
title="신규 도서"
description="최근에 들어온 도서들을 확인해보세요"
/>
<Section.Body className="flex gap-4">
{data.map(({ id, imageUrl, title, author, publisher }) => (
<Section.Body className="grid grid-cols-2 gap-4 md:grid-cols-4">
{data.items.map(({ id, imageUrl, title, author, publisher }) => (
<Link
key={id}
to={PATH_FINDER.BOOK_DETAIL(id)}
className="group relative flex flex-col gap-2 rounded-lg border shadow-lg"
className="group relative flex flex-col gap-2 overflow-hidden rounded-lg border"
>
<Image
src={imageUrl}
alt={title}
width="w-[200px]"
className="rounded-lg object-cover"
overflow
className="rounded-lg object-cover transition-transform group-hover:scale-105"
/>
<div className="pointer-events-none absolute inset-0 rounded-lg bg-gradient-to-t from-black/60 via-black/30 opacity-0 transition-all group-hover:opacity-100" />
<div className="absolute bottom-0 px-2 text-white opacity-0 transition-all group-hover:-translate-y-5 group-hover:opacity-100">
<p className="break-keep font-semibold">{title}</p>
<div className="pointer-events-none absolute inset-0 rounded-lg bg-gradient-to-t from-black/60 via-black/30 opacity-0 group-hover:opacity-100" />
<div className="absolute bottom-0 px-2 text-white opacity-0 transition-transform group-hover:-translate-y-2.5 group-hover:opacity-100">
<p className="line-clamp-2 break-keep font-semibold">{title}</p>
<p className="text-sm">
{author} | {publisher}
</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useCallback } from 'react';

import { Badge } from '@clab/design-system';

import EmptyBox from '@components/common/EmptyBox/EmptyBox';
import ListButton from '@components/common/ListButton/ListButton';
import Section from '@components/common/Section/Section';
import BookLoanConditionStatusBadge from '@components/library/BookLoanConditionStatusBadge/BookLoanConditionStatusBadge';

import { MY_MESSAGE } from '@constants/message';
import { PATH_FINDER } from '@constants/path';
Expand Down Expand Up @@ -67,14 +66,17 @@ const MyHistorySection = ({ title, data }: MyHistorySectionProps) => {
return (
<ListButton key={index} to={PATH_FINDER.BOOK_DETAIL(bookId)}>
<p className="grow space-x-2 truncate pr-4">
<Badge color={returnedAt ? 'green' : 'yellow'}>
{returnedAt ? '반납완료' : '대출중'}
</Badge>
<BookLoanConditionStatusBadge
borrowedAt={borrowedAt}
returnedAt={returnedAt}
/>
<span>{bookTitle}</span>
</p>
<p className="text-clab-main-light">
{toYYMMDD(borrowedAt ?? '')}
</p>
{returnedAt && (
<p className="text-clab-main-light">
{toYYMMDD(returnedAt)}
</p>
)}
</ListButton>
);
}
Expand Down
4 changes: 3 additions & 1 deletion apps/member/src/constants/state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export const BOOK_STATE = {
BORROWED: '대여중',
WAIT: '대기',
AVAILABLE: '대여가능',
BORROWED: '대여중',
RETURN: '반납완료',
} as const;

export const DATE_FORMAT = {
Expand Down
21 changes: 12 additions & 9 deletions apps/member/src/hooks/common/usePagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,32 @@ import { useLocation, useNavigate } from 'react-router-dom';

/**
* 페이지네이션을 위한 페이지 조작 훅입니다.
* Pagination Component와 같이 사용합니다.
*/
export const usePagination = (defaultSize: number = 20) => {
const navigate = useNavigate();
const location = useLocation();
const searchParams = new URLSearchParams(location.search);

const getPage = useCallback(() => {
const searchParams = new URLSearchParams(location.search);
return parseInt(searchParams.get('page') ?? '1', 10) - 1;
}, [location.search]);

const [pagination, setPagination] = useState({
page: parseInt(searchParams.get('page') ?? '1') - 1,
page: getPage(),
size: defaultSize,
});

// 페이지 변경 핸들러
const handlePageChange = useCallback(
(page: number) => {
navigate(`?page=${page}`, { replace: false });
navigate('?page=' + page);
},
[navigate],
);

useEffect(() => {
const page = parseInt(searchParams.get('page') ?? '1', 10) - 1;
setPagination((prev) => ({ ...prev, page }));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.search]);
setPagination((prev) => ({ ...prev, page: getPage() }));
}, [getPage]);

return { page: pagination.page, size: pagination.size, handlePageChange };
return { ...pagination, handlePageChange };
};
2 changes: 2 additions & 0 deletions apps/member/src/hooks/queries/book/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './useBooks';
export * from './useBookDetails';
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { useSuspenseQuery } from '@tanstack/react-query';
import { getBooks } from '@api/book';
import { QUERY_KEY } from '@constants/key';

/**
* 도서 목록을 조회합니다.
*/
export const useBooks = (page = 0, size = 6) => {
return useSuspenseQuery({
queryKey: [QUERY_KEY.BOOK, page, size],
queryKey: [QUERY_KEY.BOOK, { page, size }],
queryFn: () => getBooks(page, size),
});
};
1 change: 1 addition & 0 deletions apps/member/src/hooks/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ export * from './useScheduleDeleteMutation';
export * from './useUserInfoMutation';
export * from './useActivityGroupMemberMy';
export * from './book-loan-record';
export * from './book';
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import BookLoanHistorySection from '@components/library/BookLoanHistorySection/B

import { LIBRARY_MESSAGE } from '@constants/message';
import { PATH } from '@constants/path';
import { useBookDetails } from '@hooks/queries/useBookDetails';
import { useBookDetails } from '@hooks/queries/book';

const LibraryDetailPage = () => {
const { id } = useParams<{ id: string }>();
Expand Down
34 changes: 8 additions & 26 deletions apps/member/src/pages/LibraryPage/LibraryPage.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import { Suspense } from 'react';
import { useNavigate } from 'react-router-dom';

import { Button } from '@clab/design-system';

import Content from '@components/common/Content/Content';
import Header from '@components/common/Header/Header';
import Pagination from '@components/common/Pagination/Pagination';
import Section from '@components/common/Section/Section';
import LibraryBookList from '@components/library/LibraryBookList/LibraryBookList';
import LibraryBooksSection from '@components/library/LibraryBooksSection/LibraryBooksSection';
import LibraryNewBooksSection from '@components/library/LibraryNewBooksSection/LibraryNewBooksSection';

import { PATH } from '@constants/path';
import { usePagination } from '@hooks/common/usePagination';
import { useBooks } from '@hooks/queries/useBooks';

const LibraryPage = () => {
const navigate = useNavigate();
const { page, size, handlePageChange } = usePagination();

const { data: newBookData } = useBooks(0, 4);
const { data: bookData } = useBooks(page, size);

return (
<Content>
Expand All @@ -27,23 +20,12 @@ const LibraryPage = () => {
희망도서 신청하기
</Button>
</Header>
<LibraryNewBooksSection data={newBookData.items} />
<Section>
<Section.Header
title="둘러보기"
description="소장 도서를 둘러볼 수 있어요"
/>
<Section.Body>
<LibraryBookList data={bookData.items} />
<Pagination
className="mt-4 justify-center"
totalItems={bookData.totalItems}
postLimit={size}
onChange={handlePageChange}
page={page}
/>
</Section.Body>
</Section>
<Suspense>
<LibraryNewBooksSection />
</Suspense>
<Suspense>
<LibraryBooksSection />
</Suspense>
</Content>
);
};
Expand Down