From d0dc01deb1a7df4a370f2afff68d3332aad323a9 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 24 Mar 2026 16:57:23 +0100 Subject: [PATCH] feat(search) : add server-side multi-field search (name + reference) for pieces, components and products Co-Authored-By: Claude Opus 4.6 (1M context) --- .../machine/AddEntityToMachineModal.vue | 25 +++++++++++++++++++ app/composables/useComposants.ts | 2 +- app/composables/usePieces.ts | 2 +- app/composables/useProducts.ts | 2 +- .../useStructureAssignmentFetch.ts | 12 ++++----- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/app/components/machine/AddEntityToMachineModal.vue b/app/components/machine/AddEntityToMachineModal.vue index 5359d7b..f39fc98 100644 --- a/app/components/machine/AddEntityToMachineModal.vue +++ b/app/components/machine/AddEntityToMachineModal.vue @@ -44,6 +44,7 @@ :empty-text="`Aucun ${entityLabelLower} disponible dans cette catégorie`" :option-label="entityOptionLabel" :option-description="entityOptionDescription" + @search="handleEntitySearch" /> @@ -187,6 +188,30 @@ watch(selectedTypeId, async () => { } }) +let searchDebounce: ReturnType | null = null + +const handleEntitySearch = (term: string) => { + if (searchDebounce) clearTimeout(searchDebounce) + searchDebounce = setTimeout(async () => { + if (!selectedTypeName.value) return + loadingEntities.value = true + try { + if (props.entityKind === 'component') { + const result = await loadComposants({ typeName: selectedTypeName.value, search: term.trim(), itemsPerPage: 200 }) + entities.value = result?.data?.items || [] + } else if (props.entityKind === 'piece') { + const result = await loadPieces({ typeName: selectedTypeName.value, search: term.trim(), itemsPerPage: 200 }) + entities.value = result?.data?.items || [] + } else { + const result = await loadProducts({ typeName: selectedTypeName.value, search: term.trim(), itemsPerPage: 200 }) + entities.value = result?.data?.items || [] + } + } finally { + loadingEntities.value = false + } + }, 300) +} + const handleClose = () => { resetState() emit('close') diff --git a/app/composables/useComposants.ts b/app/composables/useComposants.ts index 5e3a519..7423d3a 100644 --- a/app/composables/useComposants.ts +++ b/app/composables/useComposants.ts @@ -135,7 +135,7 @@ export function useComposants() { params.set('page', String(page)) if (search && search.trim()) { - params.set('q', search.trim()) + params.set('search', search.trim()) } if (typeName && typeName.trim()) { diff --git a/app/composables/usePieces.ts b/app/composables/usePieces.ts index 16bcf9c..97b7fe7 100644 --- a/app/composables/usePieces.ts +++ b/app/composables/usePieces.ts @@ -147,7 +147,7 @@ export function usePieces() { params.set('page', String(page)) if (search && search.trim()) { - params.set('q', search.trim()) + params.set('search', search.trim()) } if (typeName && typeName.trim()) { diff --git a/app/composables/useProducts.ts b/app/composables/useProducts.ts index 99f35a8..98364ce 100644 --- a/app/composables/useProducts.ts +++ b/app/composables/useProducts.ts @@ -145,7 +145,7 @@ export function useProducts() { params.set('page', String(page)) if (search && search.trim()) { - params.set('q', search.trim()) + params.set('search', search.trim()) } if (typeName && typeName.trim()) { diff --git a/app/composables/useStructureAssignmentFetch.ts b/app/composables/useStructureAssignmentFetch.ts index 996ef1c..26e442d 100644 --- a/app/composables/useStructureAssignmentFetch.ts +++ b/app/composables/useStructureAssignmentFetch.ts @@ -105,9 +105,9 @@ export function useStructureAssignmentFetch(deps: StructureAssignmentFetchDeps) definition.typeComposantId || definition.modelId || definition.typeComposant?.id || null const params = new URLSearchParams() - params.set('itemsPerPage', '50') + params.set('itemsPerPage', '200') if (term.trim()) { - params.set('name', term.trim()) + params.set('search', term.trim()) } if (requiredTypeId) { params.set('typeComposant', typeIri(requiredTypeId)) @@ -173,9 +173,9 @@ export function useStructureAssignmentFetch(deps: StructureAssignmentFetchDeps) definition.typePieceId || definition.typePiece?.id || null const params = new URLSearchParams() - params.set('itemsPerPage', '50') + params.set('itemsPerPage', '200') if (term.trim()) { - params.set('name', term.trim()) + params.set('search', term.trim()) } if (requiredTypeId) { params.set('typePiece', typeIri(requiredTypeId)) @@ -246,9 +246,9 @@ export function useStructureAssignmentFetch(deps: StructureAssignmentFetchDeps) definition.typeProductId || definition.typeProduct?.id || null const params = new URLSearchParams() - params.set('itemsPerPage', '50') + params.set('itemsPerPage', '200') if (term.trim()) { - params.set('name', term.trim()) + params.set('search', term.trim()) } if (requiredTypeId) { params.set('typeProduct', typeIri(requiredTypeId))