feat: show product thumbnails in catalogue list

Display the primary product document (image/pdf) as the leading column in the catalogue table for quicker visual identification.
This commit is contained in:
Matthieu
2025-11-05 15:38:44 +01:00
parent d860f24e69
commit 34af59d054

View File

@@ -91,6 +91,7 @@
<table class="table table-sm md:table-md">
<thead>
<tr>
<th class="w-16">Aperçu</th>
<th>Nom</th>
<th>Référence</th>
<th>Type de produit</th>
@@ -101,6 +102,12 @@
</thead>
<tbody>
<tr v-for="product in filteredProducts" :key="product.id">
<td class="align-middle">
<DocumentThumbnail
:document="resolvePrimaryDocument(product)"
:alt="resolvePreviewAlt(product)"
/>
</td>
<td class="font-medium">{{ product.name }}</td>
<td>{{ product.reference || '—' }}</td>
<td>{{ product.typeProduct?.name || '—' }}</td>
@@ -142,6 +149,8 @@ import { computed, onMounted, ref } from 'vue'
import { useHead } from '#imports'
import { useProducts } from '~/composables/useProducts'
import { useToast } from '~/composables/useToast'
import DocumentThumbnail from '~/components/DocumentThumbnail.vue'
import { isImageDocument, isPdfDocument } from '~/utils/documentPreview'
useHead(() => ({
title: 'Catalogue des produits',
@@ -230,6 +239,35 @@ const formatConstructeurs = (constructeurs: Array<Record<string, any>>) =>
.filter((name): name is string => Boolean(name))
.join(', ')
const resolvePrimaryDocument = (product: Record<string, any>) => {
const documents = Array.isArray(product?.documents) ? product.documents : []
if (!documents.length) {
return null
}
const normalized = documents.filter((doc) => doc && typeof doc === 'object')
const withPath = normalized.filter((doc) => doc?.path)
if (!withPath.length) {
return normalized[0] ?? null
}
const images = withPath.filter((doc) => isImageDocument(doc))
if (images.length) {
return images[0]
}
const pdf = withPath.find((doc) => isPdfDocument(doc))
if (pdf) {
return pdf
}
return withPath[0]
}
const resolvePreviewAlt = (product: Record<string, any>) => {
const parts = [product?.name, product?.reference].filter(Boolean)
if (parts.length) {
return `Aperçu du document de ${parts.join(' ')}`
}
return 'Aperçu du document'
}
const reload = async () => {
await loadProducts({ force: true })
}