| | import { useEffect, useMemo, useRef, useState, useCallback } from 'react'; |
| | import { useRecoilState } from 'recoil'; |
| | import { usePromptGroupsInfiniteQuery } from '~/data-provider'; |
| | import store from '~/store'; |
| |
|
| | export default function usePromptGroupsNav(hasAccess = true) { |
| | const [pageSize] = useRecoilState(store.promptsPageSize); |
| | const [category] = useRecoilState(store.promptsCategory); |
| | const [name, setName] = useRecoilState(store.promptsName); |
| |
|
| | |
| | const [currentPageIndex, setCurrentPageIndex] = useState(0); |
| | const cursorHistoryRef = useRef<Array<string | null>>([null]); |
| |
|
| | const prevFiltersRef = useRef({ name, category }); |
| |
|
| | const groupsQuery = usePromptGroupsInfiniteQuery( |
| | { |
| | name, |
| | pageSize, |
| | category, |
| | }, |
| | { |
| | enabled: hasAccess, |
| | }, |
| | ); |
| |
|
| | |
| | const currentPageData = useMemo(() => { |
| | if (!hasAccess || !groupsQuery.data?.pages || groupsQuery.data.pages.length === 0) { |
| | return null; |
| | } |
| | |
| | const pageIndex = Math.min(currentPageIndex, groupsQuery.data.pages.length - 1); |
| | return groupsQuery.data.pages[pageIndex]; |
| | }, [hasAccess, groupsQuery.data?.pages, currentPageIndex]); |
| |
|
| | |
| | const promptGroups = useMemo(() => { |
| | return currentPageData?.promptGroups || []; |
| | }, [currentPageData]); |
| |
|
| | |
| | const hasNextPage = useMemo(() => { |
| | if (!currentPageData) return false; |
| |
|
| | |
| | if (currentPageIndex < (groupsQuery.data?.pages?.length || 0) - 1) { |
| | return true; |
| | } |
| |
|
| | |
| | return currentPageData.has_more || false; |
| | }, [currentPageData, currentPageIndex, groupsQuery.data?.pages?.length]); |
| |
|
| | const hasPreviousPage = currentPageIndex > 0; |
| | const currentPage = currentPageIndex + 1; |
| | const totalPages = hasNextPage ? currentPage + 1 : currentPage; |
| |
|
| | |
| | const nextPage = useCallback(async () => { |
| | if (!hasAccess || !hasNextPage) return; |
| |
|
| | const nextPageIndex = currentPageIndex + 1; |
| |
|
| | |
| | if (nextPageIndex >= (groupsQuery.data?.pages?.length || 0)) { |
| | |
| | const result = await groupsQuery.fetchNextPage(); |
| | if (result.isSuccess && result.data?.pages) { |
| | |
| | const lastPage = result.data.pages[result.data.pages.length - 2]; |
| | if (lastPage?.after && !cursorHistoryRef.current.includes(lastPage.after)) { |
| | cursorHistoryRef.current.push(lastPage.after); |
| | } |
| | } |
| | } |
| |
|
| | setCurrentPageIndex(nextPageIndex); |
| | }, [hasAccess, currentPageIndex, hasNextPage, groupsQuery]); |
| |
|
| | |
| | const prevPage = useCallback(() => { |
| | if (!hasAccess || !hasPreviousPage) return; |
| | setCurrentPageIndex(currentPageIndex - 1); |
| | }, [hasAccess, currentPageIndex, hasPreviousPage]); |
| |
|
| | |
| | useEffect(() => { |
| | if (!hasAccess) return; |
| |
|
| | const filtersChanged = |
| | prevFiltersRef.current.name !== name || prevFiltersRef.current.category !== category; |
| |
|
| | if (filtersChanged) { |
| | setCurrentPageIndex(0); |
| | cursorHistoryRef.current = [null]; |
| | prevFiltersRef.current = { name, category }; |
| | } |
| | }, [hasAccess, name, category]); |
| |
|
| | return { |
| | promptGroups: hasAccess ? promptGroups : [], |
| | groupsQuery, |
| | currentPage, |
| | totalPages, |
| | hasNextPage: hasAccess && hasNextPage, |
| | hasPreviousPage: hasAccess && hasPreviousPage, |
| | nextPage, |
| | prevPage, |
| | isFetching: hasAccess ? groupsQuery.isFetching : false, |
| | name, |
| | setName, |
| | }; |
| | } |
| |
|