297 lines
11 KiB
TypeScript
297 lines
11 KiB
TypeScript
import { useEffect, useState } from 'react'
|
||
import * as Dialog from '@radix-ui/react-dialog'
|
||
import { X } from 'lucide-react'
|
||
import { useMutation, useQuery } from '@apollo/client/react'
|
||
|
||
import {
|
||
GET_ORGANISATIONS_QUERY,
|
||
GET_USERS_PAGE_QUERY,
|
||
SIGN_UP_MUTATION,
|
||
} from '../../../../entities/employee/api/employee.graphql'
|
||
import type {
|
||
Employee,
|
||
EmployeeRole,
|
||
GetOrganisationsData,
|
||
GetOrganisationsVariables,
|
||
SignUpData,
|
||
SignUpVariables,
|
||
} from '../../../../entities/employee/model/types'
|
||
|
||
import './AddEmployeeModal.scss'
|
||
|
||
type AddEmployeeModalProps = {
|
||
open: boolean
|
||
mode?: 'create' | 'edit'
|
||
employee?: Employee | null
|
||
onOpenChange: (open: boolean) => void
|
||
}
|
||
|
||
export function AddEmployeeModal({
|
||
open,
|
||
mode = 'create',
|
||
employee = null,
|
||
onOpenChange,
|
||
}: AddEmployeeModalProps) {
|
||
const isEditMode = mode === 'edit'
|
||
const [orgId, setOrgId] = useState('')
|
||
const [lastName, setLastName] = useState('')
|
||
const [firstName, setFirstName] = useState('')
|
||
const [middleName, setMiddleName] = useState('')
|
||
const [username, setUsername] = useState('')
|
||
const [password, setPassword] = useState('')
|
||
const [role, setRole] = useState<EmployeeRole>('User')
|
||
|
||
useEffect(() => {
|
||
if (!open) return
|
||
|
||
if (isEditMode && employee) {
|
||
setOrgId(String(employee.org?.id ?? employee.orgId ?? ''))
|
||
setLastName(employee.lastName ?? '')
|
||
setFirstName(employee.firstName ?? '')
|
||
setMiddleName(employee.middleName ?? '')
|
||
setUsername('')
|
||
setPassword('')
|
||
setRole(employee.role ?? 'User')
|
||
return
|
||
}
|
||
|
||
if (!isEditMode) {
|
||
setLastName('')
|
||
setFirstName('')
|
||
setMiddleName('')
|
||
setUsername('')
|
||
setPassword('')
|
||
setRole('User')
|
||
setOrgId('')
|
||
}
|
||
}, [open, isEditMode, employee])
|
||
|
||
const {
|
||
data: organisationsData,
|
||
loading: organisationsLoading,
|
||
error: organisationsError,
|
||
} = useQuery<GetOrganisationsData, GetOrganisationsVariables>(
|
||
GET_ORGANISATIONS_QUERY,
|
||
{
|
||
variables: {},
|
||
skip: !open,
|
||
fetchPolicy: 'network-only',
|
||
},
|
||
)
|
||
|
||
const organisations = organisationsData?.getOrganisations.page ?? []
|
||
|
||
useEffect(() => {
|
||
if (!open) return
|
||
if (orgId) return
|
||
if (!organisations.length) return
|
||
|
||
setOrgId(String(organisations[0].id))
|
||
}, [open, organisations, orgId])
|
||
|
||
const [signUp, { loading, error }] = useMutation<SignUpData, SignUpVariables>(
|
||
SIGN_UP_MUTATION,
|
||
{
|
||
refetchQueries: [
|
||
{
|
||
query: GET_USERS_PAGE_QUERY,
|
||
variables: {},
|
||
},
|
||
],
|
||
onCompleted: () => {
|
||
setLastName('')
|
||
setFirstName('')
|
||
setMiddleName('')
|
||
setUsername('')
|
||
setPassword('')
|
||
setRole('User')
|
||
setOrgId('')
|
||
|
||
onOpenChange(false)
|
||
},
|
||
},
|
||
)
|
||
|
||
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
|
||
event.preventDefault()
|
||
|
||
if (!orgId) return
|
||
|
||
if (isEditMode) {
|
||
console.log('Редактирование сотрудника пока без мутации', {
|
||
id: employee?.id,
|
||
orgId,
|
||
lastName,
|
||
firstName,
|
||
middleName,
|
||
username,
|
||
password,
|
||
role,
|
||
})
|
||
|
||
onOpenChange(false)
|
||
return
|
||
}
|
||
|
||
signUp({
|
||
variables: {
|
||
orgId,
|
||
lastName,
|
||
firstName,
|
||
middleName,
|
||
username,
|
||
password,
|
||
role,
|
||
},
|
||
})
|
||
}
|
||
|
||
return (
|
||
<Dialog.Root open={open} onOpenChange={onOpenChange}>
|
||
<Dialog.Portal>
|
||
<Dialog.Overlay className="add-employee-modal__overlay" />
|
||
|
||
<Dialog.Content className="add-employee-modal">
|
||
<div className="add-employee-modal__header">
|
||
<div>
|
||
<Dialog.Title className="add-employee-modal__title">
|
||
{isEditMode ? 'Редактировать' : 'Добавить сотрудника'}
|
||
</Dialog.Title>
|
||
|
||
<Dialog.Description className="add-employee-modal__description">
|
||
{isEditMode
|
||
? 'Изменение данных пользователя системы MDM'
|
||
: 'Создание пользователя для доступа к системе MDM'}
|
||
</Dialog.Description>
|
||
</div>
|
||
|
||
<Dialog.Close className="add-employee-modal__close" type="button">
|
||
<X size={20} />
|
||
</Dialog.Close>
|
||
</div>
|
||
|
||
<form className="add-employee-form" onSubmit={handleSubmit}>
|
||
<label className="add-employee-field">
|
||
<span>Организация</span>
|
||
|
||
<select
|
||
value={orgId}
|
||
onChange={(event) => setOrgId(event.target.value)}
|
||
required
|
||
disabled={organisationsLoading || !organisations.length}
|
||
>
|
||
{organisationsLoading && (
|
||
<option value="">Загрузка организаций...</option>
|
||
)}
|
||
|
||
{!organisationsLoading && organisations.length === 0 && (
|
||
<option value="">Организации не найдены</option>
|
||
)}
|
||
|
||
{organisations.map((organisation) => (
|
||
<option key={organisation.id} value={String(organisation.id)}>
|
||
{organisation.name}
|
||
</option>
|
||
))}
|
||
</select>
|
||
</label>
|
||
|
||
<div className="add-employee-form__grid">
|
||
<label className="add-employee-field">
|
||
<span>Фамилия</span>
|
||
<input
|
||
value={lastName}
|
||
onChange={(event) => setLastName(event.target.value)}
|
||
placeholder="Например: Иванов"
|
||
required
|
||
/>
|
||
</label>
|
||
|
||
<label className="add-employee-field">
|
||
<span>Имя</span>
|
||
<input
|
||
value={firstName}
|
||
onChange={(event) => setFirstName(event.target.value)}
|
||
placeholder="Например: Иван"
|
||
required
|
||
/>
|
||
</label>
|
||
</div>
|
||
|
||
<label className="add-employee-field">
|
||
<span>Отчество</span>
|
||
<input
|
||
value={middleName}
|
||
onChange={(event) => setMiddleName(event.target.value)}
|
||
placeholder="Например: Иванович"
|
||
required
|
||
/>
|
||
</label>
|
||
|
||
<div className="add-employee-form__grid">
|
||
<label className="add-employee-field">
|
||
<span>Логин</span>
|
||
<input
|
||
value={username}
|
||
onChange={(event) => setUsername(event.target.value)}
|
||
placeholder="Например: user1"
|
||
required
|
||
/>
|
||
</label>
|
||
|
||
<label className="add-employee-field">
|
||
<span>Пароль</span>
|
||
<input
|
||
value={password}
|
||
onChange={(event) => setPassword(event.target.value)}
|
||
placeholder="Введите пароль"
|
||
type="password"
|
||
required
|
||
/>
|
||
</label>
|
||
</div>
|
||
|
||
<label className="add-employee-field">
|
||
<span>Роль</span>
|
||
|
||
<select
|
||
value={role}
|
||
onChange={(event) => setRole(event.target.value as EmployeeRole)}
|
||
required
|
||
>
|
||
<option value="User">Пользователь</option>
|
||
<option value="Admin">Администратор</option>
|
||
</select>
|
||
</label>
|
||
|
||
{organisationsError && (
|
||
<div className="add-employee-error">
|
||
Не удалось загрузить список организаций
|
||
</div>
|
||
)}
|
||
|
||
{error && (
|
||
<div className="add-employee-error">
|
||
Не удалось добавить сотрудника. Проверьте данные.
|
||
</div>
|
||
)}
|
||
|
||
<div className="add-employee-modal__footer">
|
||
<Dialog.Close className="add-employee-cancel" type="button">
|
||
Отмена
|
||
</Dialog.Close>
|
||
|
||
<button
|
||
className="add-employee-submit"
|
||
type="submit"
|
||
disabled={loading || organisationsLoading || !orgId}
|
||
>
|
||
{loading ? 'Добавление...' : isEditMode ? 'Сохранить' : 'Добавить'}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</Dialog.Content>
|
||
</Dialog.Portal>
|
||
</Dialog.Root>
|
||
)
|
||
} |