This commit is contained in:
Matthieu
2026-03-31 17:53:30 +02:00
parent e0f761da2b
commit 958a00c8fc
21 changed files with 281 additions and 144 deletions

View File

@@ -35,6 +35,7 @@
class="text-xs text-base-content/50"
>
{{ constructeur.name }}
<span v-if="supplierReferenceMap.get(constructeur.id)" class="opacity-70">({{ supplierReferenceMap.get(constructeur.id) }})</span>
</span>
<span v-if="displayProductName" class="badge badge-info badge-xs">
{{ displayProductName }}
@@ -102,6 +103,9 @@
class="text-base-content"
>
{{ constructeur.name }}
<span v-if="supplierReferenceMap.get(constructeur.id)" class="text-sm text-base-content/60">
Réf. {{ supplierReferenceMap.get(constructeur.id) }}
</span>
<span v-if="formatConstructeurContact(constructeur)" class="text-xs text-base-content/50 block">
{{ formatConstructeurContact(constructeur) }}
</span>
@@ -292,6 +296,7 @@ import {
formatConstructeurContact as formatConstructeurContactSummary,
resolveConstructeurs,
uniqueConstructeurIds,
parseConstructeurLinksFromApi,
} from '~/shared/constructeurUtils'
import {
formatSize,
@@ -391,23 +396,36 @@ const structurePieces = computed(() => allPieces.value.filter((p) => p._structur
// --- Constructeurs ---
const { constructeurs } = useConstructeurs()
const componentConstructeurIds = computed(() =>
uniqueConstructeurIds(
props.component,
const componentConstructeurLinks = computed(() =>
parseConstructeurLinksFromApi(
Array.isArray(props.component.constructeurs) ? props.component.constructeurs : [],
props.component.constructeur ? [props.component.constructeur] : [],
),
)
const componentConstructeursDisplay = computed(() =>
resolveConstructeurs(
componentConstructeurIds.value,
Array.isArray(props.component.constructeurs) ? props.component.constructeurs : [],
props.component.constructeur ? [props.component.constructeur] : [],
constructeurs.value,
),
const supplierReferenceMap = computed(() => {
const map = new Map()
componentConstructeurLinks.value.forEach(l => {
if (l.supplierReference) map.set(l.constructeurId, l.supplierReference)
})
return map
})
const componentConstructeurIds = computed(() =>
componentConstructeurLinks.value.map(l => l.constructeurId).filter(Boolean),
)
const componentConstructeursDisplay = computed(() => {
// Extract nested constructeur objects from link entries
const linkConstructeurs = componentConstructeurLinks.value
.filter(l => l.constructeur && l.constructeur.id)
.map(l => l.constructeur)
return resolveConstructeurs(
componentConstructeurIds.value,
linkConstructeurs,
constructeurs.value,
)
})
const formatConstructeurContact = (constructeur) =>
formatConstructeurContactSummary(constructeur)

View File

@@ -78,7 +78,9 @@ const getConstructeurContact = (link: ConstructeurLinkEntry): string => {
const updateReference = (index: number, value: string) => {
const updated = [...props.modelValue]
updated[index] = { ...updated[index], supplierReference: value || null }
const entry = updated[index]
if (!entry) return
updated[index] = { ...entry, supplierReference: value || null }
emit('update:modelValue', updated)
}
@@ -86,6 +88,6 @@ const removeLink = (index: number) => {
const removed = props.modelValue[index]
const updated = props.modelValue.filter((_, i) => i !== index)
emit('update:modelValue', updated)
emit('remove', removed.constructeurId)
if (removed) emit('remove', removed.constructeurId)
}
</script>

View File

@@ -15,9 +15,9 @@
<IconLucideEye v-else class="w-5 h-5 mr-2" aria-hidden="true" />
{{ isEditMode ? 'Voir détails' : 'Modifier' }}
</button>
<NuxtLink :to="backLink" class="btn btn-ghost btn-sm md:btn-md">
<button type="button" class="btn btn-ghost btn-sm md:btn-md" @click="goBack">
Retour au catalogue
</NuxtLink>
</button>
</div>
</div>
</template>
@@ -26,7 +26,9 @@
import IconLucideSquarePen from '~icons/lucide/square-pen'
import IconLucideEye from '~icons/lucide/eye'
defineProps<{
const router = useRouter()
const props = defineProps<{
title: string
subtitle?: string
isEditMode: boolean
@@ -37,4 +39,13 @@ defineProps<{
defineEmits<{
'toggle-edit': []
}>()
function goBack() {
if (window.history.length > 1) {
router.back()
}
else {
navigateTo(props.backLink)
}
}
</script>

View File

@@ -50,6 +50,9 @@
class="badge badge-outline badge-sm"
>
{{ constructeur.name }}
<span v-if="supplierReferenceMap.get(constructeur.id)" class="text-xs opacity-60 ml-0.5">
({{ supplierReferenceMap.get(constructeur.id) }})
</span>
</span>
</template>
<span v-if="pieceData.prix" class="badge badge-primary badge-sm">{{ pieceData.prix }}</span>
@@ -122,6 +125,9 @@
>
<span class="font-medium">
{{ constructeur.name }}
<span v-if="supplierReferenceMap.get(constructeur.id)" class="text-sm font-normal text-base-content/60">
Réf. {{ supplierReferenceMap.get(constructeur.id) }}
</span>
</span>
<span
v-if="formatConstructeurContact(constructeur)"
@@ -283,6 +289,7 @@ import {
formatConstructeurContact as formatConstructeurContactSummary,
resolveConstructeurs,
uniqueConstructeurIds,
parseConstructeurLinksFromApi,
} from '~/shared/constructeurUtils'
import {
resolveFieldId,
@@ -393,23 +400,36 @@ const toggleCollapse = () => {
// --- Constructeurs ---
const { constructeurs } = useConstructeurs()
const pieceConstructeurIds = computed(() =>
uniqueConstructeurIds(
props.piece,
const pieceConstructeurLinks = computed(() =>
parseConstructeurLinksFromApi(
Array.isArray(props.piece.constructeurs) ? props.piece.constructeurs : [],
props.piece.constructeur ? [props.piece.constructeur] : [],
),
)
const pieceConstructeursDisplay = computed(() =>
resolveConstructeurs(
pieceConstructeurIds.value,
Array.isArray(props.piece.constructeurs) ? props.piece.constructeurs : [],
props.piece.constructeur ? [props.piece.constructeur] : [],
constructeurs.value,
),
const supplierReferenceMap = computed(() => {
const map = new Map()
pieceConstructeurLinks.value.forEach(l => {
if (l.supplierReference) map.set(l.constructeurId, l.supplierReference)
})
return map
})
const pieceConstructeurIds = computed(() =>
pieceConstructeurLinks.value.map(l => l.constructeurId).filter(Boolean),
)
const pieceConstructeursDisplay = computed(() => {
// Extract nested constructeur objects from link entries
const linkConstructeurs = pieceConstructeurLinks.value
.filter(l => l.constructeur && l.constructeur.id)
.map(l => l.constructeur)
return resolveConstructeurs(
pieceConstructeurIds.value,
linkConstructeurs,
constructeurs.value,
)
})
const formatConstructeurContact = (constructeur) =>
formatConstructeurContactSummary(constructeur)

View File

@@ -32,6 +32,9 @@
<IconLucidePrinter class="w-5 h-5 mr-2" aria-hidden="true" />
Imprimer
</button>
<button type="button" class="btn btn-ghost btn-sm md:btn-md" @click="goBack">
Retour aux machines
</button>
</div>
</div>
</template>
@@ -41,6 +44,8 @@ import IconLucideSquarePen from '~icons/lucide/square-pen'
import IconLucideEye from '~icons/lucide/eye'
import IconLucidePrinter from '~icons/lucide/printer'
const router = useRouter()
defineProps<{
title: string
isEditMode: boolean
@@ -50,4 +55,13 @@ defineEmits<{
'toggle-edit': []
'open-print': []
}>()
function goBack() {
if (window.history.length > 1) {
router.back()
}
else {
navigateTo('/machines')
}
}
</script>

View File

@@ -58,7 +58,7 @@
{{ machineReference }}
</div>
</div>
<div v-if="isEditMode || hasMachineConstructeur" class="form-control">
<div v-if="isEditMode || hasMachineConstructeur" class="form-control md:col-span-2">
<label class="label">
<span class="label-text">Fournisseur</span>
</label>
@@ -70,23 +70,15 @@
placeholder="Rechercher un ou plusieurs fournisseurs..."
@update:modelValue="$emit('update:constructeur-ids', $event)"
/>
<div v-else class="border border-base-300 rounded-btn bg-base-200 px-4 py-2 min-h-12 flex items-center">
<div v-if="machineConstructeursDisplay.length" class="flex flex-wrap gap-2">
<span
v-for="constructeur in machineConstructeursDisplay"
:key="constructeur.id"
class="badge badge-ghost gap-1"
>
{{ constructeur.name }}
<span
v-if="formatConstructeurContactSummary(constructeur)"
class="text-xs opacity-60"
>
· {{ formatConstructeurContactSummary(constructeur) }}
</span>
</span>
</div>
<span v-else class="text-base-content/50">Non défini</span>
<ConstructeurLinksTable
v-if="constructeurLinks.length"
:model-value="constructeurLinks"
:readonly="!isEditMode"
@update:model-value="$emit('update:constructeur-links', $event)"
@remove="$emit('remove-constructeur-link', $event)"
/>
<div v-else-if="!isEditMode" class="border border-base-300 rounded-btn bg-base-200 px-4 py-2 min-h-12 flex items-center">
<span class="text-base-content/50">Non défini</span>
</div>
</div>
</div>
@@ -188,12 +180,11 @@
<script setup lang="ts">
import { watch } from 'vue'
import ConstructeurSelect from '~/components/ConstructeurSelect.vue'
import ConstructeurLinksTable from '~/components/ConstructeurLinksTable.vue'
import MachineCustomFieldDefEditor from '~/components/machine/MachineCustomFieldDefEditor.vue'
import {
formatConstructeurContact as formatConstructeurContactSummary,
} from '~/shared/constructeurUtils'
import { formatCustomFieldValue } from '~/shared/utils/customFieldUtils'
import { useMachineCustomFieldDefs } from '~/composables/useMachineCustomFieldDefs'
import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils'
const props = defineProps<{
isEditMode: boolean
@@ -205,6 +196,7 @@ const props = defineProps<{
machineConstructeurIds: string[]
machineConstructeursDisplay: any[]
hasMachineConstructeur: boolean
constructeurLinks: ConstructeurLinkEntry[]
visibleCustomFields: any[]
getMachineFieldId: (fieldName: string) => string
machineId: string
@@ -216,6 +208,8 @@ const emit = defineEmits<{
'update:machine-reference': [value: string]
'update:machine-site-id': [value: string]
'update:constructeur-ids': [ids: unknown]
'update:constructeur-links': [links: ConstructeurLinkEntry[]]
'remove-constructeur-link': [constructeurId: string]
'set-custom-field-value': [field: any, value: unknown]
'custom-fields-saved': []
}>()