port profile and explore pages to useInfiniteLoader
This commit is contained in:
parent
1933391d38
commit
133cd9ec5b
3 changed files with 57 additions and 66 deletions
|
|
@ -1,11 +1,12 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { createInfiniteQuery } from '@tanstack/svelte-query'
|
||||
import ExploreGrid from '$lib/components/explore/ExploreGrid.svelte'
|
||||
import ProfileHeader from '$lib/components/profile/ProfileHeader.svelte'
|
||||
import { userQueries } from '$lib/api/queries/user.queries'
|
||||
import { crewStore } from '$lib/stores/crew.store.svelte'
|
||||
import { IsInViewport } from 'runed'
|
||||
import { useInfiniteLoader } from '$lib/stores/loaderState.svelte'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
import PageMeta from '$lib/components/PageMeta.svelte'
|
||||
|
|
@ -18,6 +19,8 @@
|
|||
const viewerCrewRole = $derived(crewStore.membership?.role ?? null)
|
||||
const viewerCrewId = $derived(crewStore.crew?.id ?? null)
|
||||
|
||||
let sentinelEl = $state<HTMLElement>()
|
||||
|
||||
const partiesQuery = createInfiniteQuery(() => ({
|
||||
...userQueries.parties(data.user?.username ?? ''),
|
||||
enabled: !!data.user?.username,
|
||||
|
|
@ -38,30 +41,18 @@
|
|||
initialDataUpdatedAt: 0
|
||||
}))
|
||||
|
||||
// State-gated infinite scroll
|
||||
const loader = useInfiniteLoader(() => partiesQuery, () => sentinelEl, { rootMargin: '300px' })
|
||||
|
||||
// Cleanup on destroy
|
||||
onDestroy(() => loader.destroy())
|
||||
|
||||
const items = $derived(() => {
|
||||
if (!partiesQuery.data?.pages) return data.items || []
|
||||
return partiesQuery.data.pages.flatMap((page) => page.results ?? [])
|
||||
})
|
||||
|
||||
const isEmpty = $derived(!partiesQuery.isLoading && items().length === 0)
|
||||
const showSentinel = $derived(partiesQuery.hasNextPage && !partiesQuery.isFetchingNextPage)
|
||||
|
||||
let sentinelEl = $state<HTMLElement>()
|
||||
|
||||
const inViewport = new IsInViewport(() => sentinelEl, {
|
||||
rootMargin: '300px'
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if (
|
||||
inViewport.current &&
|
||||
partiesQuery.hasNextPage &&
|
||||
!partiesQuery.isFetchingNextPage &&
|
||||
!partiesQuery.isLoading
|
||||
) {
|
||||
partiesQuery.fetchNextPage()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<PageMeta
|
||||
|
|
@ -104,9 +95,11 @@
|
|||
<div class="profile-grid">
|
||||
<ExploreGrid items={items()} />
|
||||
|
||||
{#if showSentinel}
|
||||
<div class="load-more-sentinel" bind:this={sentinelEl}></div>
|
||||
{/if}
|
||||
<div
|
||||
class="load-more-sentinel"
|
||||
bind:this={sentinelEl}
|
||||
class:hidden={!partiesQuery.hasNextPage}
|
||||
></div>
|
||||
|
||||
{#if partiesQuery.isFetchingNextPage}
|
||||
<div class="loading-more">
|
||||
|
|
@ -169,6 +162,10 @@
|
|||
.load-more-sentinel {
|
||||
height: 1px;
|
||||
margin-top: $unit;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-more {
|
||||
|
|
|
|||
|
|
@ -2,42 +2,33 @@
|
|||
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { createInfiniteQuery } from '@tanstack/svelte-query'
|
||||
import ExploreGrid from '$lib/components/explore/ExploreGrid.svelte'
|
||||
import ProfileHeader from '$lib/components/profile/ProfileHeader.svelte'
|
||||
import { userQueries } from '$lib/api/queries/user.queries'
|
||||
import { IsInViewport } from 'runed'
|
||||
import { useInfiniteLoader } from '$lib/stores/loaderState.svelte'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
|
||||
const { data }: { data: PageData } = $props()
|
||||
|
||||
let sentinelEl = $state<HTMLElement>()
|
||||
|
||||
const favoritesQuery = createInfiniteQuery(() => userQueries.favorites())
|
||||
|
||||
// State-gated infinite scroll
|
||||
const loader = useInfiniteLoader(() => favoritesQuery, () => sentinelEl, { rootMargin: '300px' })
|
||||
|
||||
// Cleanup on destroy
|
||||
onDestroy(() => loader.destroy())
|
||||
|
||||
const items = $derived(() => {
|
||||
if (!favoritesQuery.data?.pages) return []
|
||||
return favoritesQuery.data.pages.flatMap((page) => page.items ?? [])
|
||||
})
|
||||
|
||||
const isEmpty = $derived(!favoritesQuery.isLoading && items().length === 0)
|
||||
const showSentinel = $derived(favoritesQuery.hasNextPage && !favoritesQuery.isFetchingNextPage)
|
||||
|
||||
let sentinelEl = $state<HTMLElement>()
|
||||
|
||||
const inViewport = new IsInViewport(() => sentinelEl, {
|
||||
rootMargin: '300px'
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if (
|
||||
inViewport.current &&
|
||||
favoritesQuery.hasNextPage &&
|
||||
!favoritesQuery.isFetchingNextPage &&
|
||||
!favoritesQuery.isLoading
|
||||
) {
|
||||
favoritesQuery.fetchNextPage()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
|
@ -77,9 +68,11 @@
|
|||
<div class="profile-grid">
|
||||
<ExploreGrid items={items()} />
|
||||
|
||||
{#if showSentinel}
|
||||
<div class="load-more-sentinel" bind:this={sentinelEl}></div>
|
||||
{/if}
|
||||
<div
|
||||
class="load-more-sentinel"
|
||||
bind:this={sentinelEl}
|
||||
class:hidden={!favoritesQuery.hasNextPage}
|
||||
></div>
|
||||
|
||||
{#if favoritesQuery.isFetchingNextPage}
|
||||
<div class="loading-more">
|
||||
|
|
@ -142,6 +135,10 @@
|
|||
.load-more-sentinel {
|
||||
height: 1px;
|
||||
margin-top: $unit;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-more {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { createInfiniteQuery } from '@tanstack/svelte-query'
|
||||
import ExploreGrid from '$lib/components/explore/ExploreGrid.svelte'
|
||||
import { partyQueries } from '$lib/api/queries/party.queries'
|
||||
import { IsInViewport } from 'runed'
|
||||
import { useInfiniteLoader } from '$lib/stores/loaderState.svelte'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
import PageMeta from '$lib/components/PageMeta.svelte'
|
||||
|
|
@ -11,6 +12,8 @@
|
|||
|
||||
const { data } = $props() as { data: PageData }
|
||||
|
||||
let sentinelEl = $state<HTMLElement>()
|
||||
|
||||
const partiesQuery = createInfiniteQuery(() => ({
|
||||
...partyQueries.list(),
|
||||
initialData: data.items
|
||||
|
|
@ -30,29 +33,17 @@
|
|||
initialDataUpdatedAt: 0
|
||||
}))
|
||||
|
||||
// State-gated infinite scroll
|
||||
const loader = useInfiniteLoader(() => partiesQuery, () => sentinelEl, { rootMargin: '300px' })
|
||||
|
||||
// Cleanup on destroy
|
||||
onDestroy(() => loader.destroy())
|
||||
|
||||
const items = $derived(
|
||||
partiesQuery.data?.pages.flatMap((page) => page.results) ?? data.items ?? []
|
||||
)
|
||||
|
||||
const isEmpty = $derived(!partiesQuery.isLoading && items.length === 0)
|
||||
const showSentinel = $derived(partiesQuery.hasNextPage && !partiesQuery.isFetchingNextPage)
|
||||
|
||||
let sentinelEl = $state<HTMLElement>()
|
||||
|
||||
const inViewport = new IsInViewport(() => sentinelEl, {
|
||||
rootMargin: '300px'
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if (
|
||||
inViewport.current &&
|
||||
partiesQuery.hasNextPage &&
|
||||
!partiesQuery.isFetchingNextPage &&
|
||||
!partiesQuery.isLoading
|
||||
) {
|
||||
partiesQuery.fetchNextPage()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<PageMeta title={m.page_title_teams()} description={m.page_desc_teams()} />
|
||||
|
|
@ -81,9 +72,11 @@
|
|||
<div class="explore-grid">
|
||||
<ExploreGrid items={items} />
|
||||
|
||||
{#if showSentinel}
|
||||
<div class="load-more-sentinel" bind:this={sentinelEl}></div>
|
||||
{/if}
|
||||
<div
|
||||
class="load-more-sentinel"
|
||||
bind:this={sentinelEl}
|
||||
class:hidden={!partiesQuery.hasNextPage}
|
||||
></div>
|
||||
|
||||
{#if partiesQuery.isFetchingNextPage}
|
||||
<div class="loading-more">
|
||||
|
|
@ -150,6 +143,10 @@
|
|||
.load-more-sentinel {
|
||||
height: 1px;
|
||||
margin-top: $unit;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-more {
|
||||
|
|
|
|||
Loading…
Reference in a new issue