Files
homebox/frontend/components/Item/View/table/card-view.vue
Tonya 6cd9e2779f 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
2025-09-24 02:37:38 +01:00

67 lines
2.3 KiB
Vue

<script setup lang="ts">
import ItemCard from "@/components/Item/Card.vue";
import type { ItemSummary } from "~/lib/api/types/data-contracts";
import type { Table as TableType } from "@tanstack/vue-table";
import MdiSelectSearch from "~icons/mdi/select-search";
import { Checkbox } from "@/components/ui/checkbox";
import DropdownAction from "./data-table-dropdown.vue";
const preferences = useViewPreferences();
const props = defineProps<{
table: TableType<ItemSummary>;
locationFlatTree?: FlatTreeItem[];
}>();
defineEmits<{
(e: "refresh"): void;
}>();
const selectedCount = computed(() => props.table.getSelectedRowModel().rows.length);
</script>
<template>
<Teleport to="#selectable-subtitle" defer>
<Checkbox
class="size-6 p-0"
:model-value="
table.getIsAllPageRowsSelected() ? true : table.getSelectedRowModel().rows.length > 0 ? 'indeterminate' : false
"
:aria-label="$t('components.item.view.selectable.select_all')"
@update:model-value="table.toggleAllPageRowsSelected(!!$event)"
/>
<div class="grow" />
<div :class="['relative inline-flex items-center', selectedCount === 0 ? 'pointer-events-none opacity-50' : '']">
<DropdownAction
:multi="{ items: table.getSelectedRowModel().rows, columns: table.getAllColumns() }"
view="card"
:table="table"
@refresh="$emit('refresh')"
/>
<span v-if="selectedCount > 0" class="absolute -right-1 -top-1 flex size-4">
<span
class="pointer-events-none relative flex size-4 items-center justify-center whitespace-nowrap rounded-full bg-primary p-1 text-xs text-primary-foreground"
>
{{ String(selectedCount) }}
</span>
</span>
</div>
</Teleport>
<div v-if="table.getRowModel().rows?.length === 0" class="flex flex-col items-center gap-2">
<MdiSelectSearch class="size-10" />
<p>{{ $t("items.no_results") }}</p>
</div>
<div v-else class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<ItemCard
v-for="item in table.getRowModel().rows"
:key="item.original.id"
:item="item.original"
:table-row="preferences.quickActions.enabled ? item : undefined"
:location-flat-tree="locationFlatTree"
/>
</div>
</template>