89ce523019
- badge « Archivé » et libellé barré dans la liste admin - popup de confirmation avant archivage (rappelle que c'est réversible) - bouton de restauration (PATCH archived:false) pour les archivés - case « Afficher les utilisateurs archivés » (filtre ?archived=true) - masque l'action d'archivage sur son propre compte (évite le 403) - service users : getArchived/restore, toast remove -> users.archived - i18n FR : clés archived/restored/badge/confirmation
167 lines
4.7 KiB
Vue
167 lines
4.7 KiB
Vue
<template>
|
|
<div>
|
|
<div class="flex items-center justify-between">
|
|
<h2 class="text-lg font-bold text-neutral-900">Utilisateurs</h2>
|
|
<MalioButton
|
|
icon-name="mdi:plus"
|
|
icon-position="left"
|
|
button-class="w-auto px-4"
|
|
label="Ajouter un utilisateur"
|
|
@click="openCreate"
|
|
/>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<MalioCheckbox
|
|
v-model="showArchived"
|
|
:label="$t('users.showArchived')"
|
|
:reserve-message-space="false"
|
|
/>
|
|
</div>
|
|
|
|
<DataTable
|
|
:columns="columns"
|
|
:items="items"
|
|
:loading="isLoading"
|
|
empty-message="Aucun utilisateur trouvé."
|
|
@row-click="openEdit"
|
|
>
|
|
<template #cell-username="{ item }">
|
|
<span :class="{ 'text-neutral-400 line-through': item.archived }">
|
|
{{ item.username }}
|
|
</span>
|
|
<span
|
|
v-if="item.archived"
|
|
class="ml-2 rounded-full bg-red-100 px-2 py-0.5 text-xs font-semibold text-red-700"
|
|
>
|
|
{{ $t('users.archivedBadge') }}
|
|
</span>
|
|
</template>
|
|
|
|
<template #cell-roles="{ item }">
|
|
<span
|
|
v-for="role in item.roles"
|
|
:key="role"
|
|
class="mr-1 rounded-full bg-neutral-200 px-2 py-0.5 text-xs font-semibold text-neutral-700"
|
|
>
|
|
{{ role }}
|
|
</span>
|
|
</template>
|
|
|
|
<template #actions="{ item }">
|
|
<MalioButtonIcon
|
|
v-if="item.archived"
|
|
icon="mdi:restore"
|
|
:aria-label="$t('users.restore')"
|
|
variant="ghost"
|
|
icon-size="20"
|
|
button-class="text-neutral-400 hover:text-primary-500"
|
|
@click.stop="handleRestore(item)"
|
|
/>
|
|
<MalioButtonIcon
|
|
v-else-if="item.id !== currentUserId"
|
|
icon="mdi:delete-outline"
|
|
:aria-label="$t('users.archive')"
|
|
variant="ghost"
|
|
icon-size="20"
|
|
button-class="text-neutral-400 hover:text-red-500"
|
|
@click.stop="openArchiveConfirm(item)"
|
|
/>
|
|
</template>
|
|
</DataTable>
|
|
|
|
<UserDrawer
|
|
v-model="drawerOpen"
|
|
:item="selectedItem"
|
|
@saved="onSaved"
|
|
/>
|
|
|
|
<ConfirmArchiveUserModal
|
|
v-model="archiveConfirmOpen"
|
|
:username="userToArchive?.username ?? ''"
|
|
@confirm="confirmArchive"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { UserData } from '~/services/dto/user-data'
|
|
import { useUserService } from '~/services/users'
|
|
import { useAuthStore } from '~/shared/stores/auth'
|
|
|
|
import type { DataTableColumn } from '~/components/ui/DataTable.vue'
|
|
|
|
const columns: DataTableColumn[] = [
|
|
{ key: 'username', label: "Nom d'utilisateur", primary: true },
|
|
{ key: 'roles', label: 'Rôles' },
|
|
]
|
|
|
|
const { getAll, getArchived, remove, restore } = useUserService()
|
|
const authStore = useAuthStore()
|
|
const currentUserId = computed(() => authStore.user?.id)
|
|
|
|
const items = ref<UserData[]>([])
|
|
const isLoading = ref(true)
|
|
const drawerOpen = ref(false)
|
|
const selectedItem = ref<UserData | null>(null)
|
|
const showArchived = ref(false)
|
|
const archiveConfirmOpen = ref(false)
|
|
const userToArchive = ref<UserData | null>(null)
|
|
|
|
async function loadItems() {
|
|
isLoading.value = true
|
|
try {
|
|
if (showArchived.value) {
|
|
const [active, archived] = await Promise.all([getAll(), getArchived()])
|
|
items.value = [...active, ...archived]
|
|
} else {
|
|
items.value = await getAll()
|
|
}
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
function openCreate() {
|
|
selectedItem.value = null
|
|
drawerOpen.value = true
|
|
}
|
|
|
|
function openEdit(item: UserData) {
|
|
selectedItem.value = item
|
|
drawerOpen.value = true
|
|
}
|
|
|
|
function openArchiveConfirm(item: UserData) {
|
|
userToArchive.value = item
|
|
archiveConfirmOpen.value = true
|
|
}
|
|
|
|
async function confirmArchive() {
|
|
if (!userToArchive.value) {
|
|
return
|
|
}
|
|
await remove(userToArchive.value.id)
|
|
archiveConfirmOpen.value = false
|
|
userToArchive.value = null
|
|
await loadItems()
|
|
}
|
|
|
|
async function handleRestore(item: UserData) {
|
|
await restore(item.id)
|
|
await loadItems()
|
|
}
|
|
|
|
async function onSaved() {
|
|
await loadItems()
|
|
}
|
|
|
|
watch(showArchived, () => {
|
|
loadItems()
|
|
})
|
|
|
|
onMounted(() => {
|
|
loadItems()
|
|
})
|
|
</script>
|