feat(frontend) : ERP-27 - admin users page with DataTable and RBAC drawer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
126
frontend/modules/core/pages/admin/users.vue
Normal file
126
frontend/modules/core/pages/admin/users.vue
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- En-tete -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h1 class="text-xl font-bold text-primary-500 sm:text-2xl">
|
||||||
|
{{ t('admin.users.title') }}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Table des utilisateurs -->
|
||||||
|
<MalioDataTable
|
||||||
|
class="mt-6"
|
||||||
|
:columns="columns"
|
||||||
|
:items="userItems"
|
||||||
|
:total-items="users.length"
|
||||||
|
:row-clickable="canManage"
|
||||||
|
:empty-message="t('admin.users.noUsers')"
|
||||||
|
@row-click="onRowClick"
|
||||||
|
>
|
||||||
|
<template #cell-admin="{ item }">
|
||||||
|
<span
|
||||||
|
v-if="item.admin"
|
||||||
|
class="inline-flex items-center rounded-full bg-purple-100 px-2.5 py-0.5 text-xs font-medium text-purple-800"
|
||||||
|
>
|
||||||
|
{{ t('admin.users.table.admin') }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #cell-actions="{ item }">
|
||||||
|
<div class="flex items-center justify-end gap-2" @click.stop>
|
||||||
|
<MalioButtonIcon
|
||||||
|
v-if="canManage"
|
||||||
|
icon="mdi:shield-edit-outline"
|
||||||
|
:aria-label="t('common.edit')"
|
||||||
|
variant="ghost"
|
||||||
|
@click="openDrawer(getUserById(item.id as number)!)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</MalioDataTable>
|
||||||
|
|
||||||
|
<!-- Drawer RBAC -->
|
||||||
|
<UserRbacDrawer
|
||||||
|
v-model="drawerOpen"
|
||||||
|
:user="selectedUser"
|
||||||
|
@saved="onUserSaved"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface UserListItem {
|
||||||
|
id: number
|
||||||
|
username: string
|
||||||
|
isAdmin: boolean
|
||||||
|
roles: string[]
|
||||||
|
directPermissions: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const api = useApi()
|
||||||
|
const { can } = usePermissions()
|
||||||
|
|
||||||
|
useHead({ title: t('admin.users.title') })
|
||||||
|
|
||||||
|
const canManage = can('core.users.manage')
|
||||||
|
|
||||||
|
const users = ref<UserListItem[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const drawerOpen = ref(false)
|
||||||
|
const selectedUser = ref<UserListItem | null>(null)
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ key: 'username', label: t('admin.users.table.username') },
|
||||||
|
{ key: 'admin', label: t('admin.users.table.admin') },
|
||||||
|
{ key: 'roles', label: t('admin.users.table.roles') },
|
||||||
|
{ key: 'directPermissions', label: t('admin.users.table.directPermissions') },
|
||||||
|
{ key: 'actions', label: t('admin.users.table.actions') },
|
||||||
|
]
|
||||||
|
|
||||||
|
const userItems = computed(() =>
|
||||||
|
users.value.map(user => ({
|
||||||
|
id: user.id,
|
||||||
|
username: user.username,
|
||||||
|
admin: user.isAdmin,
|
||||||
|
roles: user.roles.length,
|
||||||
|
directPermissions: user.directPermissions.length,
|
||||||
|
actions: '',
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
async function loadUsers() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await api.get<{ member: UserListItem[] }>(
|
||||||
|
'/users',
|
||||||
|
{},
|
||||||
|
{ toast: false },
|
||||||
|
)
|
||||||
|
users.value = data.member
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserById(id: number): UserListItem | undefined {
|
||||||
|
return users.value.find(u => u.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDrawer(user: UserListItem) {
|
||||||
|
selectedUser.value = user
|
||||||
|
drawerOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRowClick(item: Record<string, unknown>) {
|
||||||
|
const user = getUserById(item.id as number)
|
||||||
|
if (user) openDrawer(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onUserSaved() {
|
||||||
|
loadUsers()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadUsers()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user