clqms-shadcn-v1/src/lib/components/reusable/reusable-data-table.svelte

187 lines
6.4 KiB
Svelte

<script>
import { getCoreRowModel, getPaginationRowModel, getFilteredRowModel } from "@tanstack/table-core";
import {
createSvelteTable,
FlexRender,
} from "$lib/components/ui/data-table/index.js";
import * as Table from "$lib/components/ui/table/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import * as Select from "$lib/components/ui/select/index.js";
import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
import ChevronLeftIcon from "@lucide/svelte/icons/chevron-left";
import ChevronsRightIcon from "@lucide/svelte/icons/chevrons-right";
import ChevronsLeftIcon from "@lucide/svelte/icons/chevrons-left";
import { Input } from "$lib/components/ui/input/index.js";
let props = $props();
let pagination = $state({ pageIndex: 0, pageSize: 10 });
let columnFilters = $state([]);
let globalFilter = $state("");
let activeRowId = $state(null);
let table = createSvelteTable({
get data() {
return props.data;
},
get columns() {
return props.columns;
},
state: {
get pagination() {
return pagination;
},
get columnFilters() {
return columnFilters;
},
get globalFilter() {
return globalFilter;
},
},
onPaginationChange: (updater) => {
if (typeof updater === "function") {
pagination = updater(pagination);
} else {
pagination = updater;
}
},
onColumnFiltersChange: (updater) => {
if (typeof updater === "function") {
columnFilters = updater(columnFilters);
} else {
columnFilters = updater;
}
},
onGlobalFilterChange: (value) => {
globalFilter = value;
},
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFilteredRowModel: getFilteredRowModel(),
});
</script>
<div class="h-full flex flex-col relative">
<div class="flex items-center absolute top-[-2rem]">
<Input
placeholder="Filter all columns..."
value={globalFilter}
oninput={(e) => {
globalFilter = e.currentTarget.value;
}}
class="h-7 w-64 text-xs px-2"
/>
</div>
<div class="rounded-md border h-full flex flex-col">
<Table.Root>
<Table.Header>
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
<Table.Row>
{#each headerGroup.headers as header (header.id)}
<Table.Head colspan={header.colSpan}>
{#if !header.isPlaceholder}
<FlexRender
content={header.column.columnDef.header}
context={header.getContext()}
/>
{/if}
</Table.Head>
{/each}
</Table.Row>
{/each}
</Table.Header>
<Table.Body>
{#each table.getRowModel().rows as row (row.id)}
<Table.Row
data-state={row.getIsSelected() && "selected"}
onclick={() => props.handleRowClick(row.original)}
class="cursor-pointer"
>
{#each row.getVisibleCells() as cell, i (cell.id)}
<Table.Cell class={`${i === 0 ? "border-l-4" : ""} ${i === 0 && activeRowId == row.original[props.rowIdKey] ? "border-primary" : "border-transparent"}`}>
<FlexRender
content={cell.column.columnDef.cell}
context={cell.getContext()}
/>
</Table.Cell>
{/each}
</Table.Row>
{:else}
<Table.Row>
<Table.Cell colspan={props.columns.length} class="h-24 text-center">
No results.
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
<div class="flex items-center justify-between p-2 mt-auto">
<div class="flex items-center space-x-2">
<p class="text-sm font-medium">Rows per page</p>
<Select.Root
allowDeselect={false}
type="single"
value={`${table.getState().pagination.pageSize}`}
onValueChange={(value) => {
table.setPageSize(Number(value));
}}
>
<Select.Trigger class="h-8 w-[70px]">
{String(table.getState().pagination.pageSize)}
</Select.Trigger>
<Select.Content side="top">
{#each [1, 2, 3, 4, 5] as pageSize (pageSize)}
<Select.Item value={`${pageSize}`}>
{pageSize}
</Select.Item>
{/each}
</Select.Content>
</Select.Root>
</div>
<div class="flex items-center gap-2">
<div class="flex w-[100px] items-center justify-center text-sm font-medium">
Page {table.getState().pagination.pageIndex + 1} of
{table.getPageCount()}
</div>
<div class="flex items-center space-x-2">
<Button
variant="outline"
class="hidden size-8 p-0 lg:flex"
onclick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
>
<span class="sr-only">Go to first page</span>
<ChevronsLeftIcon />
</Button>
<Button
variant="outline"
class="size-8 p-0"
onclick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
<span class="sr-only">Go to previous page</span>
<ChevronLeftIcon />
</Button>
<Button
variant="outline"
class="size-8 p-0"
onclick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
<span class="sr-only">Go to next page</span>
<ChevronRightIcon />
</Button>
<Button
variant="outline"
class="hidden size-8 p-0 lg:flex"
onclick={() => table.setPageIndex(table.getPageCount() - 1)}
disabled={!table.getCanNextPage()}
>
<span class="sr-only">Go to last page</span>
<ChevronsRightIcon />
</Button>
</div>
</div>
</div>
</div>
</div>