- Site color field with color picker in create/edit modals - Dark mode theme (mytheme-dark) with toggle in navbar - Stronger site color visibility on cards (gradient, top border, badges) - Bigger action buttons (btn-sm) on machine cards - White card backgrounds with proper dark mode support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
176 lines
5.8 KiB
Vue
176 lines
5.8 KiB
Vue
<template>
|
|
<div class="card bg-base-100 shadow-sm">
|
|
<div class="card-body space-y-4">
|
|
<DocumentPreviewModal
|
|
:document="previewDocument"
|
|
:visible="previewVisible"
|
|
:documents="previewDocumentList"
|
|
@close="closePreview"
|
|
/>
|
|
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h2 class="card-title">Produits associés</h2>
|
|
<p class="text-xs text-gray-500">
|
|
Produits sélectionnés directement pour cette machine.
|
|
</p>
|
|
</div>
|
|
<span class="badge badge-outline" v-if="products.length">
|
|
{{ products.length }} produit{{ products.length > 1 ? 's' : '' }}
|
|
</span>
|
|
</div>
|
|
|
|
<div v-if="products.length" class="space-y-3">
|
|
<div
|
|
v-for="product in products"
|
|
:key="product.id || product.name"
|
|
class="rounded border border-base-200 bg-base-200/60 p-3 text-sm space-y-2"
|
|
>
|
|
<div class="flex items-center justify-between flex-wrap gap-2">
|
|
<p class="font-semibold text-base-content">
|
|
{{ product.name }}
|
|
</p>
|
|
<div class="flex items-center gap-2">
|
|
<span v-if="product.groupLabel" class="badge badge-ghost badge-sm">
|
|
{{ product.groupLabel }}
|
|
</span>
|
|
<button
|
|
v-if="isEditMode"
|
|
type="button"
|
|
class="btn btn-ghost btn-xs text-error"
|
|
title="Supprimer ce produit"
|
|
@click="$emit('remove-product', (product.linkId || product.id) as string)"
|
|
>
|
|
Supprimer
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<p v-if="product.reference" class="text-xs text-base-content/70">
|
|
<span class="font-medium">Référence :</span>
|
|
<span class="ml-1">{{ product.reference }}</span>
|
|
</p>
|
|
<p v-if="product.supplierLabel" class="text-xs text-base-content/70">
|
|
<span class="font-medium">Fournisseurs :</span>
|
|
<span class="ml-1">{{ product.supplierLabel }}</span>
|
|
</p>
|
|
<p v-if="product.priceLabel" class="text-xs text-base-content/70">
|
|
<span class="font-medium">Prix indicatif :</span>
|
|
<span class="ml-1">{{ product.priceLabel }}</span>
|
|
</p>
|
|
|
|
<!-- Documents liés au produit -->
|
|
<div v-if="product.documents?.length" class="mt-2 space-y-1">
|
|
<p class="text-xs font-medium text-base-content/70">Documents :</p>
|
|
<div
|
|
v-for="doc in product.documents"
|
|
:key="doc.id || doc.name"
|
|
class="flex items-center justify-between gap-3 rounded border border-base-200 bg-base-100 px-3 py-2"
|
|
>
|
|
<div class="flex items-center gap-3 text-xs">
|
|
<div
|
|
class="flex-shrink-0 overflow-hidden rounded-md border border-base-200 bg-base-200/70 flex items-center justify-center h-8 w-6"
|
|
>
|
|
<component
|
|
:is="documentIcon(doc).component"
|
|
class="h-4 w-4"
|
|
:class="documentIcon(doc).colorClass"
|
|
aria-hidden="true"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<div class="font-medium text-base-content">{{ doc.name }}</div>
|
|
<div class="text-xs text-base-content/60">
|
|
{{ doc.mimeType || 'Inconnu' }} • {{ formatSize(doc.size) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-2 text-xs">
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-xs"
|
|
:disabled="!canPreviewDocument(doc)"
|
|
:title="canPreviewDocument(doc) ? 'Consulter le document' : 'Aucun aperçu disponible pour ce type'"
|
|
@click="openPreview(doc, product.documents || [])"
|
|
>
|
|
Consulter
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-xs"
|
|
@click="downloadDocument(doc)"
|
|
>
|
|
Télécharger
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p v-else class="text-xs text-gray-500">
|
|
Aucun produit n'a été associé directement à cette machine.
|
|
</p>
|
|
|
|
<button
|
|
v-if="isEditMode"
|
|
type="button"
|
|
class="btn btn-sm md:btn-md btn-primary"
|
|
@click="$emit('add-product')"
|
|
>
|
|
Ajouter un produit
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
import DocumentPreviewModal from '~/components/DocumentPreviewModal.vue'
|
|
import { canPreviewDocument } from '~/utils/documentPreview'
|
|
import {
|
|
formatSize,
|
|
documentIcon,
|
|
downloadDocument,
|
|
} from '~/shared/utils/documentDisplayUtils'
|
|
|
|
defineProps<{
|
|
products: Array<{
|
|
id?: string | null
|
|
linkId?: string | null
|
|
name?: string
|
|
reference?: string | null
|
|
supplierLabel?: string | null
|
|
priceLabel?: string | null
|
|
groupLabel?: string
|
|
documents?: Array<{
|
|
id?: string
|
|
name?: string
|
|
mimeType?: string
|
|
size?: number
|
|
fileUrl?: string
|
|
downloadUrl?: string
|
|
}>
|
|
}>
|
|
isEditMode: boolean
|
|
}>()
|
|
|
|
defineEmits<{
|
|
'add-product': []
|
|
'remove-product': [linkId: string]
|
|
}>()
|
|
|
|
const previewDocument = ref<any>(null)
|
|
const previewVisible = ref(false)
|
|
const previewDocumentList = ref<any[]>([])
|
|
|
|
const openPreview = (doc: any, docs: any[]) => {
|
|
previewDocument.value = doc
|
|
previewDocumentList.value = docs
|
|
previewVisible.value = true
|
|
}
|
|
|
|
const closePreview = () => {
|
|
previewVisible.value = false
|
|
previewDocument.value = null
|
|
}
|
|
</script>
|