import { useState } from 'react'; import { DocumentNode, OperationVariables, TypedDocumentNode, useQuery, } from '@apollo/client'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; type CustomResolverQueryResult< T extends { [key: string]: any; }, > = { [queryName: string]: T; }; export const useCustomResolver = < T extends { [key: string]: any; }, >( query: | DocumentNode | TypedDocumentNode, OperationVariables>, queryName: string, objectName: string, activityTargetableObject: ActivityTargetableObject, pageSize: number, ): { data: CustomResolverQueryResult | undefined; firstQueryLoading: boolean; isFetchingMore: boolean; fetchMoreRecords: () => Promise; } => { const { enqueueSnackBar } = useSnackBar(); const [page, setPage] = useState({ pageNumber: 1, hasNextPage: true, }); const [isFetchingMore, setIsFetchingMore] = useState(false); const queryVariables = { ...(activityTargetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person ? { personId: activityTargetableObject.id } : { companyId: activityTargetableObject.id }), page: 1, pageSize, }; const { data, loading: firstQueryLoading, fetchMore, } = useQuery>(query, { variables: queryVariables, onError: (error) => { enqueueSnackBar(error.message || `Error loading ${objectName}`, { variant: 'error', }); }, }); const fetchMoreRecords = async () => { if (page.hasNextPage && !isFetchingMore && !firstQueryLoading) { setIsFetchingMore(true); await fetchMore({ variables: { ...queryVariables, page: page.pageNumber + 1, }, updateQuery: (prev, { fetchMoreResult }) => { if (!fetchMoreResult?.[queryName]?.[objectName]?.length) { setPage((page) => ({ ...page, hasNextPage: false, })); return { [queryName]: { ...prev?.[queryName], [objectName]: [...(prev?.[queryName]?.[objectName] ?? [])], }, }; } return { [queryName]: { ...prev?.[queryName], [objectName]: [ ...(prev?.[queryName]?.[objectName] ?? []), ...(fetchMoreResult?.[queryName]?.[objectName] ?? []), ], }, }; }, }); setPage((page) => ({ ...page, pageNumber: page.pageNumber + 1, })); setIsFetchingMore(false); } }; return { data, firstQueryLoading, isFetchingMore, fetchMoreRecords, }; };