import { ref } from 'vue' import { useUsersStore } from '@/api' export interface UserOption { label: string value: number } /** * Composable for debounced server-side user search. * Encapsulates the 300ms debounce, fetch, and optional owner-exclusion * pattern shared by the Lists user filter, Items owner select, and * Items share-modal user select. */ export function useUserSearch(config: { perPage?: number exclude?: (u: UserOption) => boolean } = {}) { const { getUsers } = useUsersStore() const query = ref('') const options = ref([]) const fetching = ref(false) let timer: ReturnType | null = null let searchSeq = 0 const search = (q: string) => { query.value = q if (timer) { clearTimeout(timer) } if (!q || q.trim() === '') { options.value = [] return } timer = setTimeout(async () => { const seq = ++searchSeq fetching.value = true try { const data = await getUsers({ search: q, per_page: config.perPage ?? 20 }) if (seq !== searchSeq) return const mapped: UserOption[] = (data as any[]).map((u: any) => ({ label: u.name, value: u.id })) options.value = config.exclude ? mapped.filter((u) => !config.exclude!(u)) : mapped } catch { if (seq === searchSeq) { options.value = [] } } finally { if (seq === searchSeq) { fetching.value = false } } }, 300) } const reset = () => { query.value = '' options.value = [] searchSeq++ fetching.value = false if (timer) { clearTimeout(timer) timer = null } } return { query, options, fetching, search, reset } }