143 lines
4.1 KiB
Vue
143 lines
4.1 KiB
Vue
<template>
|
|
<form @submit.prevent="validate">
|
|
<div class="flex items-center relative">
|
|
<div class="flex flex-row absolute -left-[60px]">
|
|
<Icon
|
|
@click="router.push('/admin/user/list')"
|
|
name="gg:arrow-left-o"
|
|
size="40"
|
|
class="cursor-pointer text-primary-500"
|
|
/>
|
|
</div>
|
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
|
{{ userId ? "Modification de l'utilisateur" : "Ajout d'un utilisateur" }}
|
|
</h1>
|
|
</div>
|
|
|
|
<div class="flex flex-cols-3 justify-between mb-11 pt-7">
|
|
<UiTextInput
|
|
id="user-name"
|
|
v-model="form.username"
|
|
label="Nom de l'utilisateur"
|
|
:disabled="!auth.isAdmin"
|
|
wrapper-class="w-[280px]"
|
|
/>
|
|
|
|
<UiSelect
|
|
id="user-role"
|
|
v-model="form.role"
|
|
label="Role de l'utilisateur"
|
|
:options="ROLE"
|
|
:disabled="!auth.isAdmin"
|
|
wrapper-class="w-[280px]"
|
|
/>
|
|
|
|
<UiTextInput
|
|
id="user-password"
|
|
v-model="form.password"
|
|
label="Mot de passe"
|
|
type="password"
|
|
:disabled="!auth.isAdmin"
|
|
wrapper-class="w-[280px]"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-center">
|
|
<UiButton
|
|
class="inline-flex mb-28 items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
|
type="submit"
|
|
:disabled="isLoading || isHydrating || !auth.isAdmin"
|
|
>
|
|
<Icon :name="userId ? '' : 'mdi:plus'" size="28" />
|
|
{{ userId ? 'Valider' : 'Ajouter' }}
|
|
</UiButton>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, reactive, ref, watch } from 'vue'
|
|
import { ROLE } from '~/utils/constants'
|
|
import { createUser, updateUser, getUser } from '~/services/auth'
|
|
import type { UserData, UserFormData, UserPayload } from '~/services/dto/user-data'
|
|
import { useAuthStore } from '~/stores/auth'
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const auth = useAuthStore()
|
|
const userId = computed(() => resolveUserId(route.params.id))
|
|
const isLoading = ref(false)
|
|
const isHydrating = ref(false)
|
|
|
|
const resolveUserId = (param: unknown) => {
|
|
const idStr = Array.isArray(param) ? param[0] : param
|
|
if (!idStr) {
|
|
return null
|
|
}
|
|
const id = Number(idStr)
|
|
return Number.isFinite(id) ? id : null
|
|
}
|
|
|
|
const form = reactive<UserFormData>({
|
|
username: '',
|
|
password: '',
|
|
role: ''
|
|
})
|
|
|
|
const hydrateFromUser = (user: UserData | null) => {
|
|
if (!user) {
|
|
return
|
|
}
|
|
isHydrating.value = true
|
|
form.username = user.username ?? ''
|
|
const roles = user.roles ?? []
|
|
const hasAdmin = roles.includes('ROLE_ADMIN')
|
|
form.role = hasAdmin ? 'ROLE_ADMIN' : 'ROLE_USER'
|
|
form.password = ''
|
|
isHydrating.value = false
|
|
}
|
|
|
|
watch(
|
|
() => userId.value,
|
|
async (id) => {
|
|
if (id === null) {
|
|
return
|
|
}
|
|
isLoading.value = true
|
|
try {
|
|
const user = await getUser(id)
|
|
hydrateFromUser(user)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
async function validate() {
|
|
if (!auth.isAdmin) return
|
|
|
|
const normalizedUsername = form.username.trim()
|
|
const normalizedRole = form.role.trim()
|
|
const normalizedPassword = form.password.trim()
|
|
|
|
const basePayload: UserPayload = {
|
|
username: normalizedUsername,
|
|
roles: normalizedRole ? [normalizedRole] : undefined,
|
|
}
|
|
if (normalizedPassword) {
|
|
basePayload.password = normalizedPassword
|
|
}
|
|
|
|
if (userId.value) {
|
|
await updateUser(userId.value, basePayload)
|
|
return
|
|
}
|
|
|
|
const created = await createUser(basePayload)
|
|
if (created) {
|
|
await router.push('/admin/user/list')
|
|
}
|
|
}
|
|
</script>
|