Files
Coltura/frontend/modules/core/pages/admin/roles.vue
tristan 99e96cb493
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
[#ERP-41] Mise à jour Malio UI (#10)
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [x] TU/TI/TF rédigée
- [x] TU/TI/TF OK
- [ ] CHANGELOG modifié

Reviewed-on: #10
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-05-13 09:03:44 +00:00

166 lines
4.6 KiB
Vue

<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.roles.title') }}
</h1>
<MalioButton
v-if="can('core.roles.manage')"
:label="t('admin.roles.newRole')"
icon-name="mdi:add-bold"
icon-position="left"
@click="openCreateDrawer"
/>
</div>
<!-- Table des roles -->
<MalioDataTable
class="mt-6"
:columns="columns"
:items="roleItems"
:total-items="roles.length"
:row-clickable="canManage"
:empty-message="t('admin.roles.noRoles')"
@row-click="onRowClick"
>
<template #cell-code="{ item }">
<span class="font-mono text-xs">{{ item.code }}</span>
</template>
<template #cell-permissions="{ item }">
{{ item.permissions }}
</template>
<template #cell-system="{ item }">
<span
v-if="item.isSystem"
class="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800"
>
{{ t('admin.roles.table.system') }}
</span>
</template>
</MalioDataTable>
<!-- Drawer creation/edition -->
<RoleDrawer
v-model="drawerOpen"
:role="selectedRole"
@saved="onRoleSaved"
@delete="onDeleteRequest"
/>
<!-- Modale de suppression -->
<RoleDeleteModal
v-model="deleteModalOpen"
:role-label="roleToDelete?.label ?? ''"
:loading="deleting"
@confirm="handleDelete"
/>
</div>
</template>
<script setup lang="ts">
import type { Role } from '~/shared/types/rbac'
const { t } = useI18n()
const api = useApi()
const { can } = usePermissions()
const canManage = computed(() => can('core.roles.manage'))
useHead({ title: t('admin.roles.title') })
const roles = ref<Role[]>([])
const loading = ref(false)
const columns = [
{ key: 'label', label: t('admin.roles.table.label') },
{ key: 'code', label: t('admin.roles.table.code') },
{ key: 'permissions', label: t('admin.roles.table.permissions') },
{ key: 'system', label: t('admin.roles.table.system') },
]
// Transformer les roles en items compatibles MalioDataTable
const roleItems = computed(() =>
roles.value.map(role => ({
id: role.id,
label: role.label,
code: role.code,
permissions: role.permissions.length,
isSystem: role.isSystem,
system: '', // colonne geree par le slot
}))
)
function getRoleById(id: number): Role | undefined {
return roles.value.find(r => r.id === id)
}
function onRowClick(item: Record<string, unknown>) {
const role = getRoleById(item.id as number)
if (role) openEditDrawer(role)
}
const drawerOpen = ref(false)
const selectedRole = ref<Role | null>(null)
const deleteModalOpen = ref(false)
const roleToDelete = ref<Role | null>(null)
const deleting = ref(false)
// Charger la liste des roles
async function loadRoles() {
loading.value = true
try {
const data = await api.get<{ member: Role[] }>(
'/roles',
{},
{ toast: false },
)
roles.value = data.member
} catch {
// Reset sur echec pour ne pas afficher de donnees stale (ancienne
// requete reussie avant une perte reseau ou 403).
roles.value = []
} finally {
loading.value = false
}
}
function openCreateDrawer() {
selectedRole.value = null
drawerOpen.value = true
}
function openEditDrawer(role: Role) {
selectedRole.value = role
drawerOpen.value = true
}
function onDeleteRequest() {
if (!selectedRole.value || selectedRole.value.isSystem) return
roleToDelete.value = selectedRole.value
deleteModalOpen.value = true
}
async function handleDelete() {
if (!roleToDelete.value) return
deleting.value = true
try {
await api.delete(`/roles/${roleToDelete.value.id}`, {}, {
toastSuccessMessage: t('admin.roles.toast.deleted'),
})
deleteModalOpen.value = false
roleToDelete.value = null
drawerOpen.value = false
await loadRoles()
} finally {
deleting.value = false
}
}
function onRoleSaved() {
loadRoles()
}
onMounted(() => {
loadRoles()
})
</script>