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 @@ + + + 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 }} + +