diff options
| author | Fuwn <[email protected]> | 2026-01-24 13:09:50 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-01-24 13:09:50 +0000 |
| commit | 396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch) | |
| tree | b9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/components/input/LookupField.tsx | |
| download | umami-main.tar.xz umami-main.zip | |
Created from https://vercel.com/new
Diffstat (limited to 'src/components/input/LookupField.tsx')
| -rw-r--r-- | src/components/input/LookupField.tsx | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/components/input/LookupField.tsx b/src/components/input/LookupField.tsx new file mode 100644 index 0000000..c1d419f --- /dev/null +++ b/src/components/input/LookupField.tsx @@ -0,0 +1,65 @@ +import { ComboBox, type ComboBoxProps, ListItem, Loading, useDebounce } from '@umami/react-zen'; +import { endOfDay, subMonths } from 'date-fns'; +import { type SetStateAction, useMemo, useState } from 'react'; +import { Empty } from '@/components/common/Empty'; +import { useMessages, useWebsiteValuesQuery } from '@/components/hooks'; + +export interface LookupFieldProps extends ComboBoxProps { + websiteId: string; + type: string; + value: string; + onChange: (value: string) => void; +} + +export function LookupField({ websiteId, type, value, onChange, ...props }: LookupFieldProps) { + const { formatMessage, messages } = useMessages(); + const [search, setSearch] = useState(value); + const searchValue = useDebounce(search, 300); + const startDate = subMonths(endOfDay(new Date()), 6); + const endDate = endOfDay(new Date()); + + const { data, isLoading } = useWebsiteValuesQuery({ + websiteId, + type, + search: searchValue, + startDate, + endDate, + }); + + const items: string[] = useMemo(() => { + return data?.map(({ value }) => value) || []; + }, [data]); + + const handleSearch = (value: SetStateAction<string>) => { + setSearch(value); + }; + + return ( + <ComboBox + aria-label="LookupField" + {...props} + items={items} + inputValue={value} + onInputChange={value => { + handleSearch(value); + onChange?.(value); + }} + formValue="text" + allowsEmptyCollection + allowsCustomValue + renderEmptyState={() => + isLoading ? ( + <Loading placement="center" icon="dots" /> + ) : ( + <Empty message={formatMessage(messages.noResultsFound)} /> + ) + } + > + {items.map(item => ( + <ListItem key={item} id={item}> + {item} + </ListItem> + ))} + </ComboBox> + ); +} |