From 8b02f821d3acf062f5225020334576e47b6f9451 Mon Sep 17 00:00:00 2001
From: r-dev
Date: Sat, 4 Apr 2026 17:29:13 +0200
Subject: [PATCH] feat(ui) : add UsedInSection showing reverse entity
relationships on detail pages
---
.../app/components/common/UsedInSection.vue | 49 +++++++++++++++++
frontend/app/composables/useUsedIn.ts | 52 +++++++++++++++++++
frontend/app/pages/component/[id]/index.vue | 2 +
frontend/app/pages/piece/[id].vue | 2 +
frontend/app/pages/product/[id]/index.vue | 2 +
5 files changed, 107 insertions(+)
create mode 100644 frontend/app/components/common/UsedInSection.vue
create mode 100644 frontend/app/composables/useUsedIn.ts
diff --git a/frontend/app/components/common/UsedInSection.vue b/frontend/app/components/common/UsedInSection.vue
new file mode 100644
index 0000000..523e08f
--- /dev/null
+++ b/frontend/app/components/common/UsedInSection.vue
@@ -0,0 +1,49 @@
+
+
+
Utilisé dans
+
+
+
Machines
+
+
+ {{ m.name }}
+
+ {{ m.site.name }}
+
+
+
+
+
Composants
+
+
+ {{ c.name }}
+
+
+
+
+
+
Pièces
+
+
+ {{ p.name }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/app/composables/useUsedIn.ts b/frontend/app/composables/useUsedIn.ts
new file mode 100644
index 0000000..937c94f
--- /dev/null
+++ b/frontend/app/composables/useUsedIn.ts
@@ -0,0 +1,52 @@
+import type { Ref } from 'vue'
+
+interface UsedInMachine {
+ id: string
+ name: string
+ site?: { id: string; name: string } | null
+}
+
+interface UsedInEntity {
+ id: string
+ name: string
+}
+
+interface UsedInData {
+ machines: UsedInMachine[]
+ composants: UsedInEntity[]
+ pieces: UsedInEntity[]
+}
+
+export function useUsedIn(entityType: Ref, entityId: Ref) {
+ const data = ref({ machines: [], composants: [], pieces: [] })
+ const loading = ref(false)
+
+ const api = useApi()
+
+ const load = async () => {
+ if (!entityId.value) return
+ loading.value = true
+ try {
+ const result = await api.get(`/${entityType.value}/${entityId.value}/used-in`)
+ if (result.success && result.data) {
+ data.value = {
+ machines: result.data.machines || [],
+ composants: result.data.composants || [],
+ pieces: result.data.pieces || [],
+ }
+ }
+ } finally {
+ loading.value = false
+ }
+ }
+
+ const totalCount = computed(() =>
+ data.value.machines.length + data.value.composants.length + data.value.pieces.length
+ )
+
+ watch(entityId, (val) => {
+ if (val) load()
+ }, { immediate: true })
+
+ return { data, loading, totalCount, load }
+}
diff --git a/frontend/app/pages/component/[id]/index.vue b/frontend/app/pages/component/[id]/index.vue
index f8f7719..93a5cee 100644
--- a/frontend/app/pages/component/[id]/index.vue
+++ b/frontend/app/pages/component/[id]/index.vue
@@ -198,6 +198,8 @@
+
+
diff --git a/frontend/app/pages/piece/[id].vue b/frontend/app/pages/piece/[id].vue
index 156b455..feb3d53 100644
--- a/frontend/app/pages/piece/[id].vue
+++ b/frontend/app/pages/piece/[id].vue
@@ -222,6 +222,8 @@
:preview-badge="formatPieceStructurePreview(resolvedStructure)"
variant="piece"
/>
+
+
diff --git a/frontend/app/pages/product/[id]/index.vue b/frontend/app/pages/product/[id]/index.vue
index 1eed495..072d131 100644
--- a/frontend/app/pages/product/[id]/index.vue
+++ b/frontend/app/pages/product/[id]/index.vue
@@ -198,6 +198,8 @@
{{ structurePreview }}
+
+