Skip to content

Commit

Permalink
refactor: fetch delegates using vue-query
Browse files Browse the repository at this point in the history
  • Loading branch information
Sekhmet committed Jan 26, 2025
1 parent e8c2f14 commit f741a1e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 123 deletions.
84 changes: 45 additions & 39 deletions apps/ui/src/components/SpaceDelegates.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { sanitizeUrl } from '@braintree/sanitize-url';
import { useInfiniteQuery } from '@tanstack/vue-query';
import removeMarkdown from 'remove-markdown';
import { getGenericExplorerUrl } from '@/helpers/explorer';
import { _n, _p, _vp, shorten } from '@/helpers/utils';
Expand All @@ -21,18 +22,7 @@ const sortBy = ref(
| 'tokenHoldersRepresentedAmount-asc'
);
const { setTitle } = useTitle();
const {
loading,
loadingMore,
loaded,
failed,
errorCode,
hasMore,
delegates,
fetch,
fetchMore,
reset
} = useDelegates(
const { getDelegates } = useDelegates(
props.delegation.apiType as DelegationType,
props.delegation.apiUrl as string,
props.delegation.contractAddress as string,
Expand All @@ -42,6 +32,39 @@ const { web3 } = useWeb3();
const spaceKey = computed(() => `${props.space.network}:${props.space.id}`);
const {
data,
error,
fetchNextPage,
hasNextPage,
isPending,
isFetchingNextPage,
isError
} = useInfiniteQuery({
initialPageParam: 0,
queryKey: ['delegates', props.delegation.contractAddress, sortBy],
queryFn: ({ pageParam }) => {
const [orderBy, orderDirection] = sortBy.value.split('-');
return getDelegates({
orderBy,
orderDirection,
first: 40,
skip: pageParam
});
},
getNextPageParam: (lastPage, pages) => {
if (lastPage.length < 40) return null;
return pages.length * 40;
},
retry: (failureCount, error) => {
if (error?.message.includes('Row not found')) return false;
return failureCount < 3;
}
});
function getExplorerUrl(address: string, type: 'address' | 'token') {
let url: string | null = null;
if (props.delegation.chainId) {
Expand All @@ -67,28 +90,11 @@ function handleSortChange(
}
}
async function handleEndReached() {
if (!hasMore.value) return;
await fetchMore(sortBy.value);
}
function handleDelegateClick(delegatee?: string) {
delegateModalState.value = delegatee ? { delegatee } : null;
delegateModalOpen.value = true;
}
onMounted(() => {
if (!props.delegation.apiUrl) return;
fetch(sortBy.value);
});
watch([sortBy], () => {
reset();
fetch(sortBy.value);
});
watchEffect(() => setTitle(`Delegates - ${props.space.name}`));
</script>

Expand Down Expand Up @@ -182,27 +188,27 @@ watchEffect(() => setTitle(`Delegates - ${props.space.name}`));
</button>
<div class="w-[20px]" />
</div>
<UiLoading v-if="loading" class="px-4 py-3 block" />
<UiLoading v-if="isPending" class="px-4 py-3 block" />
<template v-else>
<div
v-if="loaded && (delegates.length === 0 || failed)"
v-if="data?.pages.length === 0 || isError"
class="px-4 py-3 flex items-center space-x-1"
>
<IH-exclamation-circle class="shrink-0" />
<span v-if="errorCode === 'initializing'">
<span v-if="error?.message.includes('Row not found')">
Delegates are being computed, please come back later.
</span>
<span v-else-if="failed">Failed to load delegates.</span>
<span v-else-if="delegates.length === 0">
There are no delegates.
</span>
<span v-else-if="isError">Failed to load delegates.</span>
<span v-else-if="data?.pages.length === 0">
There are no delegates.</span
>
</div>
<UiContainerInfiniteScroll
:loading-more="loadingMore"
@end-reached="handleEndReached"
:loading-more="isFetchingNextPage"
@end-reached="hasNextPage && fetchNextPage()"
>
<div
v-for="(delegate, i) in delegates"
v-for="(delegate, i) in data?.pages.flat()"
:key="i"
class="border-b flex space-x-3 px-4"
>
Expand Down
85 changes: 1 addition & 84 deletions apps/ui/src/composables/useDelegates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ type DelegatesQueryFilter = {
first: number;
};

type SortOrder =
| 'delegatedVotes-desc'
| 'delegatedVotes-asc'
| 'tokenHoldersRepresentedAmount-desc'
| 'tokenHoldersRepresentedAmount-asc';

const DEFAULT_ORDER = 'delegatedVotes-desc';

const DELEGATES_LIMIT = 40;

const DELEGATES_QUERY = gql`
query (
$first: Int!
Expand Down Expand Up @@ -93,14 +83,6 @@ export function useDelegates(
governance: string,
space: Space
) {
const delegates: Ref<Delegate[]> = ref([]);
const loading = ref(false);
const loadingMore = ref(false);
const loaded = ref(false);
const failed = ref(false);
const hasMore = ref(false);
const errorCode = ref<'initializing' | null>(null);

const httpLink = createHttpLink({
uri: convertUrl(delegationApiUrl)
});
Expand Down Expand Up @@ -166,72 +148,7 @@ export function useDelegates(
return formatDelegates(data);
}

async function _fetch(overwrite: boolean, sortBy: SortOrder) {
const [orderBy, orderDirection] = sortBy.split('-');

const newDelegates = await getDelegates({
orderBy,
orderDirection,
skip: overwrite ? 0 : delegates.value.length,
first: DELEGATES_LIMIT
});

delegates.value = overwrite
? newDelegates
: [...delegates.value, ...newDelegates];

hasMore.value = newDelegates.length === DELEGATES_LIMIT;
}

async function fetch(sortBy: SortOrder = DEFAULT_ORDER) {
if (loading.value || loaded.value) return;
loading.value = true;

try {
await _fetch(true, sortBy);

loaded.value = true;
} catch (e) {
failed.value = true;

if (e.message.includes('Row not found')) {
errorCode.value = 'initializing';
}
} finally {
loading.value = false;
loaded.value = true;
}
}

async function fetchMore(sortBy: SortOrder = DEFAULT_ORDER) {
if (loading.value || !loaded.value) return;
loadingMore.value = true;

await _fetch(false, sortBy);

loadingMore.value = false;
}

function reset() {
delegates.value = [];
loading.value = false;
loadingMore.value = false;
loaded.value = false;
failed.value = false;
hasMore.value = false;
}

return {
loading,
loadingMore,
loaded,
failed,
errorCode,
hasMore,
delegates,
getDelegates,
fetch,
fetchMore,
reset
getDelegates
};
}

0 comments on commit f741a1e

Please sign in to comment.