fix: search school
This commit is contained in:
parent
f1efaabf97
commit
ce180706d0
@ -6,6 +6,7 @@ import {
|
||||
flip,
|
||||
offset,
|
||||
shift,
|
||||
size,
|
||||
useDismiss,
|
||||
useFloating,
|
||||
useFocus,
|
||||
@ -27,6 +28,7 @@ export type PortalToFollowElemOptions = {
|
||||
open?: boolean
|
||||
offset?: number | OffsetOptions
|
||||
onOpenChange?: (open: boolean) => void
|
||||
triggerPopupSameWidth?: boolean
|
||||
}
|
||||
|
||||
export function usePortalToFollowElem({
|
||||
@ -34,6 +36,7 @@ export function usePortalToFollowElem({
|
||||
open,
|
||||
offset: offsetValue = 0,
|
||||
onOpenChange: setControlledOpen,
|
||||
triggerPopupSameWidth,
|
||||
}: PortalToFollowElemOptions = {}) {
|
||||
const setOpen = setControlledOpen
|
||||
|
||||
@ -50,6 +53,12 @@ export function usePortalToFollowElem({
|
||||
padding: 5,
|
||||
}),
|
||||
shift({ padding: 5 }),
|
||||
size({
|
||||
apply({ rects, elements }) {
|
||||
if (triggerPopupSameWidth)
|
||||
elements.floating.style.width = `${rects.reference.width}px`
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
|
@ -10,15 +10,16 @@ export const useEducation = () => {
|
||||
const {
|
||||
mutateAsync,
|
||||
isPending,
|
||||
data,
|
||||
} = useEducationAutocomplete()
|
||||
|
||||
const [prevSchools, setPrevSchools] = useState<string[]>([])
|
||||
const handleUpdateSchools = useCallback((searchParams: SearchParams) => {
|
||||
if (searchParams.keywords) {
|
||||
mutateAsync(searchParams).then((res) => {
|
||||
const currentPage = searchParams.page || 1
|
||||
const currentPage = searchParams.page || 0
|
||||
const resSchools = res.data
|
||||
if (currentPage > 1)
|
||||
if (currentPage > 0)
|
||||
setPrevSchools(prevSchools => [...(prevSchools || []), ...resSchools])
|
||||
else
|
||||
setPrevSchools(resSchools)
|
||||
@ -29,12 +30,15 @@ export const useEducation = () => {
|
||||
const { run: querySchoolsWithDebounced } = useDebounceFn((searchParams: SearchParams) => {
|
||||
handleUpdateSchools(searchParams)
|
||||
}, {
|
||||
wait: 1000,
|
||||
wait: 300,
|
||||
})
|
||||
|
||||
return {
|
||||
schools: prevSchools,
|
||||
setSchools: setPrevSchools,
|
||||
querySchoolsWithDebounced,
|
||||
handleUpdateSchools,
|
||||
isLoading: isPending,
|
||||
hasNext: data?.has_next,
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDebounceFn } from 'ahooks'
|
||||
import { useEducation } from './hooks'
|
||||
import Input from '@/app/components/base/input'
|
||||
import {
|
||||
@ -25,29 +24,53 @@ const SearchInput = ({
|
||||
const [open, setOpen] = useState(false)
|
||||
const {
|
||||
schools,
|
||||
isLoading,
|
||||
setSchools,
|
||||
querySchoolsWithDebounced,
|
||||
handleUpdateSchools,
|
||||
hasNext,
|
||||
} = useEducation()
|
||||
const pageRef = useRef(0)
|
||||
const valueRef = useRef(value)
|
||||
|
||||
const {
|
||||
run: handleSearch,
|
||||
} = useDebounceFn(() => {
|
||||
querySchoolsWithDebounced({
|
||||
keywords: value,
|
||||
page: 1,
|
||||
const handleSearch = useCallback((debounced?: boolean) => {
|
||||
const keywords = valueRef.current
|
||||
const page = pageRef.current
|
||||
if (debounced) {
|
||||
querySchoolsWithDebounced({
|
||||
keywords,
|
||||
page,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
handleUpdateSchools({
|
||||
keywords,
|
||||
page,
|
||||
})
|
||||
}, {
|
||||
wait: 300,
|
||||
})
|
||||
const handleValueChange = useCallback((e: { target: { value: string } }) => {
|
||||
onChange(e.target.value)
|
||||
handleSearch()
|
||||
}, [handleSearch, onChange])
|
||||
}, [querySchoolsWithDebounced, handleUpdateSchools])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !open && schools.length)
|
||||
setOpen(true)
|
||||
}, [isLoading, open, schools])
|
||||
const handleValueChange = useCallback((e: any) => {
|
||||
setOpen(true)
|
||||
setSchools([])
|
||||
pageRef.current = 0
|
||||
const inputValue = e.target.value
|
||||
valueRef.current = inputValue
|
||||
onChange(inputValue)
|
||||
handleSearch(true)
|
||||
}, [onChange, handleSearch, setSchools])
|
||||
|
||||
const handleScroll = useCallback((e: Event) => {
|
||||
const target = e.target as HTMLDivElement
|
||||
const {
|
||||
scrollTop,
|
||||
scrollHeight,
|
||||
clientHeight,
|
||||
} = target
|
||||
if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0 && hasNext) {
|
||||
pageRef.current += 1
|
||||
handleSearch()
|
||||
}
|
||||
}, [handleSearch, hasNext])
|
||||
|
||||
return (
|
||||
<PortalToFollowElem
|
||||
@ -55,6 +78,7 @@ const SearchInput = ({
|
||||
onOpenChange={setOpen}
|
||||
placement='bottom'
|
||||
offset={4}
|
||||
triggerPopupSameWidth
|
||||
>
|
||||
<PortalToFollowElemTrigger className='block w-full'>
|
||||
<Input
|
||||
@ -64,20 +88,31 @@ const SearchInput = ({
|
||||
onChange={handleValueChange}
|
||||
/>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent>
|
||||
<div className='p-1 border-[0.5px] border-components-panel-border bg-components-panel-bg-blur rounded-xl'>
|
||||
{
|
||||
schools.map((school, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className='flex items-center px-2 py-1.5 h-8 system-md-regular text-text-secondary truncate'
|
||||
title={school}
|
||||
>
|
||||
{school}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<PortalToFollowElemContent className='z-10'>
|
||||
{
|
||||
!!schools.length && value && (
|
||||
<div
|
||||
className='p-1 max-h-[330px] overflow-y-auto border-[0.5px] border-components-panel-border bg-components-panel-bg-blur rounded-xl'
|
||||
onScroll={handleScroll as any}
|
||||
>
|
||||
{
|
||||
schools.map((school, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className='flex items-center px-2 py-1.5 h-8 system-md-regular text-text-secondary truncate cursor-pointer hover:bg-state-base-hover rounded-lg'
|
||||
title={school}
|
||||
onClick={() => {
|
||||
onChange(school)
|
||||
setOpen(false)
|
||||
}}
|
||||
>
|
||||
{school}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
)
|
||||
|
@ -44,8 +44,8 @@ export const useEducationAutocomplete = () => {
|
||||
mutationFn: (searchParams: SearchParams) => {
|
||||
const {
|
||||
keywords = '',
|
||||
page = 1,
|
||||
limit = 20,
|
||||
page = 0,
|
||||
limit = 40,
|
||||
} = searchParams
|
||||
return get<{ data: string[]; has_next: boolean; curr_page: number }>(`/account/education/autocomplete?keywords=${keywords}&page=${page}&limit=${limit}`)
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user