This repository has no description
1<script lang="ts">
2 import { untrack } from "svelte";
3 import { getAuth } from "$lib/auth.svelte";
4 import { createBobbinClient } from "$lib/api/client";
5 import FollowCard from "../FollowCard.svelte";
6 import Section from "$lib/components/ui/Section.svelte";
7 import Pagination from "$lib/components/ui/Pagination.svelte";
8 import Error from "$lib/components/ui/Error.svelte";
9 import { createCursorPager, pageCount } from "../pagination.svelte";
10 import { PROFILE_PAGE_LIMIT, fetchPeoplePage } from "../pages";
11 import type { PersonData } from "../types";
12
13 interface Props {
14 initial: PersonData[];
15 cursor?: string;
16 total: number;
17 did: string;
18 direction: "followers" | "following";
19 title: string;
20 emptyMessage: string;
21 }
22
23 let {
24 initial,
25 cursor: initialCursor,
26 total,
27 did,
28 direction,
29 title,
30 emptyMessage
31 }: Props = $props();
32
33 const auth = getAuth();
34
35 const pager = createCursorPager(
36 { items: untrack(() => initial), cursor: untrack(() => initialCursor) },
37 (cursor) => {
38 const ctx = createBobbinClient({ serviceUrl: auth.bobbinUrl });
39 return fetchPeoplePage(ctx, {
40 did,
41 viewerDid: auth.currentDid ?? undefined,
42 direction,
43 cursor
44 });
45 }
46 );
47 const people = $derived(pager.items);
48 const pages = $derived(pageCount(total, PROFILE_PAGE_LIMIT));
49</script>
50
51<Section {title} empty={people.length === 0} {emptyMessage} listClass="flex flex-col gap-8">
52 {#each people as person (person.did)}
53 <FollowCard {person} />
54 {/each}
55 {#snippet footer()}
56 {#if pages > 1}
57 <div class="mt-4 flex justify-center">
58 <Pagination
59 page={pager.state.page}
60 total={pages}
61 labels
62 disabled={pager.state.kind === "loading"}
63 onchange={pager.select}
64 class="gap-5"
65 />
66 </div>
67 {/if}
68 {#if pager.state.kind === "failed"}
69 <Error label="couldn't load that page. try again." class="mt-2" />
70 {/if}
71 {/snippet}
72</Section>