Skip to content

Commit

Permalink
tweak: improve pagination logic and UX
Browse files Browse the repository at this point in the history
  • Loading branch information
Draconizations committed Oct 4, 2024
1 parent 3c2791c commit 444f53a
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 148 deletions.
183 changes: 140 additions & 43 deletions src/components/dash/Pagination.svelte
Original file line number Diff line number Diff line change
@@ -1,93 +1,190 @@
<script lang="ts">
import type { Group, Member } from "$api/types"
import { browser } from "$app/environment"
import type { DashList } from "$lib/dash/dash.svelte"
let {
list = $bindable(),
class: className = "",
class: className,
itemsPerPage,
rawList,
size = "xs",
currentPage = $bindable(),
paginate,
}: {
list: DashList<Group | Member>
itemsPerPage: number
class?: string
rawList: any[]
currentPage: number
size?: "sm" | "xs"
paginate?: () => void
} = $props()
let pageAmount = $derived(Math.ceil(list.list.processed.length / list.settings.itemsPerPage))
let pageAmount = $derived(Math.ceil(rawList.length / itemsPerPage))
function jumpToPage() {
if (browser) {
let page = parseInt(window.prompt("Jump to the following page") || "nope")
if (!isNaN(page)) list.settings.currentPage = page
list.paginate()
if (!isNaN(page)) goToPage(page)
}
}
function goToPage(page: number) {
list.settings.currentPage = page
list.paginate()
currentPage = page
if (paginate) paginate()
}
</script>

<nav class={`join ${className}`} aria-label="List pagination">
{#if pageAmount > 0}
<button
aria-label="Go to page 1"
class={`btn btn-sm join-item ${
list.settings.currentPage === 1 ? "btn-primary" : "btn-neutral"
}`}
onclick={() => goToPage(1)}
>
1
</button>
{#if list.settings.currentPage > 3}
{#if pageAmount > 1}
<!-- first page (visible if 1 < previous page)-->
{#if 1 < currentPage - 1}
<button
aria-label={`Go to first page (page 1)`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(1)}
>
1
</button>
{/if}

<!-- second page
visible if previous page > 2 AND skip backward ISN'T visible
- OR -
skip fowards + 1 isn't visible
ALWAYS invisible if there's less than 4 pages and we're not on page 4
-->
{#if (pageAmount > 4 || currentPage === 4) && ((currentPage - 1 > 2 && !(currentPage - 1 > 3)) || !(currentPage + 1 < pageAmount - 1))}
<button
aria-label={`Go to second page (page 2)`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(2)}
>
2
</button>
{/if}

<!-- third page, only visible if we're on the last two pages AND there's more than 5 pages-->
{#if currentPage > pageAmount - 2 && pageAmount > 5}
<button
aria-label={`Go to third page (page 3)`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(3)}
>
3
</button>
{/if}

<!-- skip backward (visible if previous page > third page) AND there's more than 6 pages -->
{#if currentPage - 1 > 3 && pageAmount > 6}
<button
aria-label="Jump to any page"
class="btn btn-sm btn-neutral join-item"
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => jumpToPage()}
>
...
</button>
{/if}
{#if list.settings.currentPage > 2}

<!-- third to last page
ONLY visible if we're on the last page
-->
{#if currentPage === pageAmount}
<button
aria-label={`Go to third page (page ${pageAmount - 2})`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(pageAmount - 2)}
>
{pageAmount - 2}
</button>
{/if}

{#if pageAmount > 1}
<!-- previous page (visible if we're not on first page)-->
{#if currentPage != 1}
<button
aria-label={`Go to previous page (page ${currentPage - 1})`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(currentPage - 1)}
>
{currentPage - 1}
</button>
{/if}

<!-- Current page (always visible)-->
<button
aria-label={`Go to page ${list.settings.currentPage - 1}`}
class="btn btn-sm btn-neutral join-item"
onclick={() => goToPage(list.settings.currentPage - 1)}
aria-label={`Go to current page (page ${currentPage})`}
class={`btn btn-${size} join-item btn-primary`}
onclick={() => goToPage(currentPage)}
>
{list.settings.currentPage - 1}
{currentPage}
</button>
{/if}
{#if list.settings.currentPage > 1 && list.settings.currentPage < pageAmount}

<!-- next page (visible if we're not on the last page)-->
{#if currentPage < pageAmount}
<button
aria-label={`Page ${list.settings.currentPage} (current page)`}
class="btn btn-sm join-item btn-primary"
aria-label={`Go to next page (page ${currentPage + 1})`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(currentPage + 1)}
>
{list.settings.currentPage}
{currentPage + 1}
</button>
{/if}
{#if (list.settings.currentPage < pageAmount - 1 && pageAmount > 3) || (list.settings.currentPage === 1 && pageAmount === 3)}
<!-- third page
ONLY visible if there's more than 3 pages and we're on page 1
-->
{#if currentPage === 1 && pageAmount > 3}
<button
aria-label={`Go to page ${list.settings.currentPage + 1}`}
class="btn btn-sm btn-neutral join-item"
onclick={() => goToPage(list.settings.currentPage + 1)}
aria-label={`Go to third page (page 3)`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(3)}
>
{list.settings.currentPage + 1}
3
</button>
{/if}
{#if list.settings.currentPage < pageAmount - 2 && pageAmount > 3}

<!-- skip forward (visible if next page < third to last page) AND there's more than 6 pages -->
{#if currentPage + 1 < pageAmount - 2 && pageAmount > 6}
<button
aria-label="Jump to any page"
class="btn btn-sm btn-neutral join-item"
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => jumpToPage()}
>
...
</button>
{/if}
{#if pageAmount > 1}

<!-- third to last page, only visible if we're on the first two pages AND there's more than 5 pages-->
{#if currentPage < 3 && pageAmount > 5}
<button
aria-label={`Go to third to last page (page ${pageAmount - 2})`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(pageAmount - 2)}
>
{pageAmount - 2}
</button>
{/if}

<!-- second to last page
visible if next page < second to last page AND skip forward ISN'T visible
OR
visible if skip backwards - 1 isn't visible
always invisible if there's less than 5 pages and we're not on page 1
-->
{#if (pageAmount > 4 || currentPage === 1) && ((currentPage + 1 < pageAmount - 1 && !(currentPage + 1 < pageAmount - 2)) || !(currentPage - 1 > 2))}
<button
aria-label={`Go to second to last page ${pageAmount - 1}`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(pageAmount - 1)}
>
{pageAmount - 1}
</button>
{/if}

<!-- last page (visible if last page > next page)-->
{#if pageAmount > currentPage + 1}
<button
aria-label={`Go to page ${pageAmount} (last page)`}
class={`btn btn-sm join-item ${
list.settings.currentPage === pageAmount ? "btn-primary" : "btn-neutral"
}`}
aria-label={`Go to next page (page ${pageAmount})`}
class={`btn btn-${size} join-item btn-neutral`}
onclick={() => goToPage(pageAmount)}
>
{pageAmount}
Expand Down
93 changes: 0 additions & 93 deletions src/components/dash/SimplePagination.svelte

This file was deleted.

18 changes: 16 additions & 2 deletions src/components/dash/groups/GroupList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@
>
</p>
</div>
<Pagination class="mx-auto" bind:list />
<Pagination
class="mx-auto"
size="sm"
rawList={list.list.processed}
paginate={list.paginate}
itemsPerPage={list.settings.itemsPerPage}
bind:currentPage={list.settings.currentPage}
/>
{#if list.settings.view.type === ViewType.COLLAPSE || list.settings.view.type === ViewType.OPEN}
{#each list.list.paginated as group (group.uuid)}
<ItemCollapse
Expand All @@ -74,4 +81,11 @@
{#if list.list.processed.length === 0}
<div class="alert bg-info/20 flex flex-col text-center">No groups found.</div>
{/if}
<Pagination class="mx-auto" bind:list />
<Pagination
class="mx-auto"
size="sm"
rawList={list.list.processed}
paginate={list.paginate}
itemsPerPage={list.settings.itemsPerPage}
bind:currentPage={list.settings.currentPage}
/>
4 changes: 2 additions & 2 deletions src/components/dash/groups/GroupMembers.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { Group, Member } from "$api/types"
import { PrivacyMode, dash, type DashList } from "$lib/dash/dash.svelte"
import { IconEdit } from "@tabler/icons-svelte"
import SimplePagination from "../SimplePagination.svelte"
import Pagination from "../Pagination.svelte"
import GroupLink from "./GroupLink.svelte"
import GroupMemberEdit from "./edit/GroupMemberEdit.svelte"
import GroupMemberList from "./GroupMemberList.svelte"
Expand Down Expand Up @@ -49,7 +49,7 @@
<h5 class="text-lg mb-2">Member info</h5>
<div class="flex flex-row justify-between gap-2 items-start">
<p class="mb-3">{members.length} total members</p>
<SimplePagination {itemsPerPage} rawList={members} bind:currentPage />
<Pagination {itemsPerPage} rawList={members} bind:currentPage />
</div>
<GroupMemberList {members} bind:currentPage {itemsPerPage} />
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/dash/groups/create/GroupMemberCreate.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { Member } from "$api/types"
import SimplePagination from "$components/dash/SimplePagination.svelte"
import Pagination from "$components/dash/Pagination.svelte"
import type { DashList } from "$lib/dash/dash.svelte"
import { IconPlus, IconRefresh } from "@tabler/icons-svelte"
import Svelecte from "svelecte"
Expand Down Expand Up @@ -111,7 +111,7 @@
</div>
<div class="bg-base-100 flex-1 rounded-box p-4 gap-2 flex flex-col">
<h5 class="text-lg">Member list</h5>
<SimplePagination {itemsPerPage} rawList={selectedMembers} bind:currentPage />
<Pagination {itemsPerPage} rawList={selectedMembers} bind:currentPage />
<GroupMemberList members={selectedMembers} bind:currentPage {itemsPerPage} small={true} />
</div>
</div>
Expand Down
Loading

0 comments on commit 444f53a

Please sign in to comment.