yunohost-admin/app/src/views/user/UserCreate.vue
2024-08-13 11:56:52 +02:00

143 lines
3.5 KiB
Vue

<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import api from '@/api'
import { useDomains, useUsersAndGroups } from '@/composables/data'
import { useForm } from '@/composables/form'
import {
alphalownumdot_,
minLength,
name,
required,
sameAs,
unique,
} from '@/helpers/validators'
import { formatForm } from '@/helpers/yunohostArguments'
import type { FieldProps, FormFieldDict } from '@/types/form'
const { t } = useI18n()
const router = useRouter()
await api.fetchAll([
{ uri: 'users', cachePath: 'users' },
{ uri: 'domains', cachePath: 'domains' },
])
const { usernames } = useUsersAndGroups()
const { domainsAsChoices, mainDomain } = useDomains()
type Form = typeof form.value
const form = ref({
username: '',
fullname: '',
domain: mainDomain.value,
password: '',
confirmation: '',
})
const fields = {
username: reactive({
component: 'InputItem',
label: t('user_username'),
rules: computed(() => ({
required,
alphalownumdot_,
notInUsers: unique(usernames),
})),
cProps: {
id: 'username',
placeholder: t('placeholder.username'),
},
}) satisfies FieldProps<'InputItem', Form['username']>,
fullname: {
component: 'InputItem',
hr: true,
label: t('user_fullname'),
rules: { required, name },
cProps: {
id: 'fullname',
placeholder: t('placeholder.fullname'),
},
} satisfies FieldProps<'InputItem', Form['fullname']>,
domain: reactive({
component: 'SelectItem',
hr: true,
id: 'mail',
label: t('user_email'),
description: t('tip_about_user_email'),
descriptionVariant: 'info',
rules: { required },
cProps: { choices: domainsAsChoices },
}) satisfies FieldProps<'SelectItem', Form['domain']>,
password: {
component: 'InputItem',
label: t('password'),
description: t('good_practices_about_user_password'),
descriptionVariant: 'warning',
rules: { required, passwordLenght: minLength(8) },
cProps: {
id: 'password',
placeholder: '••••••••',
type: 'password',
},
} satisfies FieldProps<'InputItem', Form['password']>,
confirmation: reactive({
component: 'InputItem',
label: t('password_confirmation'),
rules: computed(() => ({
required,
passwordMatch: sameAs(form.value.password),
})),
cProps: {
id: 'confirmation',
placeholder: '••••••••',
type: 'password',
},
}) satisfies FieldProps<'InputItem', Form['confirmation']>,
} satisfies FormFieldDict<Form>
const { v, onSubmit } = useForm(form, fields)
const onUserCreate = onSubmit(async (onError) => {
const data = await formatForm(form)
api
.post({
uri: 'users',
cachePath: 'users',
data,
humanKey: { key: 'users.create', name: form.value.username },
})
.then(() => {
router.push({ name: 'user-list' })
})
.catch(onError)
})
</script>
<template>
<div>
<CardForm
v-model="form"
icon="user-plus"
:fields="fields"
:title="$t('users_new')"
:validations="v"
@submit.prevent="onUserCreate"
>
<template #component:domain="componentProps">
<BInputGroup>
<BInputGroupText id="local-part" tag="label" class="border-right-0">
{{ form.username }}@
</BInputGroupText>
<SelectItem v-bind="componentProps" v-model="form.domain" />
</BInputGroup>
</template>
</CardForm>
</div>
</template>