You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gcgj-dify-1.7.0/web/app/education-apply/search-input.tsx

121 lines
3.2 KiB
TypeScript

import type { ChangeEventHandler } from 'react'
import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useEducation } from './hooks'
import Input from '@/app/components/base/input'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
type SearchInputProps = {
value?: string;
onChange: (value: string) => void;
}
const SearchInput = ({ value, onChange }: SearchInputProps) => {
const { t } = useTranslation()
const [open, setOpen] = useState(false)
const {
schools,
setSchools,
querySchoolsWithDebounced,
handleUpdateSchools,
hasNext,
} = useEducation()
const pageRef = useRef(0)
const valueRef = useRef(value)
const handleSearch = useCallback(
(debounced?: boolean) => {
const keywords = valueRef.current
const page = pageRef.current
if (debounced) {
querySchoolsWithDebounced({
keywords,
page,
})
return
}
handleUpdateSchools({
keywords,
page,
})
},
[querySchoolsWithDebounced, handleUpdateSchools],
)
const handleValueChange: ChangeEventHandler<HTMLInputElement> = useCallback(
(e) => {
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
open={open}
onOpenChange={setOpen}
placement="bottom"
offset={4}
triggerPopupSameWidth
>
<PortalToFollowElemTrigger className="block w-full">
<Input
className="w-full"
placeholder={t('education.form.schoolName.placeholder')}
value={value}
onChange={handleValueChange}
/>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className="z-[32]">
{!!schools.length && value && (
<div
className="max-h-[330px] overflow-y-auto rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1"
onScroll={handleScroll as any}
>
{schools.map((school, index) => (
<div
key={index}
className="system-md-regular flex h-8 cursor-pointer items-center truncate rounded-lg px-2 py-1.5 text-text-secondary hover:bg-state-base-hover"
title={school}
onClick={() => {
onChange(school)
setOpen(false)
}}
>
{school}
</div>
))}
</div>
)}
</PortalToFollowElemContent>
</PortalToFollowElem>
)
}
export default SearchInput