aboutsummaryrefslogtreecommitdiff
path: root/src/components/input/LookupField.tsx
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/components/input/LookupField.tsx
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/components/input/LookupField.tsx')
-rw-r--r--src/components/input/LookupField.tsx65
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>
+ );
+}