From aaa26161da06837e7853c8dfaf0d594e0f8cbbb3 Mon Sep 17 00:00:00 2001 From: KharchenkoVladimir Date: Thu, 21 Oct 2021 17:27:53 +0500 Subject: [PATCH 1/3] CF2-85: Added base registration page --- src/App.js | 4 + src/pages/Login.jsx | 23 +- src/pages/Register.jsx | 297 ++++++++++++++++++++++++ src/services/api/models/UserDto.ts | 3 + src/services/api/models/UserTokenDto.ts | 3 + src/styles/index.css | 14 ++ 6 files changed, 337 insertions(+), 7 deletions(-) create mode 100644 src/pages/Register.jsx diff --git a/src/App.js b/src/App.js index 49ee5eb..9b81ac1 100644 --- a/src/App.js +++ b/src/App.js @@ -6,6 +6,7 @@ import { import {ConfigProvider} from 'antd' import locale from "antd/lib/locale/ru_RU" import Login from './pages/Login' +import Register from './pages/Register' import Main from './pages/Main' import { OpenAPI } from './services/api' import { PrivateRoute } from './components/Private' @@ -21,6 +22,9 @@ export default function App() { + + +
diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx index cd144f6..8ac6878 100644 --- a/src/pages/Login.jsx +++ b/src/pages/Login.jsx @@ -3,8 +3,9 @@ import { UserOutlined, LockOutlined } from '@ant-design/icons' import logo from '../images/logo_32.png' import Loader from '../components/Loader' import { useState } from 'react' -import { useHistory } from "react-router-dom"; +import {Link, useHistory} from "react-router-dom"; import { AuthService, OpenAPI } from '../services/api/' +import '../styles/index.css' const { login } = AuthService @@ -61,8 +62,9 @@ export default function Login() {
({ validator() { return showError(isErrorVisible, new Error('Неправильные логин или пароль!')) @@ -83,7 +85,7 @@ export default function Login() { ({ validator() { return showError(isErrorVisible) @@ -102,10 +104,17 @@ export default function Login() { - - +
+ +
+
+ +
+ Отправить заявку на регистрацию +
+
{loader && } diff --git a/src/pages/Register.jsx b/src/pages/Register.jsx new file mode 100644 index 0000000..0cf87a4 --- /dev/null +++ b/src/pages/Register.jsx @@ -0,0 +1,297 @@ +import { Card, Form, Input, Select, Button, notification } from 'antd'; +import { UserOutlined, LockOutlined } from '@ant-design/icons' +import logo from '../images/logo_32.png' +import Loader from '../components/Loader' +import { useState } from 'react' +import { Link, useHistory } from "react-router-dom"; +import { AuthService } from '../services/api/' + +const openNotificationError = (message, title) => { + notification['error']({ + message: title||'Ошибка', + description: message, + }); +}; + +const { Option } = Select; + +const companies = [ + { name: "ООО «Газпромнефть-Хантос» ", value: 1 }, + { name: "АО «НафтаГаз»", value: 2 }, + { name: "ООО «Нафтагаз Бурение»", value: 3 }, + { name: "ООО «Газпромнефть-ННГ»", value: 4 } +]; + +export default function Register() { + const [loader, setLoader] = useState(false); + const [isErrorVisible, setErrorVisible] = useState(false); + const [selectedCompanyId, setSelectedCompanyId] = useState(companies[0].value); + const history = useHistory(); + const [form] = Form.useForm(); + + const logoIcon = АСБ + + const children = companies.map((line) => ( + + )); + + let handleRegister = async (formData) =>{ + formData.idCompany = +selectedCompanyId + + setLoader(true) + try{ + await AuthService.register(formData) + setLoader(false) + openNotificationError("Заявка на регистрацию отправлена. ") + history.push("/login"); + }catch(e){ + if(e.status === 400) + openNotificationError(e.message) + console.error(`Error ${e}`) + + setErrorVisible(true) + form.validateFields() + setLoader(false) + } + } + + const showError = (isErrorVisible, errorObj) => { + if (isErrorVisible) + return Promise.reject(errorObj) + + return Promise.resolve() + } + + return ( +
+ +
+ ({ + validator() { + return showError(isErrorVisible, new Error('Неправильные логин или пароль!')) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + + + + ({ + validator() { + return showError(isErrorVisible) + } + }) + ]} + > + } + onChange={() => { + setErrorVisible(false) + form.validateFields() + }} + /> + + + +
+ +
+
+ +
+ Назад +
+ +
+
+ {loader && } +
+ ) +} \ No newline at end of file diff --git a/src/services/api/models/UserDto.ts b/src/services/api/models/UserDto.ts index c8761f9..748389f 100644 --- a/src/services/api/models/UserDto.ts +++ b/src/services/api/models/UserDto.ts @@ -10,6 +10,9 @@ export type UserDto = { name?: string | null; surname?: string | null; patronymic?: string | null; + email?: string | null; + phone?: string | null; + position?: string | null; id?: number; idCompany?: number | null; idRole?: number | null; diff --git a/src/services/api/models/UserTokenDto.ts b/src/services/api/models/UserTokenDto.ts index 6e3321d..c7a5f92 100644 --- a/src/services/api/models/UserTokenDto.ts +++ b/src/services/api/models/UserTokenDto.ts @@ -8,6 +8,9 @@ export type UserTokenDto = { name?: string | null; surname?: string | null; patronymic?: string | null; + email?: string | null; + phone?: string | null; + position?: string | null; id?: number; companyName?: string | null; roleName?: string | null; diff --git a/src/styles/index.css b/src/styles/index.css index 59c2d76..39aef5a 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -75,6 +75,10 @@ body { vertical-align: center; } +.text-align-center { + text-align: center; +} + .text-align-r-container { width: 100%; text-align: right; @@ -97,3 +101,13 @@ code { width: 100%; } +.login-button { + width: 20%; + margin: auto; +} + +.register-button { + width: 50%; + margin: auto; +} + From 2f6e2fbc4e6a50c161b968d8f32fbd599afa0574 Mon Sep 17 00:00:00 2001 From: KharchenkoVladimir Date: Fri, 22 Oct 2021 17:40:03 +0500 Subject: [PATCH 2/3] CF2-85: Added register form validation --- src/pages/Register.jsx | 327 ++++++++++++++--------------------------- 1 file changed, 114 insertions(+), 213 deletions(-) diff --git a/src/pages/Register.jsx b/src/pages/Register.jsx index 0cf87a4..e718099 100644 --- a/src/pages/Register.jsx +++ b/src/pages/Register.jsx @@ -1,13 +1,16 @@ import { Card, Form, Input, Select, Button, notification } from 'antd'; -import { UserOutlined, LockOutlined } from '@ant-design/icons' +import { UserOutlined, + LockOutlined, + EyeInvisibleOutlined, + EyeTwoTone } from '@ant-design/icons' import logo from '../images/logo_32.png' import Loader from '../components/Loader' import { useState } from 'react' import { Link, useHistory } from "react-router-dom"; import { AuthService } from '../services/api/' -const openNotificationError = (message, title) => { - notification['error']({ +const openNotification = (message, type, title) => { + notification[type]({ message: title||'Ошибка', description: message, }); @@ -22,9 +25,30 @@ const companies = [ { name: "ООО «Газпромнефть-ННГ»", value: 4 } ]; +const showError = (isErrorVisible, errorObj) => { + if (isErrorVisible) + return Promise.reject(errorObj) + + return Promise.resolve() +} + +const getValidationRules = (isRequired, message, isErrorVisible, errorObj) => { + return [ + { required: isRequired, message: message }, + () => ({ + validator() { + return showError(isErrorVisible, errorObj) + } + }) + ] +} + + export default function Register() { const [loader, setLoader] = useState(false); - const [isErrorVisible, setErrorVisible] = useState(false); + const [isLengthErrorVisible, setIsLengthErrorVisible] = useState(false); + const [isPasswordLengthErrorVisible, setIsPasswordLengthErrorVisible] = useState(false); + const [isPasswordMismatchErrorVisible, setIsPasswordMismatchErrorVisible] = useState(false); const [selectedCompanyId, setSelectedCompanyId] = useState(companies[0].value); const history = useHistory(); const [form] = Form.useForm(); @@ -35,251 +59,128 @@ export default function Register() { )); + const checkFormErrors = (formData) => { + if(formData.login.length < 4 || formData.login.length > 50){ + setIsLengthErrorVisible(true) + form.validateFields() + return true + } + + if(formData.password.length < 4 || formData.password.length > 50) { + setIsPasswordLengthErrorVisible(true) + form.validateFields() + return true + } + + if(formData.password !== formData.confirmPassword) { + setIsPasswordMismatchErrorVisible(true) + form.validateFields() + return true + } + + return false + } + let handleRegister = async (formData) =>{ + + if(checkFormErrors(formData)) + return + formData.idCompany = +selectedCompanyId setLoader(true) try{ await AuthService.register(formData) setLoader(false) - openNotificationError("Заявка на регистрацию отправлена. ") + openNotification("Заявка на регистрацию отправлена.", 'success') history.push("/login"); }catch(e){ - if(e.status === 400) - openNotificationError(e.message) + openNotification(e.message, 'error') console.error(`Error ${e}`) - - setErrorVisible(true) - form.validateFields() setLoader(false) } } - const showError = (isErrorVisible, errorObj) => { - if (isErrorVisible) - return Promise.reject(errorObj) + const createInput = (name, placeholder, isRequired, requiredValidationMessage, lengthValidationMessage) => { - return Promise.resolve() + const rules = getValidationRules(true, requiredValidationMessage, + isLengthErrorVisible, new Error(lengthValidationMessage)) + + return ( + + } + onChange={() => { + setIsLengthErrorVisible(false) + form.validateFields() + }} + /> + + ) + } + + const createPasswordInput = (name, message, errorObj, isErrorVisible, setIsErrorVisible) => { + return ( + + (visible ? : )} + prefix={} + onChange={() => { + setIsErrorVisible(false) + form.validateFields() + }} + /> + + ) } return (
- ({ - validator() { - return showError(isErrorVisible, new Error('Неправильные логин или пароль!')) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - - + {createInput('login', 'Пользователь', true, + 'Пожалуйста, введите имя!', + 'Допустимая длина логина от 3 до 50 символов!')} + {createPasswordInput('password', 'Пожалуйста, введите пароль!', + new Error('Допускаются пароли от 3х до 50ти символов'), + isPasswordLengthErrorVisible, setIsPasswordLengthErrorVisible)} + {createPasswordInput('confirmPassword', 'Пожалуйста, введите пароль повторно!', + new Error('Пароли не совпадают!'), isPasswordMismatchErrorVisible, + setIsPasswordMismatchErrorVisible)} + {createInput('name', 'Имя', false)} + {createInput('surName', 'Фамилия', false)} + {createInput('patronymic', 'Отчество',false)} + {createInput('email', 'Отчество',false)} + {createInput('phone', 'Номер телефона',false)} ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} > - - ({ - validator() { - return showError(isErrorVisible) - } - }) - ]} - > - } - onChange={() => { - setErrorVisible(false) - form.validateFields() - }} - /> - + {createInput('position', 'Должность',false)}
-
From 30efdaed176bec8e69fbdabe00036399ffacdec3 Mon Sep 17 00:00:00 2001 From: KharchenkoVladimir Date: Mon, 25 Oct 2021 12:03:24 +0500 Subject: [PATCH 3/3] CF2-85: Added error body text in register error notifications --- src/pages/Login.jsx | 2 +- src/pages/Register.jsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx index 8ac6878..055497b 100644 --- a/src/pages/Login.jsx +++ b/src/pages/Login.jsx @@ -40,7 +40,7 @@ export default function Login() { history.push('well') }catch(e){ if(e.status === 400) - openNotificationError(e.message) + openNotificationError(e.body) console.error(`Error ${e}`) setErrorVisible(true) diff --git a/src/pages/Register.jsx b/src/pages/Register.jsx index e718099..a84d68b 100644 --- a/src/pages/Register.jsx +++ b/src/pages/Register.jsx @@ -95,7 +95,7 @@ export default function Register() { openNotification("Заявка на регистрацию отправлена.", 'success') history.push("/login"); }catch(e){ - openNotification(e.message, 'error') + openNotification(e.body, 'error') console.error(`Error ${e}`) setLoader(false) } @@ -158,7 +158,7 @@ export default function Register() { {createInput('name', 'Имя', false)} {createInput('surName', 'Фамилия', false)} {createInput('patronymic', 'Отчество',false)} - {createInput('email', 'Отчество',false)} + {createInput('email', 'Email',false)} {createInput('phone', 'Номер телефона',false)}