- add displaying for values in recipe list, with some editable fields except topping, string params, feed pattern/level Signed-off-by: pakintada@gmail.com <Pakin>
196 lines
5.5 KiB
Svelte
196 lines
5.5 KiB
Svelte
<script module>
|
|
export { DragHandle };
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
import * as Card from '$lib/components/ui/card/index';
|
|
import Label from '$lib/components/ui/label/label.svelte';
|
|
import Input from '$lib/components/ui/input/input.svelte';
|
|
import RecipeDetail from './recipe-detail.svelte';
|
|
import {
|
|
createTable,
|
|
getCoreRowModel,
|
|
getFacetedRowModel,
|
|
getSortedRowModel,
|
|
type ColumnDef,
|
|
type Row,
|
|
type RowSelectionState,
|
|
type SortingState
|
|
} from '@tanstack/table-core';
|
|
import { createSvelteTable } from '../ui/data-table';
|
|
import * as Table from '$lib/components/ui/table/index';
|
|
import FlexRender from '../ui/data-table/flex-render.svelte';
|
|
import ScrollArea from '../ui/scroll-area/scroll-area.svelte';
|
|
import { type Attachment } from 'svelte/attachments';
|
|
import Button from '../ui/button/button.svelte';
|
|
import { GripVerticalIcon } from '@lucide/svelte/icons';
|
|
import { DragDropProvider } from '@dnd-kit-svelte/svelte';
|
|
import { move } from '@dnd-kit/helpers';
|
|
import { RestrictToVerticalAxis } from '@dnd-kit/abstract/modifiers';
|
|
import { type UniqueIdentifier } from '@dnd-kit/abstract';
|
|
import { type RecipelistMaterial } from './columns';
|
|
import { useSortable } from '@dnd-kit-svelte/svelte/sortable';
|
|
import { onMount } from 'svelte';
|
|
|
|
import { get, writable, type Writable } from 'svelte/store';
|
|
|
|
// type DataTableProps<TData, TValue> = {
|
|
// columns: ColumnDef<TData, TValue>[];
|
|
// data: TData[];
|
|
// };
|
|
|
|
let {
|
|
data,
|
|
columns,
|
|
onStateChange
|
|
}: {
|
|
data: RecipelistMaterial[];
|
|
columns: ColumnDef<any, any>[];
|
|
onStateChange: any;
|
|
} = $props();
|
|
|
|
let sorting = $state<SortingState>([]);
|
|
let rowSelection = $state<RowSelectionState>({});
|
|
|
|
// let recipeMatState = $state<RecipelistMaterial[]>(data);
|
|
|
|
const table = createSvelteTable({
|
|
get data() {
|
|
return data;
|
|
},
|
|
columns,
|
|
enableRowSelection: true,
|
|
enableMultiRowSelection: true,
|
|
getRowId: (row: any) => row.id.toString(),
|
|
state: {
|
|
get sorting() {
|
|
return sorting;
|
|
},
|
|
get rowSelection() {
|
|
return rowSelection;
|
|
}
|
|
},
|
|
getCoreRowModel: getCoreRowModel(),
|
|
getSortedRowModel: getSortedRowModel(),
|
|
getFacetedRowModel: getFacetedRowModel(),
|
|
onStateChange: async (updater) => {
|
|
console.log('table state change', data);
|
|
await onStateChange(table.getRowModel().rows.map((x) => x.original));
|
|
},
|
|
onSortingChange: async (updater) => {
|
|
console.log('triggering sorting');
|
|
if (typeof updater === 'function') {
|
|
sorting = updater(sorting);
|
|
} else {
|
|
sorting = updater;
|
|
}
|
|
await onStateChange(table.getRowModel().rows.map((x) => x.original));
|
|
},
|
|
onRowSelectionChange: async (updater) => {
|
|
// table.getRowModel().rows.find((x) => x.original.id == )
|
|
if (typeof updater === 'function') {
|
|
rowSelection = updater(rowSelection);
|
|
let rows = table.getRowModel().rows;
|
|
|
|
console.log('state size', data, rows);
|
|
} else {
|
|
rowSelection = updater;
|
|
}
|
|
await onStateChange(table.getRowModel().rows.map((x) => x.original));
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<!-- use card -->
|
|
<Card.Root>
|
|
<Card.Header>
|
|
<Card.Title>Recipe List</Card.Title>
|
|
<Card.Description>Material used in this menu's brewing process.</Card.Description>
|
|
|
|
<Card.Content>
|
|
<!-- table -->
|
|
|
|
<DragDropProvider
|
|
modifiers={[
|
|
// @ts-expect-error @dnd-kit/adbstract types are botched atm
|
|
RestrictToVerticalAxis
|
|
]}
|
|
onDragEnd={(e) => {
|
|
// snap
|
|
data = move(data as any, e as any);
|
|
//
|
|
}}
|
|
>
|
|
<ScrollArea class="h-[60vh] w-full rounded-md border" type="always">
|
|
<Table.Root class="relative w-full">
|
|
<Table.Header class="sticky top-0 z-10">
|
|
{#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 class="**:data-[slot=table-cell]:first:w-8">
|
|
{#if table.getRowModel().rows?.length}
|
|
{#each table.getRowModel().rows as row, index (row.id)}
|
|
{@render DraggableRow({ row, index })}
|
|
{/each}
|
|
{:else}
|
|
<Table.Row>
|
|
<Table.Cell colspan={columns.length} class="h-24 text-center"
|
|
>Empty recipe.</Table.Cell
|
|
>
|
|
</Table.Row>
|
|
{/if}
|
|
</Table.Body>
|
|
</Table.Root>
|
|
</ScrollArea>
|
|
</DragDropProvider>
|
|
</Card.Content>
|
|
</Card.Header>
|
|
</Card.Root>
|
|
|
|
{#snippet DraggableRow({ row, index }: { row: Row<any>; index: number })}
|
|
{@const { ref, isDragging, handleRef } = useSortable({
|
|
id: row.original.id,
|
|
index: () => index
|
|
})}
|
|
|
|
<Table.Row
|
|
data-state={row.original.is_use ? 'selected' : undefined}
|
|
data-dragging={isDragging.current}
|
|
class="relative z-0 data-[dragging=true]:z-10 data-[dragging=true]:opacity-80"
|
|
{@attach ref}
|
|
>
|
|
{#each row.getVisibleCells() as cell (cell.id)}
|
|
<Table.Cell>
|
|
<FlexRender
|
|
attach={handleRef}
|
|
content={cell.column.columnDef.cell}
|
|
context={cell.getContext()}
|
|
/>
|
|
</Table.Cell>
|
|
{/each}
|
|
</Table.Row>
|
|
{/snippet}
|
|
|
|
{#snippet DragHandle({ attach }: { attach: Attachment })}
|
|
<Button
|
|
{@attach attach}
|
|
variant="ghost"
|
|
size="icon"
|
|
class="size-7 text-muted-foreground hover:bg-transparent"
|
|
>
|
|
<GripVerticalIcon class="size-3 text-muted-foreground" />
|
|
<span class="sr-only">Drag to reorder</span>
|
|
</Button>
|
|
{/snippet}
|