feat: add form for create new user

This commit is contained in:
Vladislav Syrochkin 2025-04-23 12:22:45 +05:00
parent 5300e53c43
commit 732dd701af
5 changed files with 403 additions and 113 deletions

View File

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 18C1.45 18 0.979167 17.8042 0.5875 17.4125C0.195833 17.0208 0 16.55 0 16V2C0 1.45 0.195833 0.979167 0.5875 0.5875C0.979167 0.195833 1.45 0 2 0H10V2H2V16H16V8H18V16C18 16.55 17.8042 17.0208 17.4125 17.4125C17.0208 17.8042 16.55 18 16 18H2ZM3 14H15L11.25 9L8.25 13L6 10L3 14ZM14 6V4H12V2H14V0H16V2H18V4H16V6H14Z" fill="#606060"/>
</svg>

After

Width:  |  Height:  |  Size: 443 B

View File

@ -6,12 +6,14 @@ interface ContentDrawerProps {
open: boolean;
closeDrawer: () => void;
children: React.ReactNode;
type: 'create' | 'edit';
}
export default function ContentDrawer({
open,
closeDrawer,
children,
type,
}: ContentDrawerProps) {
const [width, setWidth] = useState<number | string>('30%');
@ -27,7 +29,7 @@ export default function ContentDrawer({
return () => window.removeEventListener('resize', calculateWidths);
}, []);
const drawerTitle = (
const editDrawerTitle = (
<div
style={{
display: 'flex',
@ -86,9 +88,64 @@ export default function ContentDrawer({
</div>
);
const createDrawerTitle = (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 12,
}}
>
<div
onClick={closeDrawer}
style={{
display: 'flex',
alignItems: 'center',
height: '24px',
width: '24px',
cursor: 'pointer',
}}
>
<img
src="./icons/drawer/arrow_back.svg"
alt="close_drawer"
style={{ height: '16px', width: '16px' }}
/>
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
gap: 12,
flex: 1,
fontSize: '20px',
}}
>
Новая учетная запись
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
height: '24px',
width: '24px',
}}
>
<img
src="./icons/drawer/delete.svg"
alt="delete"
style={{ height: '18px', width: '16px' }}
/>
</div>
</div>
);
return (
<Drawer
title={drawerTitle}
title={type === 'create' ? createDrawerTitle : editDrawerTitle}
placement="right"
open={open}
width={width}

View File

@ -0,0 +1,227 @@
import { PlusOutlined } from '@ant-design/icons';
import {
Avatar,
Button,
Form,
Input,
Select,
Upload,
Image,
UploadFile,
GetProp,
UploadProps,
} from 'antd';
import { useState } from 'react';
const { Option } = Select;
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
const getBase64 = (file: FileType): Promise<string> =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = (error) => reject(error);
});
export default function UserCreate() {
const [previewOpen, setPreviewOpen] = useState(false);
const [previewImage, setPreviewImage] = useState('');
const [fileList, setFileList] = useState<UploadFile[]>([]);
const handlePreview = async (file: UploadFile) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj as FileType);
}
setPreviewImage(file.url || (file.preview as string));
setPreviewOpen(true);
};
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) =>
setFileList(newFileList);
const customUploadButton = (
<div>
<div
style={{
height: '102px',
width: '102px',
backgroundColor: '#E2E2E2',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 8,
marginTop: 30,
cursor: 'pointer',
}}
>
<img
src="./icons/drawer/add_photo_alternate.svg"
alt="add_photo_alternate"
style={{ height: '18px', width: '18px' }}
/>
</div>
<span style={{ fontSize: '14px', color: '#8c8c8c' }}>Выбрать фото</span>
</div>
);
const photoToUpload = (
<>
<Upload
listType="picture-circle"
fileList={fileList}
onPreview={handlePreview}
onChange={handleChange}
beforeUpload={() => false}
>
{fileList.length > 0 ? null : customUploadButton}
</Upload>
{previewImage && (
<Image
wrapperStyle={{ display: 'none' }}
preview={{
visible: previewOpen,
onVisibleChange: (visible) => setPreviewOpen(visible),
afterOpenChange: (visible) => !visible && setPreviewImage(''),
}}
src={previewImage}
/>
)}
</>
);
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
height: '100%',
}}
>
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '36px',
}}
>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
{photoToUpload}
</div>
</div>
<Form
name="user-edit-form"
layout="vertical"
// onFinish={onFinish}
initialValues={{
name: '',
login: '',
password: '',
email: '',
tenant: '',
role: '',
status: '',
}}
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
>
<Form.Item
label="Имя"
name="name"
rules={[{ required: true, message: 'Введите имя' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Логин"
name="login"
rules={[{ required: true, message: 'Введите логин' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Пароль"
name="password"
rules={[{ required: true, message: 'Введите пароль' }]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="E-mail"
name="email"
rules={[
{ required: true, message: 'Введите имейл' },
{ type: 'email', message: 'Некорректный имейл' },
]}
>
<Input />
</Form.Item>
<Form.Item
label="Привязка"
name="tenant"
rules={[{ required: true, message: 'Введите привязку' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Роль"
name="role"
rules={[{ required: true, message: 'Выберите роль' }]}
>
<Select placeholder="Выберите роль">
<Option value="Директор магазина">Директор магазина</Option>
<Option value="Менеджер">Менеджер</Option>
<Option value="Кассир">Кассир</Option>
</Select>
</Form.Item>
<Form.Item
label="Статус"
name="status"
rules={[{ required: true, message: 'Выберите статус' }]}
>
<Select placeholder="Выберите статус">
<Option value="ACTIVE">Активен</Option>
<Option value="DISABLED">Неактивен</Option>
<Option value="BLOCKED">Заблокирован</Option>
<Option value="DELETED">Удален</Option>
</Select>
</Form.Item>
<div style={{ flexGrow: 1 }} />
<Form.Item>
<Button
type="primary"
htmlType="submit"
block
style={{ color: '#000' }}
>
<img
src="/icons/drawer/reg.svg"
alt="save"
style={{ height: '18px', width: '18px' }}
/>{' '}
Добавить аккаунт
</Button>
</Form.Item>
</Form>
</div>
);
}

View File

@ -0,0 +1,111 @@
import { Button, Form, Input, Select } from 'antd';
const { Option } = Select;
export default function UserEdit() {
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Form
name="user-edit-form"
layout="vertical"
// onFinish={onFinish}
initialValues={{
name: 'Александр Александров',
login: 'alexandralex@vorkout.ru',
password: 'jKUUl776GHd',
email: 'alexandralex@vorkout.ru',
tenant: 'text',
role: 'Директор магазина',
status: 'Активен',
}}
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
>
<Form.Item
label="Имя"
name="name"
rules={[{ required: true, message: 'Введите имя' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Логин"
name="login"
rules={[{ required: true, message: 'Введите логин' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Пароль (последний ввод)"
name="password"
rules={[{ required: true, message: 'Введите пароль' }]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="E-mail"
name="email"
rules={[
{ required: true, message: 'Введите имейл' },
{ type: 'email', message: 'Некорректный имейл' },
]}
>
<Input />
</Form.Item>
<Form.Item
label="Привязка"
name="tenant"
rules={[{ required: true, message: 'Введите привязку' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Роль"
name="role"
rules={[{ required: true, message: 'Выберите роль' }]}
>
<Select placeholder="Выберите роль">
<Option value="Директор магазина">Директор магазина</Option>
<Option value="Менеджер">Менеджер</Option>
<Option value="Кассир">Кассир</Option>
</Select>
</Form.Item>
<Form.Item
label="Статус"
name="status"
rules={[{ required: true, message: 'Выберите статус' }]}
>
<Select placeholder="Выберите статус">
<Option value="ACTIVE">Активен</Option>
<Option value="DISABLED">Неактивен</Option>
<Option value="BLOCKED">Заблокирован</Option>
<Option value="DELETED">Удален</Option>
</Select>
</Form.Item>
<div style={{ flexGrow: 1 }} />
<Form.Item>
<Button
type="primary"
htmlType="submit"
block
style={{ color: '#000' }}
>
<img
src="/icons/drawer/save.svg"
alt="save"
style={{ height: '18px', width: '18px' }}
/>{' '}
Сохранить изменения
</Button>
</Form.Item>
</Form>
</div>
);
}

View File

@ -1,9 +1,7 @@
import { Button, Form, Input, Select } from 'antd';
import Header from '../components/Header';
import { useState } from 'react';
import ContentDrawer from '../components/ContentDrawer';
const { Option } = Select;
import UserCreate from '../components/UserCreate';
export default function AccountsPage() {
const [open, setOpen] = useState(false);
@ -11,112 +9,6 @@ export default function AccountsPage() {
const showDrawer = () => setOpen(true);
const closeDrawer = () => setOpen(false);
const userEdit = (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Form
name="user-edit-form"
layout="vertical"
// onFinish={onFinish}
initialValues={{
name: 'Александр Александров',
login: 'alexandralex@vorkout.ru',
password: 'jKUUl776GHd',
email: 'alexandralex@vorkout.ru',
tenant: 'text',
role: 'Директор магазина',
status: 'Активен',
}}
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
>
<Form.Item
label="Имя"
name="name"
rules={[{ required: true, message: 'Введите имя' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Логин"
name="login"
rules={[{ required: true, message: 'Введите логин' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Пароль (последний ввод)"
name="password"
rules={[{ required: true, message: 'Введите пароль' }]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="E-mail"
name="email"
rules={[
{ required: true, message: 'Введите имейл' },
{ type: 'email', message: 'Некорректный имейл' },
]}
>
<Input />
</Form.Item>
<Form.Item
label="Привязка"
name="tenant"
rules={[{ required: true, message: 'Введите привязку' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Роль"
name="role"
rules={[{ required: true, message: 'Выберите роль' }]}
>
<Select placeholder="Выберите роль">
<Option value="Директор магазина">Директор магазина</Option>
<Option value="Менеджер">Менеджер</Option>
<Option value="Кассир">Кассир</Option>
</Select>
</Form.Item>
<Form.Item
label="Статус"
name="status"
rules={[{ required: true, message: 'Выберите статус' }]}
>
<Select placeholder="Выберите статус">
<Option value="ACTIVE">Активен</Option>
<Option value="DISABLED">Неактивен</Option>
<Option value="BLOCKED">Заблокирован</Option>
<Option value="DELETED">Удален</Option>
</Select>
</Form.Item>
<div style={{ flexGrow: 1 }} />
<Form.Item>
<Button
type="primary"
htmlType="submit"
block
style={{ color: '#000' }}
>
<img
src="/icons/drawer/reg.svg"
alt="save"
style={{ height: '18px', width: '18px' }}
/>{' '}
Сохранить изменения
</Button>
</Form.Item>
</Form>
</div>
);
return (
<>
<Header
@ -135,8 +27,8 @@ export default function AccountsPage() {
}
/>
<ContentDrawer open={open} closeDrawer={closeDrawer}>
{userEdit}
<ContentDrawer open={open} closeDrawer={closeDrawer} type="create">
<UserCreate />
</ContentDrawer>
</>
);