376 lines
14 KiB
Vue
376 lines
14 KiB
Vue
<script>
|
|
import {mapGetters} from 'vuex'
|
|
import Input from '@atoms/VInput.vue'
|
|
import VButton from "@atoms/VButton.vue"
|
|
import {generatePassword, isFullLengthPassword, equalPasswords, isRepeatPasswordEmpty} from './helpers/validation.js'
|
|
|
|
export default {
|
|
name: 'UserEditor',
|
|
components: {Input, VButton},
|
|
props: {
|
|
id: {
|
|
default: -1,
|
|
type: Number
|
|
},
|
|
serviceOfUsers: {
|
|
default: () => ({}),
|
|
type: Object
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
repeatPassword: '',
|
|
showNewPassword: false,
|
|
newPasswordType: 'password',
|
|
showRepeatPassword: false,
|
|
repeatPasswordType: 'password',
|
|
errorPassword: null,
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters('services', ["selectedService"]),
|
|
...mapGetters('users', ['selectedUser']),
|
|
},
|
|
mounted() {
|
|
},
|
|
methods: {
|
|
editData (params) {
|
|
if (params.key === 'password') {
|
|
this.serviceOfUsers.setUserFields(params.key, params.value)
|
|
this.errorPassword = isFullLengthPassword(params.value)
|
|
if (this.errorPassword) return false
|
|
this.errorPassword = equalPasswords(params.value, this.repeatPassword)
|
|
if (this.errorPassword) return false
|
|
}
|
|
if (params.key === 'repeat_password') {
|
|
this.repeatPassword = params.value
|
|
this.errorPassword = equalPasswords(this.selectedUser.password, this.repeatPassword)
|
|
if (this.errorPassword) return false
|
|
}
|
|
this.serviceOfUsers.setUserFields(params.key, params.value)
|
|
},
|
|
saveUser() {
|
|
this.errorPassword = isRepeatPasswordEmpty(this.selectedUser.password, this.repeatPassword)
|
|
if (this.errorPassword) return false
|
|
this.selectedUser.id ? this.selectedUser.id === -1 ? this.serviceOfUsers.createUser(this.selectedService.id) : this.serviceOfUsers.updateUser() : ''
|
|
this.serviceOfUsers.setStatusUser('inactive')
|
|
},
|
|
getPassword () {
|
|
const pass = generatePassword()
|
|
this.serviceOfUsers.setUserFields('password', pass)
|
|
this.errorPassword = equalPasswords(pass, this.repeatPassword)
|
|
},
|
|
togglePass () {
|
|
this.showNewPassword = !this.showNewPassword
|
|
this.newPasswordType = this.showNewPassword ? 'text' : 'password'
|
|
},
|
|
toggleRepeatPass () {
|
|
this.showRepeatPassword = !this.showRepeatPassword
|
|
this.repeatPasswordType = this.showRepeatPassword ? 'text' : 'password'
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="grid gap-6 mb-6 md:grid-cols-2">
|
|
<div class="hidden">
|
|
<div class="relative hidden">
|
|
<Input
|
|
id="id"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
placeholder=""
|
|
name="id"
|
|
type="text"
|
|
value="1"
|
|
autocomplete="off"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="lastName"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Фамилия
|
|
</label>
|
|
<Input
|
|
id="lastName"
|
|
required=""
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="lastName"
|
|
type="text"
|
|
:value="selectedUser?.lastName"
|
|
InputClass="py-2"
|
|
placeholder="Фамилия"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="firstName"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Имя
|
|
</label>
|
|
<Input
|
|
id="firstName"
|
|
required=""
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="firstName"
|
|
type="text"
|
|
:value="selectedUser?.firstName"
|
|
autocomplete="off"
|
|
placeholder="Имя"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="secondName"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Отчество
|
|
</label>
|
|
<Input
|
|
id="secondName"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="secondName"
|
|
type="text"
|
|
:value="selectedUser?.secondName"
|
|
autocomplete="off"
|
|
placeholder="Отчество"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="email"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Почта
|
|
</label>
|
|
<Input
|
|
id="email"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="email"
|
|
type="mail"
|
|
:value="selectedUser?.email"
|
|
autocomplete="off"
|
|
placeholder="example@ya.ru"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="login"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Логин
|
|
</label>
|
|
<Input
|
|
id="login"
|
|
required=""
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="login"
|
|
type="login"
|
|
:value="selectedUser?.login"
|
|
autocomplete="off"
|
|
placeholder="Логин"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="position"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Должность
|
|
</label>
|
|
<Input
|
|
id="position"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="position"
|
|
type="text"
|
|
:value="selectedUser?.position"
|
|
autocomplete="off"
|
|
placeholder="Должность"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="phone"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Телефон
|
|
</label>
|
|
<Input
|
|
id="phone"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="phone"
|
|
type="tel"
|
|
:value="selectedUser?.phone"
|
|
autocomplete="off"
|
|
placeholder="123-45-678"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="company"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Компания
|
|
</label>
|
|
<Input
|
|
id="company"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="company"
|
|
type="text"
|
|
:value="selectedUser?.company"
|
|
autocomplete="off"
|
|
placeholder="Компания"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="col-span-2">
|
|
<div class="relative col-span-2">
|
|
<label
|
|
for="notes"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
notes
|
|
</label>
|
|
<Input
|
|
id="notes"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="notes"
|
|
type="text"
|
|
:value="selectedUser?.notes"
|
|
autocomplete="off"
|
|
placeholder="notes"
|
|
:onChange="editData"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="password"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Новый пароль
|
|
</label>
|
|
<Input
|
|
id="password"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="password"
|
|
:type="newPasswordType"
|
|
:value="selectedUser?.password"
|
|
autocomplete="off"
|
|
:placeholder="`${showNewPassword ? '' : '•••••••••'}`"
|
|
:onChange="editData"
|
|
/>
|
|
<i
|
|
id="showPass"
|
|
ref="showPass"
|
|
class="cursor-pointer transition-all text-slate-500 hover:text-slate-800 absolute ri-eye-line bottom-[4px] right-[7px]"
|
|
:class="{'hidden': showNewPassword, '': !showNewPassword}"
|
|
@click="togglePass"
|
|
/>
|
|
<i
|
|
id="hidePass"
|
|
ref="hidePass"
|
|
class="cursor-pointer transition-all text-slate-500 hover:text-slate-800 absolute ri-eye-off-line bottom-[4px] right-[7px]"
|
|
:class="{'hidden': !showNewPassword, '': showNewPassword}"
|
|
@click="togglePass"
|
|
/>
|
|
</div>
|
|
</div><div class="">
|
|
<div class="relative ">
|
|
<label
|
|
for="repeat_password"
|
|
class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300 text-left "
|
|
>
|
|
Повторить пароль
|
|
</label>
|
|
<Input
|
|
id="repeatPassword"
|
|
ref="repeatPassword"
|
|
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full py-1 pl-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 "
|
|
name="repeat_password"
|
|
:type="repeatPasswordType"
|
|
:value="repeatPassword"
|
|
autocomplete="off"
|
|
:placeholder="`${showRepeatPassword ? '' : '•••••••••'}`"
|
|
:onChange="editData"
|
|
/>
|
|
<i
|
|
id="showRepeatPass"
|
|
ref="showRepeatPass"
|
|
class="cursor-pointer transition-all text-slate-500 hover:text-slate-800 absolute ri-eye-line bottom-[4px] right-[7px]"
|
|
:class="{'hidden': showRepeatPassword, '': !showRepeatPassword}"
|
|
@click="toggleRepeatPass"
|
|
/>
|
|
<i
|
|
id="hideRepeatPass"
|
|
ref="hideRepeatPass"
|
|
class="cursor-pointer transition-all text-slate-500 hover:text-slate-800 absolute ri-eye-off-line bottom-[4px] right-[7px]"
|
|
:class="{'hidden': !showRepeatPassword, '': showRepeatPassword}"
|
|
@click="toggleRepeatPass"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-if="errorPassword"
|
|
class="text-red-500 text-xs mt-1"
|
|
>
|
|
{{ errorPassword }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-between gap-6 mb-6">
|
|
<div>
|
|
<VButton
|
|
type="button"
|
|
class=""
|
|
color="blue"
|
|
@click="getPassword"
|
|
>
|
|
<i class="ri-key-2-line" />
|
|
Сгенерировать пароль
|
|
</VButton>
|
|
</div>
|
|
<div class="flex gap-4 justify-end">
|
|
<div>
|
|
<VButton
|
|
type="button"
|
|
class=""
|
|
color="purple"
|
|
>
|
|
<i class="ri-printer-line" />
|
|
Распечатать
|
|
</VButton>
|
|
</div>
|
|
<div>
|
|
<VButton
|
|
color="blue"
|
|
test-id="save-user"
|
|
:disable="errorPassword !== null"
|
|
@click="saveUser"
|
|
>
|
|
<i class="ri-save-line cursor-pointer" />
|
|
Сохранить
|
|
</VButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|