Refactor player handling: replace player arrays with IDs, implement PlayerSelector component

This commit is contained in:
2025-12-02 22:23:55 +01:00
parent 7ec678ae7d
commit 5f5988e270
14 changed files with 332 additions and 304 deletions

View File

@@ -17,16 +17,132 @@
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script>
import Table from "@components/moderator/pages/players/Table.svelte";
<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";
import {dataRepo} from "@repo/data";
let debounceTimer: NodeJS.Timeout;
const debounce = <T,>(value: T, func: (value: T) => void) => {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
func(value);
}, 300);
};
let playersFuture = $state($dataRepo.getPlayers())
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, true).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>
{#await playersFuture}
<p>Loading...</p>
{:then players}
<Table data={players} />
{/await}
<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>