1- import { Empty , Result , Select , Skeleton } from 'antd' ;
1+ import { Button , Empty , Form , Input , Result , Select , Skeleton } from 'antd' ;
22import { match } from 'ts-pattern' ;
3- import { useEffect , useMemo , useRef , useState } from 'react' ;
3+ import { Dispatch , SetStateAction , useEffect , useMemo , useRef , useState } from 'react' ;
44import { createStyles } from 'antd-style' ;
55import { 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
212225export 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%' } } /> )
0 commit comments