feat: vitual lazy load on combobox
This commit is contained in:
74
src/components/lookups/RoleCombobox.tsx
Normal file
74
src/components/lookups/RoleCombobox.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
'use client';
|
||||
|
||||
import { AsyncCombobox, usePaginatedLookup } from '@/components/async-combobox';
|
||||
import type { AsyncComboboxOption } from '@/components/async-combobox';
|
||||
import { roleService } from '@/services/api';
|
||||
import type { Role } from '@/types';
|
||||
|
||||
import { roleKeys } from '@/app/(modules)/roles/queries/roleKeys';
|
||||
import type { RoleComboboxProps } from './RoleCombobox.types';
|
||||
|
||||
const ROLE_PAGE_SIZE = 20;
|
||||
|
||||
function parseRoleId(value: string) {
|
||||
const roleId = Number(value);
|
||||
return Number.isFinite(roleId) ? roleId : null;
|
||||
}
|
||||
|
||||
function mapRoleOption(role: Role): AsyncComboboxOption {
|
||||
return {
|
||||
value: String(role.id),
|
||||
label: role.display_name || role.name,
|
||||
};
|
||||
}
|
||||
|
||||
export function RoleCombobox({
|
||||
value,
|
||||
onValueChange,
|
||||
enabled = true,
|
||||
disabled = false,
|
||||
portalContainer,
|
||||
}: RoleComboboxProps) {
|
||||
const lookup = usePaginatedLookup<Role>({
|
||||
enabled,
|
||||
selectedValue: value,
|
||||
pageSize: ROLE_PAGE_SIZE,
|
||||
queryKey: (searchTerm) =>
|
||||
[
|
||||
...roleKeys.lists(),
|
||||
'async-lookup',
|
||||
searchTerm,
|
||||
ROLE_PAGE_SIZE,
|
||||
] as const,
|
||||
queryFn: ({ searchTerm, skip, limit }) =>
|
||||
roleService.getRoles({
|
||||
search_term: searchTerm || undefined,
|
||||
skip,
|
||||
limit,
|
||||
effective_status: true,
|
||||
sort_by: 'display_name',
|
||||
sort_order: 'asc',
|
||||
}),
|
||||
mapOption: mapRoleOption,
|
||||
resolveSelected: (roleId) => {
|
||||
const numericRoleId = parseRoleId(roleId);
|
||||
return numericRoleId ? roleService.getRoleById(numericRoleId) : Promise.resolve(null);
|
||||
},
|
||||
resolveSelectedQueryKey: (roleId) => {
|
||||
const numericRoleId = parseRoleId(roleId);
|
||||
return numericRoleId ? roleKeys.detail(numericRoleId) : [...roleKeys.details(), 'invalid', roleId];
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<AsyncCombobox
|
||||
lookup={lookup}
|
||||
onValueChange={onValueChange}
|
||||
disabled={disabled}
|
||||
placeholder="Select role"
|
||||
searchPlaceholder="Search roles..."
|
||||
emptyMessage="No roles found."
|
||||
portalContainer={portalContainer}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user