Use Tanstack table for Selectable Table, quick actions (#998)

* feat: implement example of data table

* feat: load item data into table

* chore: begin switching dialogs

* feat: implement old dialog for controlling headers and page size

* feat: get table into relatively usable state

* feat: enhance dropdown actions for multi-selection and CSV download

* feat: enhance table cell and dropdown button styles for better usability

* feat: json download for table

* feat: add expanded row component for item details in data table

* chore: add translation support

* feat: restore table on home page

* fix: oops need ids

* feat: move card view to use tanstack to allow for pagination

* feat: switch the items search to use ItemViewSelectable

* fix: update pagination handling and improve button click logic

* feat: improve selectable table

* feat: add indeterminate to checkbox

* feat: overhaul maintenance dialog to use new system and add maintenance options to table

* feat: add label ids and location id to item patch api

* feat: change location and labels in table view

* feat: add quick actions preference and enable toggle in table settings

* fix: lint

* fix: remove sized 1 pages

* fix: attempt to fix type error

* fix: various issues

* fix: remove

* fix: refactor item fetching logic to use useAsyncData for improved reactivity and improve use confirm

* fix: sort backend issues

* fix: enhance CSV export functionality by escaping fields to prevent formula injection

* fix: put aria sort on th not button

* chore: update api types
This commit is contained in:
Tonya
2025-09-24 02:37:38 +01:00
committed by GitHub
parent a5d63ac4e1
commit 6cd9e2779f
48 changed files with 1959 additions and 617 deletions

View File

@@ -0,0 +1,73 @@
<script setup lang="ts" generic="TValue">
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import DataTableExpandedRow from "./data-table-expanded-row.vue";
import { FlexRender, type Column, type ColumnDef, type Table as TableType } from "@tanstack/vue-table";
import type { ItemSummary } from "~/lib/api/types/data-contracts";
defineProps<{
table: TableType<ItemSummary>;
columns: ColumnDef<ItemSummary, TValue>[];
}>();
const ariaSort = (column: Column<ItemSummary, unknown>) => {
const s = column.getIsSorted();
if (s === "asc") return "ascending";
if (s === "desc") return "descending";
return "none";
};
</script>
<template>
<Table class="w-full">
<TableHeader>
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
<TableHead
v-for="header in headerGroup.headers"
:key="header.id"
:class="[
'text-no-transform cursor-pointer bg-secondary text-sm text-secondary-foreground hover:bg-secondary/90',
header.column.id === 'select' || header.column.id === 'actions' ? 'w-10 px-3 text-center' : '',
]"
:aria-sort="ariaSort(header.column)"
>
<FlexRender
v-if="!header.isPlaceholder"
:render="header.column.columnDef.header"
:props="header.getContext()"
/>
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<template v-if="table.getRowModel().rows?.length">
<template v-for="row in table.getRowModel().rows" :key="row.id">
<TableRow :data-state="row.getIsSelected() ? 'selected' : undefined">
<TableCell
v-for="cell in row.getVisibleCells()"
:key="cell.id"
:href="
cell.column.id !== 'select' && cell.column.id !== 'actions' ? `/item/${row.original.id}` : undefined
"
:class="cell.column.id === 'select' || cell.column.id === 'actions' ? 'w-10 px-3' : ''"
:compact="cell.column.id === 'select' || cell.column.id === 'actions'"
>
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
</TableCell>
</TableRow>
<TableRow v-if="row.getIsExpanded()">
<TableCell :colspan="row.getAllCells().length">
<DataTableExpandedRow :item="row.original" />
</TableCell>
</TableRow>
</template>
</template>
<template v-else>
<TableRow>
<TableCell :colspan="columns.length" class="h-24 text-center">
<p>{{ $t("items.no_results") }}</p>
</TableCell>
</TableRow>
</template>
</TableBody>
</Table>
</template>