You've already forked AstralRinth
refactor: removing useAsyncData for tanstack query (#5262)
* refactor: most places with useAsyncData replaced with tanstack query * refactor report list and report view * refactor organization page to use tanstack query * fix types * refactor collection page and include proper loading state * fix followed projects proper loading state * fix 404 handling * fix organization loading and 404 states * pnpm prepr * refactor: remove useAsyncData on newsletter button * refactor: remove useAsyncData on auth globals fetch * refactor: settings/billing/index.vue to useQuery instead of useAsyncData * refactor: user page to remove useAsyncData * pnpm prepr * fix reports pages * fix notifications page * fix billing page cannot read properties of null and prop warnings * fix refresh causing 404 by removing useBaseFetch and use api-client * fix stale data after removing organization from project * pnpm prepr * fix news erroring in build * fix: project page loads header only after content * fix: user page tanstack problems (start on migrating away from useBaseFetch) * fix: start swapping useBaseFetch usages to api-client * Revert "fix: start swapping useBaseFetch usages to api-client" This reverts commit 3df3fab11d535159132b1288dd7cacc38282b553. * fix: remove debug logging * fix: lint --------- Co-authored-by: Calum H. <calum@modrinth.com> Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
This commit is contained in:
@@ -70,6 +70,7 @@ import {
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import type { AffiliateLink } from '@modrinth/utils'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
const createModal = useTemplateRef<typeof AffiliateLinkCreateModal>('createModal')
|
||||
const revokeModal = useTemplateRef<typeof ConfirmModal>('revokeModal')
|
||||
@@ -83,11 +84,12 @@ const { formatMessage } = useVIntl()
|
||||
const {
|
||||
data: affiliateLinks,
|
||||
error,
|
||||
refresh,
|
||||
} = await useAsyncData(
|
||||
'affiliateLinks',
|
||||
() => useBaseFetch('affiliate', { method: 'GET', internal: true }) as Promise<AffiliateLink[]>,
|
||||
)
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ['affiliate'],
|
||||
queryFn: () =>
|
||||
useBaseFetch('affiliate', { method: 'GET', internal: true }) as Promise<AffiliateLink[]>,
|
||||
})
|
||||
|
||||
const filterQuery = ref('')
|
||||
const creatingLink = ref(false)
|
||||
@@ -116,7 +118,7 @@ async function createAffiliateCode(data: { sourceName: string }) {
|
||||
internal: true,
|
||||
})
|
||||
|
||||
await refresh()
|
||||
await refetch()
|
||||
createModal.value?.close()
|
||||
} catch (err) {
|
||||
handleError(err)
|
||||
@@ -145,7 +147,7 @@ async function confirmRevokeAffiliateLink() {
|
||||
internal: true,
|
||||
})
|
||||
|
||||
await refresh()
|
||||
await refetch()
|
||||
revokeModal.value?.hide()
|
||||
revokingTitle.value = null
|
||||
revokingId.value = null
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import ChartDisplay from '~/components/ui/charts/ChartDisplay.vue'
|
||||
|
||||
definePageMeta({
|
||||
@@ -18,7 +20,9 @@ useHead({
|
||||
const auth = await useAuth()
|
||||
const id = auth.value?.user?.id
|
||||
|
||||
const { data: projects } = await useAsyncData(`user/${id}/projects`, () =>
|
||||
useBaseFetch(`user/${id}/projects`),
|
||||
)
|
||||
const { data: projects } = useQuery({
|
||||
queryKey: computed(() => ['user', id, 'projects']),
|
||||
queryFn: () => useBaseFetch(`user/${id}/projects`),
|
||||
enabled: computed(() => !!id),
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -159,8 +159,10 @@ import {
|
||||
useCompactNumber,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import CollectionCreateModal from '~/components/ui/create/CollectionCreateModal.vue'
|
||||
import { useBaseFetch } from '~/composables/fetch.js'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const { formatCompactNumber, formatCompactNumberPlural } = useCompactNumber()
|
||||
@@ -221,9 +223,10 @@ if (import.meta.client) {
|
||||
|
||||
const filterQuery = ref('')
|
||||
|
||||
const { data: collections } = await useAsyncData(`user/${auth.value.user.id}/collections`, () =>
|
||||
useBaseFetch(`user/${auth.value.user.id}/collections`, { apiVersion: 3 }),
|
||||
)
|
||||
const { data: collections } = useQuery({
|
||||
queryKey: ['user', auth.value.user.id, 'collections'],
|
||||
queryFn: () => useBaseFetch(`user/${auth.value.user.id}/collections`, { apiVersion: 3 }),
|
||||
})
|
||||
|
||||
const route = useNativeRoute()
|
||||
const router = useNativeRouter()
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
:auth="auth"
|
||||
raised
|
||||
compact
|
||||
@update:notifications="() => refresh()"
|
||||
@update:notifications="() => refetch()"
|
||||
/>
|
||||
<nuxt-link
|
||||
v-if="extraNotifs > 0"
|
||||
@@ -98,6 +98,7 @@
|
||||
<script setup>
|
||||
import { ChevronRightIcon, HistoryIcon } from '@modrinth/assets'
|
||||
import { Avatar } from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import NotificationItem from '~/components/ui/NotificationItem.vue'
|
||||
import { fetchExtraNotificationData, groupNotifications } from '~/helpers/platform-notifications.ts'
|
||||
@@ -108,11 +109,11 @@ useHead({
|
||||
|
||||
const auth = await useAuth()
|
||||
|
||||
const [{ data: projects }] = await Promise.all([
|
||||
useAsyncData(`user/${auth.value.user.id}/projects`, () =>
|
||||
useBaseFetch(`user/${auth.value.user.id}/projects`),
|
||||
),
|
||||
])
|
||||
const { data: projects } = useQuery({
|
||||
queryKey: computed(() => ['user', auth.value?.user?.id, 'projects']),
|
||||
queryFn: async () => await useBaseFetch(`user/${auth.value?.user?.id}/projects`),
|
||||
placeholderData: [],
|
||||
})
|
||||
|
||||
const downloadsProjectCount = computed(
|
||||
() => projects.value.filter((project) => project.downloads > 0).length,
|
||||
@@ -121,23 +122,24 @@ const followersProjectCount = computed(
|
||||
() => projects.value.filter((project) => project.followers > 0).length,
|
||||
)
|
||||
|
||||
const { data, refresh } = await useAsyncData(async () => {
|
||||
const notifications = await useBaseFetch(`user/${auth.value.user.id}/notifications`)
|
||||
const { data, refetch } = useQuery({
|
||||
queryKey: computed(() => ['user', auth.value?.user?.id, 'notifications']),
|
||||
queryFn: async () => {
|
||||
const notifications = await useBaseFetch(`user/${auth.value?.user?.id}/notifications`)
|
||||
|
||||
const filteredNotifications = notifications.filter((notif) => !notif.read)
|
||||
const slice = filteredNotifications.slice(0, 30) // send first 30 notifs to be grouped before trimming to 3
|
||||
const filteredNotifications = notifications.filter((notif) => !notif.read)
|
||||
const slice = filteredNotifications.slice(0, 30)
|
||||
|
||||
return fetchExtraNotificationData(slice).then((notifications) => {
|
||||
notifications = groupNotifications(notifications).slice(0, 3)
|
||||
return { notifications, extraNotifs: filteredNotifications.length - slice.length }
|
||||
})
|
||||
return fetchExtraNotificationData(slice).then((notifications) => {
|
||||
notifications = groupNotifications(notifications).slice(0, 3)
|
||||
return { notifications, extraNotifs: filteredNotifications.length - slice.length }
|
||||
})
|
||||
},
|
||||
enabled: computed(() => !!auth.value?.user?.id),
|
||||
})
|
||||
|
||||
const notifications = computed(() => {
|
||||
if (data.value === null) {
|
||||
return []
|
||||
}
|
||||
return data.value.notifications
|
||||
return data.value?.notifications ?? []
|
||||
})
|
||||
|
||||
const extraNotifs = computed(() => (data.value ? data.value.extraNotifs : 0))
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
:format-label="(x) => (x === 'all' ? 'All' : formatProjectType(x).replace('_', ' ') + 's')"
|
||||
:capitalize="false"
|
||||
/>
|
||||
<p v-if="pending">Loading notifications...</p>
|
||||
<p v-if="isPending">Loading notifications...</p>
|
||||
<template v-else-if="error">
|
||||
<p>Error loading notifications:</p>
|
||||
<pre>
|
||||
@@ -45,7 +45,7 @@
|
||||
:notification="notification"
|
||||
:auth="auth"
|
||||
raised
|
||||
@update:notifications="() => refresh()"
|
||||
@update:notifications="() => refetch()"
|
||||
/>
|
||||
</template>
|
||||
<p v-else>You don't have any unread notifications.</p>
|
||||
@@ -59,6 +59,7 @@
|
||||
import { CheckCheckIcon, HistoryIcon } from '@modrinth/assets'
|
||||
import { Button, Chips, Pagination } from '@modrinth/ui'
|
||||
import { formatProjectType } from '@modrinth/utils'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import Breadcrumbs from '~/components/ui/Breadcrumbs.vue'
|
||||
import NotificationItem from '~/components/ui/NotificationItem.vue'
|
||||
@@ -81,11 +82,19 @@ const selectedType = ref('all')
|
||||
const page = ref(1)
|
||||
const perPage = ref(50)
|
||||
|
||||
const { data, pending, error, refresh } = await useAsyncData(
|
||||
async () => {
|
||||
const { data, isPending, error, refetch } = useQuery({
|
||||
queryKey: computed(() => [
|
||||
'user',
|
||||
auth.value?.user?.id,
|
||||
'notifications',
|
||||
page.value,
|
||||
history.value,
|
||||
selectedType.value,
|
||||
]),
|
||||
queryFn: async () => {
|
||||
const pageNum = page.value - 1
|
||||
const showRead = history.value
|
||||
const notifications = await useBaseFetch(`user/${auth.value.user.id}/notifications`)
|
||||
const notifications = await useBaseFetch(`user/${auth.value?.user?.id}/notifications`)
|
||||
|
||||
const typesInFeed = [
|
||||
...new Set(notifications.filter((n) => showRead || !n.read).map((n) => n.type)),
|
||||
@@ -107,8 +116,9 @@ const { data, pending, error, refresh } = await useAsyncData(
|
||||
hasRead: notifications.some((n) => n.read),
|
||||
}))
|
||||
},
|
||||
{ watch: [page, history, selectedType] },
|
||||
)
|
||||
enabled: computed(() => !!auth.value?.user?.id),
|
||||
placeholderData: { notifications: [], notifTypes: [], pages: 1, hasRead: false },
|
||||
})
|
||||
|
||||
const notifications = computed(() =>
|
||||
data.value ? groupNotifications(data.value.notifications, history.value) : [],
|
||||
@@ -130,7 +140,7 @@ async function readAll() {
|
||||
])
|
||||
|
||||
await markAsRead(ids)
|
||||
await refresh()
|
||||
await refetch()
|
||||
}
|
||||
|
||||
function changePage(newPage) {
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
<script setup>
|
||||
import { PlusIcon, UsersIcon } from '@modrinth/assets'
|
||||
import { Avatar } from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import OrganizationCreateModal from '~/components/ui/create/OrganizationCreateModal.vue'
|
||||
import { useAuth } from '~/composables/auth.js'
|
||||
@@ -60,12 +61,13 @@ const createOrgModal = ref(null)
|
||||
const auth = await useAuth()
|
||||
const uid = computed(() => auth.value.user?.id || null)
|
||||
|
||||
const { data: orgs, error } = useAsyncData('organizations', () => {
|
||||
if (!uid.value) return Promise.resolve(null)
|
||||
|
||||
return useBaseFetch('user/' + uid.value + '/organizations', {
|
||||
apiVersion: 3,
|
||||
})
|
||||
const { data: orgs, error } = useQuery({
|
||||
queryKey: computed(() => ['user', uid.value, 'organizations']),
|
||||
queryFn: () =>
|
||||
useBaseFetch('user/' + uid.value + '/organizations', {
|
||||
apiVersion: 3,
|
||||
}),
|
||||
enabled: computed(() => !!uid.value),
|
||||
})
|
||||
|
||||
const sortedOrgs = computed(() =>
|
||||
|
||||
@@ -261,6 +261,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ArrowUpRightIcon, InProgressIcon, UnknownIcon } from '@modrinth/assets'
|
||||
import { defineMessages, useFormatDateTime, useFormatMoney, useVIntl } from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { Tooltip } from 'floating-vue'
|
||||
|
||||
@@ -356,9 +357,9 @@ const messages = defineMessages({
|
||||
},
|
||||
})
|
||||
|
||||
const { data: userBalance, refresh: refreshUserBalance } = await useAsyncData(
|
||||
`payout/balance`,
|
||||
async () => {
|
||||
const { data: userBalance, refetch: refreshUserBalance } = useQuery({
|
||||
queryKey: ['payout', 'balance'],
|
||||
queryFn: async () => {
|
||||
const response = (await useBaseFetch(`payout/balance`, {
|
||||
apiVersion: 3,
|
||||
})) as UserBalanceResponse
|
||||
@@ -370,28 +371,33 @@ const { data: userBalance, refresh: refreshUserBalance } = await useAsyncData(
|
||||
pending: Number(response.pending),
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
const { data: payouts, refresh: refreshPayouts } = await useAsyncData(`payout/history`, () =>
|
||||
useBaseFetch(`payout/history`, {
|
||||
apiVersion: 3,
|
||||
}),
|
||||
)
|
||||
const { data: payouts, refetch: refreshPayouts } = useQuery({
|
||||
queryKey: ['payout', 'history'],
|
||||
queryFn: () =>
|
||||
useBaseFetch(`payout/history`, {
|
||||
apiVersion: 3,
|
||||
}),
|
||||
})
|
||||
|
||||
const userCountry = useUserCountry()
|
||||
const { data: preloadedPaymentMethods } = await useAsyncData(`payout/methods-preload`, async () => {
|
||||
const defaultCountry = userCountry.value || 'US'
|
||||
try {
|
||||
return {
|
||||
country: defaultCountry,
|
||||
methods: (await useBaseFetch('payout/methods', {
|
||||
apiVersion: 3,
|
||||
query: { country: defaultCountry },
|
||||
})) as PayoutMethod[],
|
||||
const { data: preloadedPaymentMethods } = useQuery({
|
||||
queryKey: computed(() => ['payout', 'methods-preload', userCountry.value]),
|
||||
queryFn: async () => {
|
||||
const defaultCountry = userCountry.value || 'US'
|
||||
try {
|
||||
return {
|
||||
country: defaultCountry,
|
||||
methods: (await useBaseFetch('payout/methods', {
|
||||
apiVersion: 3,
|
||||
query: { country: defaultCountry },
|
||||
})) as PayoutMethod[],
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const sortedPayouts = computed(() => {
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
v-for="transaction in transactions"
|
||||
:key="transaction.id || transaction.created"
|
||||
:transaction="transaction"
|
||||
@cancelled="refresh"
|
||||
@cancelled="refetch"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -97,6 +97,7 @@ import {
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { capitalizeString } from '@modrinth/utils'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import RevenueTransaction from '~/components/ui/dashboard/RevenueTransaction.vue'
|
||||
@@ -116,11 +117,13 @@ useHead({
|
||||
title: 'Transaction history - Modrinth',
|
||||
})
|
||||
|
||||
const { data: transactions, refresh } = await useAsyncData(`payout-history`, () =>
|
||||
useBaseFetch(`payout/history`, {
|
||||
apiVersion: 3,
|
||||
}),
|
||||
)
|
||||
const { data: transactions, refetch } = useQuery({
|
||||
queryKey: ['payout', 'history'],
|
||||
queryFn: () =>
|
||||
useBaseFetch(`payout/history`, {
|
||||
apiVersion: 3,
|
||||
}),
|
||||
})
|
||||
|
||||
const allTransactions = computed(() => {
|
||||
if (!transactions.value) return []
|
||||
|
||||
Reference in New Issue
Block a user