add generic components for table sorting
This commit is contained in:
parent
9ababd4847
commit
9be57c1004
src
35
src/lib/components/Table/SortableTh.svelte
Normal file
35
src/lib/components/Table/SortableTh.svelte
Normal file
@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, getContext, onDestroy } from 'svelte';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { IconSolid } from 'svelte-heros-v2';
|
||||
|
||||
let id = crypto.randomUUID();
|
||||
let asc = false;
|
||||
let { ascHeader } = getContext('sortableTr') as { ascHeader: Writable<null | string> };
|
||||
ascHeader.subscribe((v) => {
|
||||
if (v !== id) asc = false;
|
||||
});
|
||||
|
||||
let dispatch = createEventDispatcher();
|
||||
|
||||
onDestroy(() => {
|
||||
if ($ascHeader === id) $ascHeader = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<th>
|
||||
<button
|
||||
class="flex flex-center"
|
||||
on:click={() => {
|
||||
dispatch('sort', { asc: (asc = !asc) });
|
||||
$ascHeader = id;
|
||||
}}
|
||||
>
|
||||
<span class="mr-1"><slot /></span>
|
||||
<IconSolid
|
||||
name={$ascHeader === id && asc ? 'chevron-up-solid' : 'chevron-down-solid'}
|
||||
width="12"
|
||||
height="12"
|
||||
/>
|
||||
</button>
|
||||
</th>
|
12
src/lib/components/Table/SortableTr.svelte
Normal file
12
src/lib/components/Table/SortableTr.svelte
Normal file
@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
setContext('sortableTr', {
|
||||
ascHeader: writable(null)
|
||||
});
|
||||
</script>
|
||||
|
||||
<tr {...$$restProps}>
|
||||
<slot />
|
||||
</tr>
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { IconOutline, IconSolid } from 'svelte-heros-v2';
|
||||
import { IconOutline } from 'svelte-heros-v2';
|
||||
import Input from '$lib/components/Input/Input.svelte';
|
||||
import Select from '$lib/components/Input/Select.svelte';
|
||||
import { env } from '$env/dynamic/public';
|
||||
@ -8,41 +8,11 @@
|
||||
import { buttonTriggeredRequest } from '$lib/components/utils';
|
||||
import { browser } from '$app/environment';
|
||||
import HeaderBar from './HeaderBar.svelte';
|
||||
import SortableTr from '$lib/components/Table/SortableTr.svelte';
|
||||
import SortableTh from '$lib/components/Table/SortableTh.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let headers = [
|
||||
{
|
||||
name: 'Vorname',
|
||||
key: 'firstname',
|
||||
asc: false
|
||||
},
|
||||
{
|
||||
name: 'Nachname',
|
||||
key: 'lastname',
|
||||
asc: false
|
||||
},
|
||||
{ name: 'Geburtstag', key: 'birthday', asc: false, sort: (a, b) => a.birthday - b.birthday },
|
||||
{ name: 'Telefon', key: 'telephone', asc: false, sort: (a, b) => a.telephone - b.telephone },
|
||||
{
|
||||
name: 'Username',
|
||||
key: 'username',
|
||||
asc: false
|
||||
},
|
||||
{
|
||||
name: 'Minecraft Edition',
|
||||
key: 'playertype',
|
||||
asc: false
|
||||
},
|
||||
{
|
||||
name: 'Passwort',
|
||||
key: 'password',
|
||||
asc: false
|
||||
},
|
||||
{ name: 'UUID', key: 'uuid', asc: false }
|
||||
];
|
||||
let ascHeader: (typeof headers)[0] | null = null;
|
||||
|
||||
let currentPageUsers: (typeof User.prototype.dataValues)[] = [];
|
||||
let currentPageUsersRequest: Promise<void> = new Promise((resolve) => resolve());
|
||||
let usersPerPage = 50;
|
||||
@ -70,12 +40,19 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function sortUsers(key: string, reverse: boolean) {
|
||||
const multiplyValue = reverse ? -1 : 1;
|
||||
$: fetchPageUsers(userPage, userFilter);
|
||||
|
||||
currentPageUsers.sort((entryA, entryB) => {
|
||||
const a = entryA[key];
|
||||
const b = entryB[key];
|
||||
let sortKey: string | null = null;
|
||||
let sortAsc = false;
|
||||
$: if (sortKey != null)
|
||||
currentPageUsers = currentPageUsers.sort((entryA, entryB) => {
|
||||
const multiplyValue = sortAsc ? -1 : 1;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const a = entryA[sortKey];
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const b = entryB[sortKey];
|
||||
|
||||
switch (typeof a) {
|
||||
case 'number':
|
||||
@ -86,10 +63,6 @@
|
||||
return (a - b) * multiplyValue;
|
||||
}
|
||||
});
|
||||
currentPageUsers = currentPageUsers;
|
||||
}
|
||||
|
||||
$: fetchPageUsers(userPage, userFilter);
|
||||
|
||||
async function updateUser(user: typeof User.prototype.dataValues) {
|
||||
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
|
||||
@ -126,29 +99,19 @@
|
||||
<div class="h-full overflow-scroll" bind:this={userTableContainerElement}>
|
||||
<table class="table table-auto">
|
||||
<thead>
|
||||
<tr class="[&>th]:bg-base-100 [&>th]:z-[1] [&>th]:sticky [&>th]:top-0">
|
||||
<!-- prettier-ignore -->
|
||||
<SortableTr class="[&>th]:bg-base-100 [&>th]:z-[1] [&>th]:sticky [&>th]:top-0">
|
||||
<th />
|
||||
{#each headers as header}
|
||||
<th>
|
||||
<button
|
||||
class="flex items-center"
|
||||
on:click={() => {
|
||||
sortUsers(header.key, (ascHeader = ascHeader == header ? null : header));
|
||||
}}
|
||||
>
|
||||
{header.name}
|
||||
<span class="ml-1">
|
||||
<IconSolid
|
||||
name={ascHeader === header ? 'chevron-up-solid' : 'chevron-down-solid'}
|
||||
width="12"
|
||||
height="12"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</th>
|
||||
{/each}
|
||||
<SortableTh on:sort={(e) => { sortKey = 'firstname'; sortAsc = e.detail.asc }}>Vorname</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'lastname'; sortAsc = e.detail.asc }}>Nachname</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'birthday'; sortAsc = e.detail.asc }}>Geburtstag</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'telephone'; sortAsc = e.detail.asc }}>Telefon</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'username'; sortAsc = e.detail.asc }}>Username</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'playertype'; sortAsc = e.detail.asc }}>Minecraft Edition</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'password'; sortAsc = e.detail.asc }}>Passwort</SortableTh>
|
||||
<SortableTh on:sort={(e) => { sortKey = 'uuid'; sortAsc = e.detail.asc }}>UUID</SortableTh>
|
||||
<th />
|
||||
</tr>
|
||||
</SortableTr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#key currentPageUsersRequest}
|
||||
|
Loading…
x
Reference in New Issue
Block a user