328 lines
10 KiB
Svelte
328 lines
10 KiB
Svelte
<script>
|
|
import { _ } from "svelte-i18n";
|
|
let tablePageCount = [25, 50, 100, 250, 500];
|
|
import { writable } from "svelte/store";
|
|
import {
|
|
createSvelteTable,
|
|
flexRender,
|
|
getCoreRowModel,
|
|
getFilteredRowModel,
|
|
getPaginationRowModel,
|
|
getSortedRowModel,
|
|
} from "@tanstack/svelte-table";
|
|
import {
|
|
RunnerService,
|
|
RunnerTeamService,
|
|
RunnerOrganizationService,
|
|
} from "@odit/lfk-client-js";
|
|
import store from "../../store";
|
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
|
import { onMount } from "svelte";
|
|
import InputElement from "../shared/InputElement.svelte";
|
|
import { groupFilter } from "../shared/tablefilters";
|
|
|
|
$: selected =
|
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
|
|
|
const columns = [
|
|
{
|
|
accessorKey: "id",
|
|
header: () => "id",
|
|
filterFn: `equalsString`,
|
|
},
|
|
{
|
|
accessorKey: "firstname",
|
|
header: () => $_("first-name"),
|
|
filterFn: `includesString`,
|
|
},
|
|
{
|
|
accessorKey: "lastname",
|
|
header: () => $_("last-name"),
|
|
filterFn: `includesString`,
|
|
},
|
|
{
|
|
accessorKey: "group",
|
|
header: () => $_("group"),
|
|
cell: (info) => {
|
|
const group = info.getValue();
|
|
if (group.responseType === "RUNNERORGANIZATION") {
|
|
return group.name;
|
|
}
|
|
return `${group.parentGroup.name} > ${group.name}`;
|
|
},
|
|
filterFn: `group`,
|
|
},
|
|
{
|
|
accessorKey: "distance",
|
|
header: () => $_("distance"),
|
|
cell: (info) => {
|
|
if (info.getValue() < 1000) {
|
|
return `${info.getValue()} m`;
|
|
}
|
|
return `${(info.getValue() / 1000).toFixed(1)} km`;
|
|
},
|
|
enableColumnFilter: false,
|
|
},
|
|
];
|
|
|
|
//
|
|
|
|
$: active_deletes = [];
|
|
let dataLoaded = false;
|
|
export let current_runners = [];
|
|
$: sponsoring_contracts_show = selected.length > 0;
|
|
$: cards_show = selected.length > 0;
|
|
$: certificates_show = selected.length > 0;
|
|
$: generate_runners = []; //current_runners.filter((r) => r.selected === true);
|
|
$: teams = [];
|
|
$: orgs = [];
|
|
$: mappedteams = teams.map(function (g) {
|
|
return { value: g.id, label: g.parentGroup.name + " > " + g.name };
|
|
});
|
|
$: selectgroups = orgs
|
|
.map(function (g) {
|
|
return { value: g.id, label: g.name };
|
|
})
|
|
.concat(mappedteams);
|
|
const options = writable({
|
|
data: [],
|
|
columns: columns,
|
|
filterFns: {
|
|
group: groupFilter,
|
|
},
|
|
initialState: {
|
|
pagination: {
|
|
pageSize: 50,
|
|
},
|
|
},
|
|
enableRowSelection: true,
|
|
getCoreRowModel: getCoreRowModel(),
|
|
getFilteredRowModel: getFilteredRowModel(),
|
|
getPaginationRowModel: getPaginationRowModel(),
|
|
getSortedRowModel: getSortedRowModel(),
|
|
});
|
|
const table = createSvelteTable(options);
|
|
onMount(() => {
|
|
RunnerService.runnerControllerGetAll().then((val) => {
|
|
current_runners = val;
|
|
dataLoaded = true;
|
|
|
|
options.update((options) => ({
|
|
...options,
|
|
data: current_runners,
|
|
}));
|
|
});
|
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
|
teams = val;
|
|
});
|
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
|
(val) => {
|
|
orgs = val;
|
|
}
|
|
);
|
|
});
|
|
</script>
|
|
|
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
|
{#if !dataLoaded}
|
|
<div
|
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
|
role="alert"
|
|
>
|
|
<p class="font-bold">{$_("runners-are-being-loaded")}</p>
|
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
|
</div>
|
|
{:else}
|
|
<div class="h-12 mt-2">
|
|
<GenerateSponsoringContracts
|
|
bind:sponsoring_contracts_show
|
|
bind:generate_runners
|
|
/>
|
|
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
|
<GenerateRunnerCertificates
|
|
bind:certificates_show
|
|
bind:generate_runners
|
|
/>
|
|
</div>
|
|
<table class="w-full">
|
|
<thead>
|
|
{#each $table.getHeaderGroups() as headerGroup}
|
|
<tr class="select-none">
|
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
|
<InputElement
|
|
type="checkbox"
|
|
checked={$table.getIsAllRowsSelected()}
|
|
indeterminate={$table.getIsSomeRowsSelected()}
|
|
on:change={() => $table.toggleAllRowsSelected()}
|
|
/>
|
|
</th>
|
|
{#each headerGroup.headers as header}
|
|
<th class="cursor-pointer">
|
|
{#if !header.isPlaceholder}
|
|
<div on:click={header.column.getToggleSortingHandler()}>
|
|
<svelte:component
|
|
this={flexRender(
|
|
header.column.columnDef.header,
|
|
header.getContext()
|
|
)}
|
|
/>
|
|
{#if header.column.getIsSorted().toString() == "asc"}
|
|
🔼
|
|
{:else if header.column.getIsSorted().toString() == "desc"}
|
|
🔽
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
{#if header.column.getCanFilter()}
|
|
<div class="relative max-w-xs">
|
|
<input
|
|
title="name-search"
|
|
value={header.column.getFilterValue() || ""}
|
|
on:keyup={(e) => {
|
|
header.column.setFilterValue(e.target.value);
|
|
}}
|
|
type="text"
|
|
class="block rounded-md border-gray-200 py-2 pl-8 text-xs focus:border-blue-500 focus:ring-blue-500"
|
|
placeholder=""
|
|
/>
|
|
<div
|
|
class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-2"
|
|
>
|
|
<svg
|
|
class="h-3.5 w-3.5 text-gray-400"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width={16}
|
|
height={16}
|
|
fill="currentColor"
|
|
viewBox="0 0 16 16"
|
|
>
|
|
<path
|
|
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</th>
|
|
{/each}
|
|
</tr>
|
|
{/each}
|
|
</thead>
|
|
<tbody>
|
|
{#each $table.getRowModel().rows as row}
|
|
<tr>
|
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
|
<InputElement
|
|
type="checkbox"
|
|
checked={row.getIsSelected()}
|
|
on:change={() => row.toggleSelected()}
|
|
/>
|
|
</td>
|
|
{#each row.getVisibleCells() as cell}
|
|
<td>
|
|
<svelte:component
|
|
this={flexRender(
|
|
cell.column.columnDef.cell,
|
|
cell.getContext()
|
|
)}
|
|
/>
|
|
</td>
|
|
{/each}
|
|
</tr>
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
<div class="h-2" />
|
|
<div class="flex items-center gap-2">
|
|
<button
|
|
class="border rounded p-1"
|
|
on:click={() => $table.setPageIndex(0)}
|
|
disabled={!$table.getCanPreviousPage()}
|
|
>
|
|
{"<<"}
|
|
</button>
|
|
<button
|
|
class="border rounded p-1"
|
|
on:click={() => $table.previousPage()}
|
|
disabled={!$table.getCanPreviousPage()}
|
|
>
|
|
{"<"}
|
|
</button>
|
|
<button
|
|
class="border rounded p-1"
|
|
on:click={() => $table.nextPage()}
|
|
disabled={!$table.getCanNextPage()}
|
|
>
|
|
{">"}
|
|
</button>
|
|
<button
|
|
class="border rounded p-1"
|
|
on:click={() => $table.setPageIndex($table.getPageCount() - 1)}
|
|
disabled={!$table.getCanNextPage()}
|
|
>
|
|
{">>"}
|
|
</button>
|
|
<span class="flex items-center gap-1">
|
|
<div>Page</div>
|
|
<strong>
|
|
{$table.getState().pagination.pageIndex + 1} of{" "}
|
|
{$table.getPageCount()}
|
|
</strong>
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
| Go to page:
|
|
<input
|
|
type="number"
|
|
defaultValue={$table.getState().pagination.pageIndex + 1}
|
|
on:change={(e) => {
|
|
const page = e.target.value ? Number(e.target.value) - 1 : 0;
|
|
$table.setPageIndex(page);
|
|
}}
|
|
class="border p-1 rounded w-16"
|
|
/>
|
|
</span>
|
|
<select
|
|
value={$table.getState().pagination.pageSize}
|
|
on:input={(e) => {
|
|
const ps = Number(e.target.value);
|
|
console.log({ ps });
|
|
$table.setPageSize(Number(e.target.value));
|
|
}}
|
|
>
|
|
{#each tablePageCount as pageSize}
|
|
<option value={pageSize}>{pageSize}</option>
|
|
{/each}
|
|
</select>
|
|
</div>
|
|
<!-- <pre>{JSON.stringify($table.getState(), null, 2)}</pre> -->
|
|
<div>
|
|
{Object.keys(selected).length} of{" "}
|
|
{$table.getPreFilteredRowModel().rows.length} Total Rows Selected
|
|
</div>
|
|
{/if}
|
|
{/if}
|
|
|
|
<style>
|
|
thead {
|
|
background: #fff;
|
|
}
|
|
thead {
|
|
position: sticky;
|
|
inset-block-start: 0;
|
|
}
|
|
tbody td {
|
|
padding: 4px;
|
|
}
|
|
tbody tr:nth-child(even) {
|
|
background: #fafafa;
|
|
}
|
|
tbody tr {
|
|
transition: all, 0.2s;
|
|
}
|
|
tbody tr:hover {
|
|
background: #f5f5f5;
|
|
}
|
|
</style>
|