diff --git a/app/components/layout/AppNavbar.vue b/app/components/layout/AppNavbar.vue index 50eacb5..ee6985b 100644 --- a/app/components/layout/AppNavbar.vue +++ b/app/components/layout/AppNavbar.vue @@ -275,11 +275,12 @@ const navGroups: NavGroup[] = [ { id: 'resources', label: 'Ressources liées', - activePaths: ['/sites', '/documents', '/constructeurs'], + activePaths: ['/sites', '/documents', '/constructeurs', '/activity-log'], children: [ { to: '/sites', label: 'Sites' }, { to: '/documents', label: 'Documents' }, { to: '/constructeurs', label: 'Fournisseurs' }, + { to: '/activity-log', label: 'Journal d\'activité' }, ], }, ] diff --git a/app/composables/useActivityLog.ts b/app/composables/useActivityLog.ts new file mode 100644 index 0000000..03d039b --- /dev/null +++ b/app/composables/useActivityLog.ts @@ -0,0 +1,70 @@ +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 | null + snapshot: Record | null +} + +interface LoadActivityLogOptions { + page?: number + itemsPerPage?: number + entityType?: string + action?: string +} + +export function useActivityLog() { + const { get } = useApi() + + const entries = ref([]) + const total = ref(0) + const loading = ref(false) + const error = ref(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 } +} diff --git a/app/pages/activity-log.vue b/app/pages/activity-log.vue new file mode 100644 index 0000000..2a0c220 --- /dev/null +++ b/app/pages/activity-log.vue @@ -0,0 +1,274 @@ + + +