mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-28 16:06:37 +01:00
* 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
46 lines
1.5 KiB
Vue
46 lines
1.5 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
import type { ItemSummary } from "~/lib/api/types/data-contracts";
|
|
import LabelChip from "@/components/Label/Chip.vue";
|
|
import Badge from "~/components/ui/badge/Badge.vue";
|
|
|
|
const props = defineProps<{
|
|
item: ItemSummary;
|
|
}>();
|
|
|
|
const api = useUserApi();
|
|
|
|
const imageUrl = computed(() => {
|
|
if (!props.item.imageId) {
|
|
return "/no-image.jpg";
|
|
}
|
|
if (props.item.thumbnailId) {
|
|
return api.authURL(`/items/${props.item.id}/attachments/${props.item.thumbnailId}`);
|
|
} else {
|
|
return api.authURL(`/items/${props.item.id}/attachments/${props.item.imageId}`);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex items-start gap-3">
|
|
<div class="shrink-0">
|
|
<img :src="imageUrl" class="size-32 rounded-lg bg-muted object-cover" />
|
|
</div>
|
|
<div class="flex min-w-0 flex-1 flex-col gap-2">
|
|
<h2 class="truncate text-xl font-bold">{{ item.name }}</h2>
|
|
<Badge class="w-min text-nowrap bg-secondary text-secondary-foreground hover:bg-secondary/70 hover:underline">
|
|
<NuxtLink v-if="item.location" :to="`/location/${item.location.id}`">
|
|
{{ item.location.name }}
|
|
</NuxtLink>
|
|
</Badge>
|
|
<div class="flex flex-wrap gap-2">
|
|
<LabelChip v-for="label in item.labels" :key="label.id" :label="label" size="sm" />
|
|
</div>
|
|
<p class="whitespace-pre-line break-words text-sm text-muted-foreground">
|
|
{{ item.description || $t("components.item.no_description") }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|