Skip to content

Commit 732fdaa

Browse files
committed
feat: 검색 기능 추가
1 parent 722ec2e commit 732fdaa

File tree

2 files changed

+63
-48
lines changed

2 files changed

+63
-48
lines changed

apps/web-client/src/components/books/BookList.tsx

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Empty, Result, Select, Skeleton } from 'antd';
1+
import { Button, Empty, Form, Input, Result, Select, Skeleton } from 'antd';
22
import { match } from 'ts-pattern';
3-
import { useEffect, useMemo, useRef, useState } from 'react';
3+
import { Dispatch, SetStateAction, useEffect, useMemo, useRef, useState } from 'react';
44
import { createStyles } from 'antd-style';
55
import { BookControllerService, BookResponse, queryKey, useAppInfiniteQuery } from '~/lib/api-v2';
66

@@ -121,56 +121,69 @@ const useStyles = createStyles(({ css }) => ({
121121
`,
122122
}));
123123

124-
// const initSearchForm = { type: 'title', query: '' };
125-
// export function BookListSearch({ setSearch }) {
126-
// const { styles } = useStyles();
127-
// const [formInfo, setFormInfo] = useState(initSearchForm);
128-
// return (
129-
// <Form
130-
// initialValues={initSearchForm}
131-
// className={styles.search}
132-
// onFinish={(values) => {
133-
// setSearch(values);
134-
// }}
135-
// onFinishFailed={(error) => {
136-
// console.error('Error: ', error);
137-
// }}
138-
// >
139-
// <Form.Item name="type">
140-
// <Select
141-
// getPopupContainer={(trigger) => trigger.parentNode}
142-
// className={styles.searchSelect}
143-
// // defaultValue={initSearchForm.type}
144-
// options={[
145-
// { value: 'title', label: '제목' },
146-
// { value: 'author', label: '저자' },
147-
// { value: 'tag', label: '태그' },
148-
// ]}
149-
// onChange={(data) => setFormInfo({ ...formInfo, type: data })}
150-
// />
151-
// </Form.Item>
152-
// <Form.Item name="query">
153-
// <Input className={styles.searchInput} value={formInfo.query} onChange={(e) => setFormInfo({ ...formInfo, query: e.target.value })} />
154-
// </Form.Item>
155-
// <Form.Item label={null}>
156-
// <Button className={styles.searchBtn} type="primary" htmlType="submit">
157-
// 검색
158-
// </Button>
159-
// </Form.Item>
160-
// </Form>
161-
// );
162-
// }
163-
164-
const useInView = () => {
124+
const initSearchForm = { type: 'TITLE', keyword: '' };
125+
type sortingType = 'TITLE' | 'CREATED_AT' | 'RENT_TIME';
126+
type searchType = 'TITLE' | 'AUTHOR' | 'TAG';
127+
128+
export function BookListSearch({ setSearchInfo }: { setSearchInfo: Dispatch<SetStateAction<{ type: searchType; keyword: string }>> }) {
129+
const { styles } = useStyles();
130+
const [formInfo, setFormInfo] = useState(initSearchForm);
131+
132+
return (
133+
<Form
134+
initialValues={initSearchForm}
135+
className={styles.search}
136+
onFinish={(values) => {
137+
setSearchInfo(values);
138+
}}
139+
onFinishFailed={(error) => {
140+
console.error('Error: ', error);
141+
}}
142+
>
143+
<Form.Item name="type">
144+
<Select
145+
getPopupContainer={(trigger) => trigger.parentNode}
146+
className={styles.searchSelect}
147+
// defaultValue={initSearchForm.type}
148+
options={[
149+
{ value: 'TITLE', label: '제목' },
150+
{ value: 'AUTHOR', label: '저자' },
151+
{ value: 'TAG', label: '태그' },
152+
]}
153+
onChange={(data) => setFormInfo({ ...formInfo, type: data })}
154+
/>
155+
</Form.Item>
156+
<Form.Item name="keyword">
157+
<Input className={styles.searchInput} value={formInfo.keyword} onChange={(e) => setFormInfo({ ...formInfo, keyword: e.target.value })} />
158+
</Form.Item>
159+
<Form.Item label={null}>
160+
<Button className={styles.searchBtn} type="primary" htmlType="submit">
161+
검색
162+
</Button>
163+
</Form.Item>
164+
</Form>
165+
);
166+
}
167+
168+
const useInView = (sorting: sortingType, keyword: string, search: searchType) => {
165169
const bottomRef = useRef(null);
166170
const [inView, setInView] = useState(false);
167171

168172
const { data, fetchNextPage, isLoading, isError, isSuccess, isFetchingNextPage } = useAppInfiniteQuery({
169-
queryKey: queryKey.book.all('TITLE'),
170-
queryFn: ({ pageParam }) => BookControllerService.getAllBooksUsingGet({ page: pageParam, sort: 'TITLE' }),
173+
queryKey: keyword ? queryKey.book.search(sorting, keyword, search) : queryKey.book.all(sorting),
174+
queryFn: ({ pageParam }) =>
175+
keyword
176+
? BookControllerService.searchBooksUsingGet({
177+
keyword,
178+
sort: sorting,
179+
search,
180+
page: pageParam,
181+
})
182+
: BookControllerService.getAllBooksUsingGet({ page: pageParam, sort: sorting }),
171183
initialPageParam: 0,
172184
getNextPageParam: (lastData) => (lastData.number || 0) + 1,
173185
});
186+
174187
const totalPages = data?.pages[0].totalPages || 0;
175188
const curPage = data?.pages.length || 0;
176189

@@ -211,10 +224,11 @@ const useInView = () => {
211224

212225
export default function BookList() {
213226
const { styles } = useStyles();
214-
type sortingType = 'TITLE' | 'CREATED_AT' | 'RENT_TIME';
227+
215228
const [sorting, setSorting] = useState<sortingType>('CREATED_AT');
216229

217-
const bookListInfiniteQuery = useInView();
230+
const [searchInfo, setSearchInfo] = useState<{ type: searchType; keyword: string }>({ type: 'TITLE', keyword: '' });
231+
const bookListInfiniteQuery = useInView(sorting, searchInfo.keyword, searchInfo.type);
218232

219233
return (
220234
<div className={styles.wrapper}>
@@ -233,7 +247,7 @@ export default function BookList() {
233247
{ value: 'RENT_TIME', label: '최근반납순' },
234248
]}
235249
/>
236-
{/* <BookListSearch setSearch={setSearch} /> */}
250+
<BookListSearch setSearchInfo={setSearchInfo} />
237251
</div>
238252
{match(bookListInfiniteQuery)
239253
.with({ isLoading: true }, () => <Skeleton style={{ width: '100%' }} />)

apps/web-client/src/lib/api-v2/queryKey.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const queryKey = {
1616
book: (id: number) => ['book.book', id] as const,
1717
all: (sorting: string, page?: number) => (page !== undefined ? (['book.all', page, sorting] as const) : (['book.all', sorting] as const)),
1818
borrowed: ['book.borrowed'] as const,
19+
search: (sorting: string, keyword: string, searchType: string, page?: number) => ['book.search', sorting, keyword, searchType, page] as const,
1920
},
2021
post: {
2122
all: (boardType: BoardType, page: number) => ['post.all', boardType, page] as const,

0 commit comments

Comments
 (0)