New /activity-log page showing all audit entries across pieces, products and composants. Includes entity type and action filters, expandable diffs, clickable entity links and pagination. Navbar link added under Ressources liées. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
71 lines
2.0 KiB
TypeScript
71 lines
2.0 KiB
TypeScript
import { ref } from 'vue'
|
|
import { useApi } from '~/composables/useApi'
|
|
|
|
export type ActivityLogActor = {
|
|
id: string
|
|
label: string
|
|
}
|
|
|
|
export type ActivityLogEntry = {
|
|
id: string
|
|
entityType: string
|
|
entityId: string
|
|
entityName: string | null
|
|
entityRef: string | null
|
|
action: 'create' | 'update' | 'delete' | string
|
|
createdAt: string
|
|
actor: ActivityLogActor | null
|
|
diff: Record<string, { from: unknown; to: unknown }> | null
|
|
snapshot: Record<string, unknown> | null
|
|
}
|
|
|
|
interface LoadActivityLogOptions {
|
|
page?: number
|
|
itemsPerPage?: number
|
|
entityType?: string
|
|
action?: string
|
|
}
|
|
|
|
export function useActivityLog() {
|
|
const { get } = useApi()
|
|
|
|
const entries = ref<ActivityLogEntry[]>([])
|
|
const total = ref(0)
|
|
const loading = ref(false)
|
|
const error = ref<string | null>(null)
|
|
|
|
const loadActivityLog = async (options: LoadActivityLogOptions = {}) => {
|
|
loading.value = true
|
|
error.value = null
|
|
try {
|
|
const params = new URLSearchParams()
|
|
params.set('page', String(options.page ?? 1))
|
|
params.set('itemsPerPage', String(options.itemsPerPage ?? 30))
|
|
if (options.entityType) params.set('entityType', options.entityType)
|
|
if (options.action) params.set('action', options.action)
|
|
|
|
const result = await get(`/activity-logs?${params.toString()}`)
|
|
if (!result.success) {
|
|
error.value = result.error ?? 'Impossible de charger le journal d\'activité.'
|
|
entries.value = []
|
|
return result
|
|
}
|
|
|
|
const data = result.data as any
|
|
entries.value = Array.isArray(data?.items) ? data.items : []
|
|
total.value = typeof data?.total === 'number' ? data.total : entries.value.length
|
|
|
|
return { success: true, data: entries.value }
|
|
} catch (err: any) {
|
|
const message = err?.message ?? 'Erreur inconnue'
|
|
error.value = message
|
|
entries.value = []
|
|
return { success: false, error: message }
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
return { entries, total, loading, error, loadActivityLog }
|
|
}
|