mirror of
https://github.com/faiztyanirh/clqms-shadcn-v1.git
synced 2026-04-22 17:19:52 +07:00
187 lines
6.4 KiB
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> |