149 lines
5.6 KiB
Svelte
149 lines
5.6 KiB
Svelte
<!--
|
|
- This file is a part of the SteamWar software.
|
|
-
|
|
- Copyright (C) 2025 SteamWar.de-Serverteam
|
|
-
|
|
- This program is free software: you can redistribute it and/or modify
|
|
- it under the terms of the GNU Affero General Public License as published by
|
|
- the Free Software Foundation, either version 3 of the License, or
|
|
- (at your option) any later version.
|
|
-
|
|
- This program is distributed in the hope that it will be useful,
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- GNU Affero General Public License for more details.
|
|
-
|
|
- You should have received a copy of the GNU Affero General Public License
|
|
- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
-->
|
|
|
|
<script lang="ts">
|
|
import { createSvelteTable, FlexRender } from "@components/ui/data-table";
|
|
import { columns } from "./columns";
|
|
import { getCoreRowModel, getPaginationRowModel, type PaginationState } from "@tanstack/table-core";
|
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@components/ui/table";
|
|
import { dataRepo } from "@repo/data";
|
|
import type { Player } from "@type/data";
|
|
import { Button } from "@components/ui/button";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger } from "@components/ui/select";
|
|
import { Input } from "@components/ui/input";
|
|
|
|
let debounceTimer: NodeJS.Timeout;
|
|
const debounce = <T,>(value: T, func: (value: T) => void) => {
|
|
clearTimeout(debounceTimer);
|
|
debounceTimer = setTimeout(() => {
|
|
func(value);
|
|
}, 300);
|
|
};
|
|
|
|
let search = $state("");
|
|
|
|
let pagination = $state<PaginationState>({
|
|
pageIndex: 0,
|
|
pageSize: 25,
|
|
});
|
|
|
|
let data = $state<Player[]>([]);
|
|
let rows = $state(0);
|
|
|
|
$effect(() => {
|
|
$dataRepo.queryPlayers(search || undefined, undefined, undefined, pagination.pageSize, pagination.pageIndex, true, false).then((res) => {
|
|
data = res.entries;
|
|
rows = res.rows;
|
|
});
|
|
});
|
|
|
|
const table = createSvelteTable({
|
|
get data() {
|
|
return data;
|
|
},
|
|
columns,
|
|
state: {
|
|
get pagination() {
|
|
return pagination;
|
|
},
|
|
},
|
|
onPaginationChange: (updater) => {
|
|
if (typeof updater === "function") {
|
|
pagination = updater(pagination);
|
|
} else {
|
|
pagination = updater;
|
|
}
|
|
},
|
|
getCoreRowModel: getCoreRowModel(),
|
|
getPaginationRowModel: getPaginationRowModel(),
|
|
manualPagination: true,
|
|
get rowCount() {
|
|
return rows;
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<div class="p-4">
|
|
<div class="rounded border mb-4 p-2 flex lg:flex-row flex-col">
|
|
<Input
|
|
class="w-48 mr-2"
|
|
placeholder="Search players..."
|
|
value={search}
|
|
onchange={(e) =>
|
|
debounce(e.currentTarget.value, (v) => {
|
|
search = v;
|
|
})}
|
|
oninput={(e) =>
|
|
debounce(e.currentTarget.value, (v) => {
|
|
search = v;
|
|
})}
|
|
/>
|
|
</div>
|
|
<div class="rounded border">
|
|
<Table>
|
|
<TableHeader>
|
|
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
|
|
<TableRow>
|
|
{#each headerGroup.headers as header (header.id)}
|
|
<TableHead colspan={header.colSpan}>
|
|
{#if !header.isPlaceholder}
|
|
<FlexRender content={header.column.columnDef.header} context={header.getContext()} />
|
|
{/if}
|
|
</TableHead>
|
|
{/each}
|
|
</TableRow>
|
|
{/each}
|
|
</TableHeader>
|
|
<TableBody>
|
|
{#each table.getRowModel().rows as row (row.id)}
|
|
<TableRow>
|
|
{#each row.getVisibleCells() as cell (cell.id)}
|
|
<TableCell class="p-2 align-top">
|
|
<FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
|
|
</TableCell>
|
|
{/each}
|
|
</TableRow>
|
|
{:else}
|
|
<TableRow>
|
|
<TableCell colspan={columns.length} class="h-24 text-center">No players found.</TableCell>
|
|
</TableRow>
|
|
{/each}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-end space-x-2 py-4">
|
|
<div>
|
|
<Select type="single" value={pagination.pageSize.toString()} onValueChange={(e) => (pagination = { pageSize: +e, pageIndex: 0 })}>
|
|
<SelectTrigger>{pagination.pageSize}</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="5">5</SelectItem>
|
|
<SelectItem value="10">10</SelectItem>
|
|
<SelectItem value="25">25</SelectItem>
|
|
<SelectItem value="50">50</SelectItem>
|
|
<SelectItem value="100">100</SelectItem>
|
|
<SelectItem value="200">200</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<Button variant="outline" size="sm" onclick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>Previous</Button>
|
|
<Button variant="outline" size="sm" onclick={() => table.nextPage()} disabled={!table.getCanNextPage()}>Next</Button>
|
|
</div>
|
|
</div>
|