/* eslint-disable max-lines-per-function -- 列表筛选与游标分页状态集中在一个 Hook */ import type { UserSummary } from '@lingxi/shared'; import { useCallback, useMemo, useState } from 'react'; import { useUserListQuery } from '@/hooks/queries/use-users'; import { useDebouncedValue } from '@/hooks/use-debounced-value'; import { DEFAULT_USER_LIST_FILTERS, toUserListQueryInput, type UserListFilters, } from './user-filters'; export interface UserListController { filters: UserListFilters; users: UserSummary[]; loading: boolean; error: Error | null; hasNext: boolean; hasPrev: boolean; setFilters: (next: Partial) => void; resetFilters: () => void; onNext: () => void; onPrev: () => void; onRetry: () => void; } /** 列表筛选 + 游标分页(cursor 历史栈,前进/后退都复用后端返回的 next_cursor) */ export function useUserListController(): UserListController { const [filters, setFiltersState] = useState(DEFAULT_USER_LIST_FILTERS); const debouncedKeyword = useDebouncedValue(filters.keyword); const [cursors, setCursors] = useState<(string | null)[]>([null]); const [pageIndex, setPageIndex] = useState(0); const queryInput = useMemo( () => toUserListQueryInput( { ...filters, keyword: debouncedKeyword }, cursors[pageIndex] ?? undefined, ), [filters, debouncedKeyword, cursors, pageIndex], ); const query = useUserListQuery(queryInput); const resetPaging = useCallback(() => { setCursors([null]); setPageIndex(0); }, []); const setFilters = useCallback( (next: Partial) => { setFiltersState((current) => ({ ...current, ...next })); resetPaging(); }, [resetPaging], ); const resetFilters = useCallback(() => { setFiltersState(DEFAULT_USER_LIST_FILTERS); resetPaging(); }, [resetPaging]); const nextCursor = query.data?.next_cursor ?? null; const onNext = useCallback(() => { if (nextCursor === null) { return; } setCursors((current) => [...current.slice(0, pageIndex + 1), nextCursor]); setPageIndex((current) => current + 1); }, [nextCursor, pageIndex]); const onPrev = useCallback(() => { setPageIndex((current) => Math.max(0, current - 1)); }, []); const onRetry = useCallback(() => { void query.refetch(); }, [query]); return { filters, users: query.data?.items ?? [], loading: query.isPending, error: query.error, hasNext: nextCursor !== null, hasPrev: pageIndex > 0, setFilters, resetFilters, onNext, onPrev, onRetry, }; }