Files
website/src/components/admin/table/DataTable.svelte
bytedream 55c0852b7e
All checks were successful
deploy / build-and-deploy (push) Successful in 16s
rewrite website
2025-10-13 18:09:48 +02:00

82 lines
2.3 KiB
Svelte

<script lang="ts">
import type { Writable } from 'svelte/store';
import SortableTr from '@components/admin/table/SortableTr.svelte';
import SortableTh from '@components/admin/table/SortableTh.svelte';
import Icon from '@iconify/svelte';
import type { Snippet } from 'svelte';
import { getObjectEntryByKey } from '@util/objects.ts';
// types
interface Props<T> {
data: Writable<T[]>;
count?: boolean;
keys: {
key: string;
label: string;
width?: number;
sortable?: boolean;
transform?: Snippet<[T]>;
}[];
onClick?: (t: T) => void;
onEdit?: (t: T) => void;
onDelete?: (t: T) => void;
}
// input
let { data, count, keys, onClick, onEdit, onDelete }: Props<any> = $props();
</script>
<div class="h-screen overflow-x-auto">
<table class="table table-pin-rows">
<thead>
<SortableTr {data}>
{#if count}
<SortableTh style="width: 5%">#</SortableTh>
{/if}
{#each keys as key (key.key)}
<SortableTh style={key.width ? `width: ${key.width}%` : undefined} key={key.sortable ? key.key : undefined}
>{key.label}</SortableTh
>
{/each}
{#if onEdit || onDelete}
<SortableTh style="width: 5%"></SortableTh>
{/if}
</SortableTr>
</thead>
<tbody>
{#each $data as d, i (d)}
<tr class="hover:bg-base-200" onclick={() => onClick?.(d)}>
{#if count}
<td>{i + 1}</td>
{/if}
{#each keys as key (key.key)}
<td>
{#if key.transform}
{@render key.transform(getObjectEntryByKey(key.key, d))}
{:else}
{getObjectEntryByKey(key.key, d)}
{/if}
</td>
{/each}
{#if onEdit || onDelete}
<td>
{#if onEdit}
<button class="cursor-pointer" onclick={() => onEdit(d)}>
<Icon icon="heroicons:pencil-square" />
</button>
{/if}
{#if onDelete}
<button class="cursor-pointer" onclick={() => onDelete(d)}>
<Icon icon="heroicons:trash" />
</button>
{/if}
</td>
{/if}
</tr>
{/each}
</tbody>
</table>
</div>