refactoring code part 1

parent e09dda18
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"react-router-dom": "^6.25.1" "react-router-dom": "^6.25.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.14.12",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.15.0", "@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0", "@typescript-eslint/parser": "^7.15.0",
...@@ -1521,6 +1522,15 @@ ...@@ -1521,6 +1522,15 @@
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA=="
}, },
"node_modules/@types/node": {
"version": "20.14.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz",
"integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.12", "version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
...@@ -4216,6 +4226,12 @@ ...@@ -4216,6 +4226,12 @@
"node": ">=14.17" "node": ">=14.17"
} }
}, },
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
......
...@@ -6,7 +6,6 @@ import HomePage from './pages/HomePage/HomePage'; ...@@ -6,7 +6,6 @@ import HomePage from './pages/HomePage/HomePage';
import RequestPage from './pages/RequestPage/RequestPage'; import RequestPage from './pages/RequestPage/RequestPage';
import AddPage from './pages/(crudPages)/AddPage'; import AddPage from './pages/(crudPages)/AddPage';
import EditPage from './pages/(crudPages)/EditPage'; import EditPage from './pages/(crudPages)/EditPage';
import 'react-material-symbols/rounded'; import 'react-material-symbols/rounded';
import './App.css'; import './App.css';
......
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
background: transparent; background: transparent;
} }
/* Customizing drawer */ /* Customizing drawer */
.custom-drawer { .custom-drawer {
color: #fff; color: #fff;
......
import React, { useState } from 'react'; import React, { useState } from 'react';
import { MaterialSymbol } from 'react-material-symbols';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Menu, Button, Drawer } from 'antd'; import { Menu, Button, Drawer } from 'antd';
import type { MenuProps } from 'antd'; import type { MenuProps } from 'antd';
import { MaterialSymbol } from 'react-material-symbols';
import './Header.css'; import './Header.css';
type MenuItem = Required<MenuProps>['items'][number]; type MenuItem = Required<MenuProps>['items'][number];
......
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
interface Organization { interface Organization {
id: number | string; id: number | string;
bin: string; bin: string;
organization_code: string; organization_code: string;
organization_name: string; organization_name: string;
......
...@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client' ...@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client'
import App from './App.tsx' import App from './App.tsx'
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import './index.css' import './index.css'
import store from './store.tsx'; import store from '../src/store/store.ts';
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>
......
import React from 'react'; import React from 'react';
import { Form, Input, Button, Select, message } from 'antd';
import { useNavigate } from 'react-router'; import { useNavigate } from 'react-router';
import { Form, Input, Button, Select, message } from 'antd';
import { useAddNewOrganizationMutation } from '../../features/api/apiSlice'; import { useAddNewOrganizationMutation } from '../../features/api/apiSlice';
import './style.css'; import './style.css';
interface AddValues{
bin: string;
host: string;
login: string;
organization_code: string;
organization_name: string;
password: string;
status: string;
}
const { Item } = Form; const { Item } = Form;
const { Option } = Select; const { Option } = Select;
...@@ -11,7 +21,7 @@ const AddPage: React.FC = () => { ...@@ -11,7 +21,7 @@ const AddPage: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [addNewOrganization] = useAddNewOrganizationMutation(); const [addNewOrganization] = useAddNewOrganizationMutation();
const onFinish = async (values: any) => { const onFinish = async (values: AddValues) => {
const newValues = { const newValues = {
...values, ...values,
status: values.status === 'active' ? '2' : values.status === 'blocked' ? '1' : '0', status: values.status === 'active' ? '2' : values.status === 'blocked' ? '1' : '0',
...@@ -20,9 +30,9 @@ const AddPage: React.FC = () => { ...@@ -20,9 +30,9 @@ const AddPage: React.FC = () => {
}; };
try { try {
await addNewOrganization(newValues).unwrap(); await addNewOrganization(newValues).unwrap(); // get data from promise
message.success('Организация успешно добавлена!'); message.success('Организация успешно добавлена!');
console.log(values); // console.log('Add values: ', values);
navigate('/'); navigate('/');
} catch (err) { } catch (err) {
message.error('Произошла ошибка при добавлении организации!'); message.error('Произошла ошибка при добавлении организации!');
...@@ -46,7 +56,7 @@ const AddPage: React.FC = () => { ...@@ -46,7 +56,7 @@ const AddPage: React.FC = () => {
{ pattern: /^\d{12}$/, message: 'БИН должен состоять из 12 цифр!' } { pattern: /^\d{12}$/, message: 'БИН должен состоять из 12 цифр!' }
]} ]}
> >
<Input maxLength={12} placeholder="12 цифр" /> <Input maxLength={12} placeholder="Максимальная длина: 12 цифр" />
</Item> </Item>
<Item <Item
...@@ -57,7 +67,7 @@ const AddPage: React.FC = () => { ...@@ -57,7 +67,7 @@ const AddPage: React.FC = () => {
{ pattern: /^[a-zA-Z0-9-_]+$/, message: 'Код организации должен содержать только английские буквы, цифры, символы "-" и "_"' } { pattern: /^[a-zA-Z0-9-_]+$/, message: 'Код организации должен содержать только английские буквы, цифры, символы "-" и "_"' }
]} ]}
> >
<Input maxLength={128} /> <Input maxLength={128} placeholder='Максимальная длина: 128 символов'/>
</Item> </Item>
<Item <Item
...@@ -65,7 +75,7 @@ const AddPage: React.FC = () => { ...@@ -65,7 +75,7 @@ const AddPage: React.FC = () => {
name="organization_name" name="organization_name"
rules={[{ required: true, message: 'Пожалуйста, введите наименование организации!' }]} rules={[{ required: true, message: 'Пожалуйста, введите наименование организации!' }]}
> >
<Input maxLength={128} /> <Input maxLength={128} placeholder='Максимальная длина: 128 символов' />
</Item> </Item>
<Item <Item
...@@ -73,7 +83,7 @@ const AddPage: React.FC = () => { ...@@ -73,7 +83,7 @@ const AddPage: React.FC = () => {
name="host" name="host"
rules={[{ required: true, message: 'Пожалуйста, введите адрес системы/хост!' }]} rules={[{ required: true, message: 'Пожалуйста, введите адрес системы/хост!' }]}
> >
<Input maxLength={128} /> <Input maxLength={128} placeholder='Максимальная длина: 128 символов' />
</Item> </Item>
<Item <Item
...@@ -84,7 +94,7 @@ const AddPage: React.FC = () => { ...@@ -84,7 +94,7 @@ const AddPage: React.FC = () => {
{ pattern: /^[a-zA-Z0-9-_]+$/, message: 'Логин должен содержать только английские буквы, цифры, символы "-" и "_"' } { pattern: /^[a-zA-Z0-9-_]+$/, message: 'Логин должен содержать только английские буквы, цифры, символы "-" и "_"' }
]} ]}
> >
<Input maxLength={128} /> <Input maxLength={128} placeholder='Максимальная длина: 128 символов' />
</Item> </Item>
<Item <Item
...@@ -95,7 +105,7 @@ const AddPage: React.FC = () => { ...@@ -95,7 +105,7 @@ const AddPage: React.FC = () => {
{ pattern: /^[a-zA-Z0-9-_]+$/, message: 'Пароль должен содержать только английские буквы, цифры, символы "-" и "_"' } { pattern: /^[a-zA-Z0-9-_]+$/, message: 'Пароль должен содержать только английские буквы, цифры, символы "-" и "_"' }
]} ]}
> >
<Input.Password maxLength={128} /> <Input.Password maxLength={128} placeholder='Максимальная длина: 128 символов' />
</Item> </Item>
<Item <Item
......
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Form, Input, Button, Select, message } from 'antd';
import { useNavigate, useParams } from 'react-router'; import { useNavigate, useParams } from 'react-router';
import { Form, Input, Button, Select, message } from 'antd';
import { useGetOrganizationQuery, useEditOrganizationMutation } from '../../features/api/apiSlice'; import { useGetOrganizationQuery, useEditOrganizationMutation } from '../../features/api/apiSlice';
import './style.css'; import './style.css';
interface EditValues {
id: string;
bin: string;
host: string;
login: string;
organization_code: string;
organization_name: string;
password: string;
status: string;
}
const { Item } = Form; const { Item } = Form;
const { Option } = Select; const { Option } = Select;
...@@ -23,7 +34,7 @@ const EditPage: React.FC = () => { ...@@ -23,7 +34,7 @@ const EditPage: React.FC = () => {
} }
}, [data, form]); }, [data, form]);
const onFinish = async (values: any) => { const onFinish = async (values: EditValues) => {
const updatedValues = { const updatedValues = {
...values, ...values,
status: values.status === 'active' ? '2' : values.status === 'blocked' ? '1' : '0', status: values.status === 'active' ? '2' : values.status === 'blocked' ? '1' : '0',
...@@ -31,8 +42,9 @@ const EditPage: React.FC = () => { ...@@ -31,8 +42,9 @@ const EditPage: React.FC = () => {
}; };
try { try {
await editOrganization({ id: data?.id, ...updatedValues }).unwrap(); await editOrganization({ ...updatedValues }).unwrap();
message.success('Организация успешно обновлена!'); message.success('Организация успешно обновлена!');
// console.log('Edit values: ', values);
navigate('/'); navigate('/');
} catch (err) { } catch (err) {
message.error('Произошла ошибка при обновлении организации!'); message.error('Произошла ошибка при обновлении организации!');
......
...@@ -7,13 +7,10 @@ ...@@ -7,13 +7,10 @@
} }
.form { .form {
margin-left: 20px; margin: 10px 20px 80px 20px;
margin-right: 20px;
margin-top: 10px;
padding-right: 20px; padding-right: 20px;
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
margin-bottom: 80px;
} }
.form-footer { .form-footer {
......
...@@ -4,9 +4,7 @@ ...@@ -4,9 +4,7 @@
left: 50%; left: 50%;
-webkit-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
padding: 24px; padding: 24px;
background-color: rgba(209, 209, 209, 0.866); background-color: rgba(209, 209, 209, 0.866);
border-radius: 8px; border-radius: 8px;
} }
......
import { Input, Typography, Button } from 'antd';
import React from 'react'; import React from 'react';
import { Input, Typography, Button } from 'antd';
import styles from './AuthPage.module.css'; import styles from './AuthPage.module.css';
const AuthPage: React.FC = () => { const AuthPage: React.FC = () => {
......
import React, { useState } from 'react';
import { useNavigate } from 'react-router';
import { MaterialSymbol } from 'react-material-symbols';
import { Button, Space, Tag, Modal, message } from 'antd';
import type { TableProps } from 'antd';
import './Homepage.css';
import { useDeleteOrganizationMutation } from '../../features/api/apiSlice';
export interface DataType {
id: string | number;
bin: string;
organization_code: string;
organization_name: string;
status: string;
host: string;
}
export const columns: TableProps<DataType>['columns'] = [
{
title: "ID",
dataIndex: "id",
key: "id"
},
{
title: "БИН",
dataIndex: "bin",
key: "bin"
},
{
title: "Код организации",
dataIndex: "organization_code",
key: "code"
},
{
title: "Наименование организации",
dataIndex: "organization_name",
key: "name"
},
{
title: "Адрес системы/хост",
dataIndex: "host",
key: "host"
},
{
title: "Статус",
dataIndex: "status",
key: "status",
render: (_, record) => {
const color = record.status === '0' ? 'red' : record.status === '1' ? 'processing' : 'green';
return (
<p>
<Tag color={color} style={{ fontSize: '14px' }}>
{record.status === '0' ? 'удален' : record.status === '1' ? 'заблокирован' : 'активен'}
</Tag>
</p>
)
}
},
{
title: "Действия",
width: 60,
render: (_, record) => {
return (
<ActionColumn data={record} />
)
}
}
]
export const ActionColumn: React.FC<{ data: DataType }> = ({ data }) => {
const [open, setOpen] = useState<boolean>(false);
const navigate = useNavigate();
const [deleteOrganization] = useDeleteOrganizationMutation();
const showDeleteModal = () => {
setOpen(true);
};
const handleDeleteModalOk = async () => {
try {
await deleteOrganization(Number(data.id)).unwrap();
message.success('Организация успешно удалена!');
setOpen(false);
} catch (err) {
message.error('Произошла ошибка при удалении организации!');
}
};
const handleDeleteModalCancel = () => {
setOpen(false);
};
const handleEditClick = () => {
navigate(`/edit/${data.id.toString()}`);
}
return (
<Space>
<Button onClick={handleEditClick} icon={<MaterialSymbol icon='visibility' size={22} />} />
<Button onClick={showDeleteModal} icon={<MaterialSymbol icon='delete' size={22} />} />
<Modal
open={open}
title={`Вы уверены в том, что хотите удалить ${data.organization_name}?`}
footer={() => (
<div style={{ textAlign: 'start', marginTop: '1rem' }}>
<Button key="submit" type="primary" danger onClick={handleDeleteModalOk} style={{ marginRight: '.5rem' }}>
Удалить
</Button>
<Button key="back" onClick={handleDeleteModalCancel}>
Назад
</Button>
</div>
)}
/>
</Space>
)
}
\ No newline at end of file
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router'; import { useNavigate } from 'react-router';
import { MaterialSymbol } from 'react-material-symbols'; import { MaterialSymbol } from 'react-material-symbols';
import { Button, Pagination, Space, Spin, Table, Tag, Modal, message } from 'antd'; import { Button, Pagination, Spin, Table } from 'antd';
import type { TableProps } from 'antd';
import './Homepage.css'; import './Homepage.css';
import { useGetOrganizationsQuery, useDeleteOrganizationMutation } from '../../features/api/apiSlice'; import { useGetOrganizationsQuery, } from '../../features/api/apiSlice';
import { DataType, columns } from './Columns';
interface DataType {
id: number | string;
bin: string;
organization_code: string;
organization_name: string;
status: string;
host: string;
}
const columns: TableProps<DataType>['columns'] = [
{
title: "ID",
dataIndex: "id",
key: "id"
},
{
title: "БИН",
dataIndex: "bin",
key: "bin"
},
{
title: "Код организации",
dataIndex: "organization_code",
key: "code"
},
{
title: "Наименование организации",
dataIndex: "organization_name",
key: "name"
},
{
title: "Адрес системы/хост",
dataIndex: "host",
key: "host"
},
{
title: "Статус",
dataIndex: "status",
key: "status",
render: (_, record) => {
const color = record.status == '0' ? 'red' : record.status == '1' ? 'processing' : 'green';
return (
<p>
<Tag color={color} style={{ fontSize: '14px' }}>
{record.status == '0' ? 'удален' : record.status == '1' ? 'заблокирован' : 'активен'}
</Tag>
</p>
)
}
},
{
title: "Действия",
width: 60,
render: (_, record) => {
return (
<ActionColumn data={record} />
)
}
}
]
const ActionColumn: React.FC<{ data: any }> = ({ data }) => {
const [open, setOpen] = useState<boolean>(false);
const navigate = useNavigate();
const [deleteOrganization] = useDeleteOrganizationMutation();
const showDeleteModal = () => {
setOpen(true);
};
const handleDeleteModalOk = async () => {
try {
await deleteOrganization(data.id).unwrap();
message.success('Организация успешно удалена!');
setOpen(false);
} catch (err) {
message.error('Произошла ошибка при удалении организации!');
}
};
const handleDeleteModalCancel = () => {
setOpen(false);
};
const handleEditClick = () => {
navigate(`/edit/${(data.id).toString()}`);
}
return (
<Space>
<Button onClick={() => handleEditClick()} icon={<MaterialSymbol icon='visibility' size={22} />} />
<Button onClick={showDeleteModal} icon={<MaterialSymbol icon='delete' size={22} />} />
<Modal
open={open}
title={`Вы уверены в том, что хотите удалить ${data.organization_name}?`}
footer={() => {
return <div style={{ textAlign: 'start', marginTop: '1rem' }}>
<Button key="submit" type="primary" danger onClick={handleDeleteModalOk} style={{ marginRight: '.5rem' }}>
Удалить
</Button>
<Button key="back" onClick={handleDeleteModalCancel}>
Назад
</Button>
</div>;
}}
/>
</Space>
)
}
const HomePage: React.FC = () => { const HomePage: React.FC = () => {
const [totalOrgNumber, setTotalOrgNumber] = useState<number>(0); const [totalOrgNumber, setTotalOrgNumber] = useState<number>(0);
...@@ -126,7 +16,7 @@ const HomePage: React.FC = () => { ...@@ -126,7 +16,7 @@ const HomePage: React.FC = () => {
navigate("/add"); navigate("/add");
}; };
const handlePaginationChange = (page: React.SetStateAction<number>) => { const handlePaginationChange = (page: number) => {
setCurrentPage(page); setCurrentPage(page);
}; };
......
.filter { .filter {
margin: 1rem 1rem .5rem; margin: 1rem 1rem .5rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
...@@ -17,10 +16,8 @@ ...@@ -17,10 +16,8 @@
left: 0; left: 0;
width: 100%; width: 100%;
padding: .5rem 1rem; padding: .5rem 1rem;
display: flex; display: flex;
justify-content: center; justify-content: center;
background: white; background: white;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
} }
\ No newline at end of file
import { configureStore, Store } from '@reduxjs/toolkit'; import { configureStore, Store } from '@reduxjs/toolkit';
import { apiSlice } from './features/api/apiSlice'; import { apiSlice } from '../features/api/apiSlice';
const store: Store = configureStore({ const store: Store = configureStore({
reducer: { reducer: {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment