feat(history): add audit history views for products, pieces and components

This commit is contained in:
Matthieu
2026-01-25 21:20:14 +01:00
parent a7101c7e77
commit a1d15c23a4
6 changed files with 673 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
import { ref } from 'vue'
import { useApi } from '~/composables/useApi'
export type ComponentHistoryActor = {
id: string
label: string
}
export type ComponentHistoryEntry = {
id: string
action: 'create' | 'update' | 'delete' | string
createdAt: string
actor: ComponentHistoryActor | null
diff: Record<string, { from: unknown; to: unknown }> | null
snapshot: Record<string, unknown> | null
}
const extractItems = (payload: any): ComponentHistoryEntry[] => {
if (Array.isArray(payload?.items)) {
return payload.items
}
if (Array.isArray(payload?.member)) {
return payload.member
}
if (Array.isArray(payload?.['hydra:member'])) {
return payload['hydra:member']
}
return []
}
export function useComponentHistory () {
const { get } = useApi()
const history = ref<ComponentHistoryEntry[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
const loadHistory = async (componentId: string) => {
loading.value = true
error.value = null
try {
const result = await get(`/composants/${componentId}/history`)
if (!result.success) {
error.value = result.error ?? 'Impossible de charger lhistorique.'
history.value = []
return result
}
history.value = extractItems(result.data) as ComponentHistoryEntry[]
return { success: true, data: history.value }
} catch (err: any) {
const message = err?.message ?? 'Erreur inconnue'
error.value = message
history.value = []
return { success: false, error: message }
} finally {
loading.value = false
}
}
return {
history,
loading,
error,
loadHistory,
}
}

View File

@@ -0,0 +1,67 @@
import { ref } from 'vue'
import { useApi } from '~/composables/useApi'
export type PieceHistoryActor = {
id: string
label: string
}
export type PieceHistoryEntry = {
id: string
action: 'create' | 'update' | 'delete' | string
createdAt: string
actor: PieceHistoryActor | null
diff: Record<string, { from: unknown; to: unknown }> | null
snapshot: Record<string, unknown> | null
}
const extractItems = (payload: any): PieceHistoryEntry[] => {
if (Array.isArray(payload?.items)) {
return payload.items
}
if (Array.isArray(payload?.member)) {
return payload.member
}
if (Array.isArray(payload?.['hydra:member'])) {
return payload['hydra:member']
}
return []
}
export function usePieceHistory () {
const { get } = useApi()
const history = ref<PieceHistoryEntry[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
const loadHistory = async (pieceId: string) => {
loading.value = true
error.value = null
try {
const result = await get(`/pieces/${pieceId}/history`)
if (!result.success) {
error.value = result.error ?? 'Impossible de charger lhistorique.'
history.value = []
return result
}
history.value = extractItems(result.data) as PieceHistoryEntry[]
return { success: true, data: history.value }
} catch (err: any) {
const message = err?.message ?? 'Erreur inconnue'
error.value = message
history.value = []
return { success: false, error: message }
} finally {
loading.value = false
}
}
return {
history,
loading,
error,
loadHistory,
}
}

View File

@@ -0,0 +1,67 @@
import { ref } from 'vue'
import { useApi } from '~/composables/useApi'
export type ProductHistoryActor = {
id: string
label: string
}
export type ProductHistoryEntry = {
id: string
action: 'create' | 'update' | 'delete' | string
createdAt: string
actor: ProductHistoryActor | null
diff: Record<string, { from: unknown; to: unknown }> | null
snapshot: Record<string, unknown> | null
}
const extractItems = (payload: any): ProductHistoryEntry[] => {
if (Array.isArray(payload?.items)) {
return payload.items
}
if (Array.isArray(payload?.member)) {
return payload.member
}
if (Array.isArray(payload?.['hydra:member'])) {
return payload['hydra:member']
}
return []
}
export function useProductHistory () {
const { get } = useApi()
const history = ref<ProductHistoryEntry[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
const loadHistory = async (productId: string) => {
loading.value = true
error.value = null
try {
const result = await get(`/products/${productId}/history`)
if (!result.success) {
error.value = result.error ?? 'Impossible de charger lhistorique.'
history.value = []
return result
}
history.value = extractItems(result.data) as ProductHistoryEntry[]
return { success: true, data: history.value }
} catch (err: any) {
const message = err?.message ?? 'Erreur inconnue'
error.value = message
history.value = []
return { success: false, error: message }
} finally {
loading.value = false
}
}
return {
history,
loading,
error,
loadHistory,
}
}