Skip to content

Commit f25f462

Browse files
committed
feat: add load more for user segment dropdown in targeting
1 parent f5df5d1 commit f25f462

8 files changed

Lines changed: 733 additions & 519 deletions

File tree

ui/dashboard/src/@queries/user-segments.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import {
22
userSegmentsFetcher,
33
UserSegmentsFetcherParams
44
} from '@api/user-segment';
5-
import { QueryClient, useQuery, useQueryClient } from '@tanstack/react-query';
5+
import {
6+
QueryClient,
7+
useInfiniteQuery,
8+
useQuery,
9+
useQueryClient
10+
} from '@tanstack/react-query';
611
import type { UserSegmentCollection, QueryOptionsRespond } from '@types';
712

813
type QueryOptions = QueryOptionsRespond<UserSegmentCollection> & {
@@ -48,3 +53,25 @@ export const prefetchUserSegments = (
4853
...queryOptions
4954
});
5055
};
56+
57+
type InfiniteQueryOptions = {
58+
params?: Omit<UserSegmentsFetcherParams, 'cursor'>;
59+
enabled?: boolean;
60+
};
61+
62+
export const useInfiniteQueryUserSegments = ({
63+
params,
64+
enabled = true
65+
}: InfiniteQueryOptions = {}) =>
66+
useInfiniteQuery({
67+
queryKey: [USER_SEGMENTS_QUERY_KEY, 'infinite', params],
68+
queryFn: ({ pageParam = '0' }) =>
69+
userSegmentsFetcher({ ...params, cursor: pageParam as string }),
70+
initialPageParam: '0',
71+
getNextPageParam: (lastPage: UserSegmentCollection) => {
72+
const nextCursor = Number(lastPage.cursor);
73+
const total = Number(lastPage.totalCount);
74+
return nextCursor < total ? String(nextCursor) : undefined;
75+
},
76+
enabled
77+
});

ui/dashboard/src/elements/dropdown-with-search/index.tsx

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export interface DropdownMenuWithSearchProps {
3636
itemClassName?: string;
3737
isExpand?: boolean;
3838
disabled?: boolean;
39+
hideSearchInput?: boolean;
3940
trigger?: ReactNode;
4041
showArrow?: boolean;
4142
showClear?: boolean;
@@ -84,6 +85,7 @@ const DropdownMenuWithSearch = ({
8485
itemClassName,
8586
isExpand,
8687
disabled,
88+
hideSearchInput,
8789
trigger,
8890
showArrow,
8991
showClear,
@@ -129,11 +131,14 @@ const DropdownMenuWithSearch = ({
129131
[options, searchValue, onSearchChange]
130132
);
131133

132-
let timerId: NodeJS.Timeout | null = null;
133-
if (timerId) clearTimeout(timerId);
134-
timerId = setTimeout(() => inputSearchRef?.current?.focus(), 50);
135134
const handleFocusSearchInput = useCallback(() => {}, []);
136135

136+
useEffect(() => {
137+
if (hideSearchInput || !isOpen) return;
138+
const timerId = setTimeout(() => inputSearchRef?.current?.focus(), 50);
139+
return () => clearTimeout(timerId);
140+
}, [hideSearchInput, isOpen]);
141+
137142
const onClearSearchValue = useCallback(() => {
138143
setSearchValue('');
139144
onSearchChange?.('');
@@ -185,28 +190,30 @@ const DropdownMenuWithSearch = ({
185190
: {}
186191
}
187192
>
188-
<DropdownMenuSearch
189-
ref={inputSearchRef}
190-
value={searchValue}
191-
placeholder={inputPlaceholder}
192-
onChange={value => {
193-
contentRef.current?.scrollTo({
194-
top: 0,
195-
behavior: 'smooth'
196-
});
197-
setSearchValue(value);
198-
onSearchChange?.(value);
199-
handleFocusSearchInput();
200-
}}
201-
onKeyDown={event =>
202-
onKeyDown?.({
203-
event,
204-
searchValue,
205-
matchOptions: dropdownOptions,
206-
onClearSearchValue
207-
})
208-
}
209-
/>
193+
{!hideSearchInput && (
194+
<DropdownMenuSearch
195+
ref={inputSearchRef}
196+
value={searchValue}
197+
placeholder={inputPlaceholder}
198+
onChange={value => {
199+
contentRef.current?.scrollTo({
200+
top: 0,
201+
behavior: 'smooth'
202+
});
203+
setSearchValue(value);
204+
onSearchChange?.(value);
205+
handleFocusSearchInput();
206+
}}
207+
onKeyDown={event =>
208+
onKeyDown?.({
209+
event,
210+
searchValue,
211+
matchOptions: dropdownOptions,
212+
onClearSearchValue
213+
})
214+
}
215+
/>
216+
)}
210217
{dropdownOptions?.length > 0 ? (
211218
<>
212219
<DropdownList

0 commit comments

Comments
 (0)