cyb/src/containers/Search/hooks/useRankLinks.tsx

import { useInfiniteQuery } from '@tanstack/react-query';
import useGetBackLink from 'src/containers/ipfs/hooks/useGetBackLink';
import { useQueryClient } from 'src/contexts/queryClient';
import { enqueueLinksSave } from 'src/services/backend/channels/BackendQueueChannel/backendQueueSenders';
import { mapLinkToLinkDto } from 'src/services/CozoDb/mapping';
import { getRankGrade, searchByHash } from 'src/utils/search/utils';
import { coinDecimals } from 'src/utils/utils';
import { LinksTypeFilter } from '../types';
import { merge } from './shared';

const _PER_PAGE_LIMIT = 10;

const useSearch = (hash: string, { skip = false } = {}) => {
  const cid = hash;

  const queryClient = useQueryClient();

  const { data, fetchNextPage, error, isFetching, refetch, hasNextPage, isInitialLoading } =
    useInfiniteQuery(
      ['useSearch', cid],
      async ({ pageParam = 0 }: { pageParam?: number }) => {
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const response = await searchByHash(queryClient, cid, pageParam);

        if (response?.result) {
          enqueueLinksSave(response.result.map((l) => mapLinkToLinkDto(hash, l.particle)));
        }

        return { data: response, page: pageParam };
      },
      {
        enabled: Boolean(queryClient && cid) && !skip,
        getNextPageParam: (lastPage) => {
          const total = lastPage?.data?.pagination?.total || 0;
          if (total === 0 || lastPage.page >= total - 1) {
            return undefined;
          }

          return lastPage.page + 1;
        },
      }
    );

  return {
    data:
      (data?.pages || [])
        .reduce((acc, page) => {
          return acc.concat(
            (page.data?.result || []).map((item) => {
              const rank = coinDecimals(item.rank);
              return {
                cid: item.particle,
                rank,
                grade: getRankGrade(rank),
                type: 'from',
              };
            })
          );
        }, [])
        .filter(Boolean) || [],
    total: data?.pages?.[0].data?.pagination?.total || 0,
    fetchNextPage,
    error,
    refetch,
    hasNextPage,
    isInitialLoading,
    isFetching,
  };
};

function useRankLinks(hash: string, type = LinksTypeFilter.from, { skip = false } = {}) {
  const linkType = type;

  const searchRank = useSearch(hash, {
    skip,
  });

  const backlinksRank = useGetBackLink(hash, {
    skip,
  });

  return {
    data: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.backlinks;
        case LinksTypeFilter.all:
          return merge(searchRank.data, backlinksRank.backlinks).sort((a, b) => {
            return parseFloat(b.rank) - parseFloat(a.rank);
          });
        default:
          return searchRank.data || [];
      }
    })(),
    total: (() => {
      return {
        to: backlinksRank.total,
        from: searchRank.total,
      };
    })(),
    refetch: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.refetch;
        case LinksTypeFilter.all:
          return () => {
            searchRank.refetch();
            backlinksRank.refetch();
          };
        default:
          return searchRank.refetch;
      }
    })(),
    isInitialLoading: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.isInitialLoading;
        case LinksTypeFilter.all:
          return backlinksRank.isInitialLoading || searchRank.isInitialLoading;
        default:
          return searchRank.isInitialLoading;
      }
    })(),
    isFetching: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.isFetching;
        case LinksTypeFilter.all:
          return backlinksRank.isFetching || searchRank.isFetching;
        default:
          return searchRank.isFetching;
      }
    })(),
    error: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.error;
        case LinksTypeFilter.all:
          return backlinksRank.error || searchRank.error;
        default:
          return searchRank.error;
      }
    })(),
    hasMore: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.hasNextPage;
        case LinksTypeFilter.all:
          return backlinksRank.hasNextPage || searchRank.hasNextPage;
        default:
          return searchRank.hasNextPage;
      }
    })(),
    fetchNextPage: (() => {
      switch (linkType) {
        case LinksTypeFilter.to:
          return backlinksRank.fetchNextPage;
        case LinksTypeFilter.all:
          return () => {
            backlinksRank.fetchNextPage();
            searchRank.fetchNextPage();
          };
        default:
          return searchRank.fetchNextPage;
      }
    })(),
  };
}

export default useRankLinks;

Synonyms

pussy-ts/src/containers/Search/hooks/useRankLinks.tsx

Neighbours