diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/AdditionalInfo.js b/FrontEnd/src/components/ProfilePage/FormComponents/AdditionalInfo.js index f8a774c19..487847b40 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/AdditionalInfo.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/AdditionalInfo.js @@ -60,7 +60,9 @@ const AdditionalInfo = (props) => { const handleSubmit = async (event) => { event.preventDefault(); - if (validateForm()) { + if (!validateForm()) { + toast.error('Зміни не можуть бути збережені, перевірте правильність заповнення полів'); + } else { try { const response = await axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/profiles/${user.profile_id}`, { founded: profile.founded, diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/ContactsInfo.js b/FrontEnd/src/components/ProfilePage/FormComponents/ContactsInfo.js index 7deb1e814..688f4a9a4 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/ContactsInfo.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/ContactsInfo.js @@ -73,7 +73,9 @@ const ContactsInfo = (props) => { const handleSubmit = async (event) => { event.preventDefault(); - if (validateForm()) { + if (!validateForm()) { + toast.error('Зміни не можуть бути збережені, перевірте правильність заповнення полів'); + } else { try { const response = await axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/profiles/${user.profile_id}`, { phone: profile.phone, diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.js b/FrontEnd/src/components/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.js index e1070d5a2..799242a1a 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/DeleteProfileComponent/DeleteProfileModal.js @@ -3,6 +3,7 @@ import css from './DeleteProfileModal.module.css'; import { useAuth } from '../../../../hooks'; import { useNavigate } from 'react-router-dom'; import { useState } from 'react'; +import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; const DeleteProfileModal = (props) => { @@ -75,6 +76,7 @@ const DeleteProfileModal = (props) => { name="email" placeholder="Електронна пошта" onChange={emailChangeHandler} + onKeyDown={preventEnterSubmit} /> {(!isCorrectEmail) && @@ -91,6 +93,7 @@ const DeleteProfileModal = (props) => { name="password" placeholder="Пароль" onChange={passwordChangeHandler} + onKeyDown={preventEnterSubmit} /> { + return (
@@ -19,6 +21,7 @@ const CheckBoxField = (props) => { Зареєстрована компанія @@ -29,6 +32,7 @@ const CheckBoxField = (props) => { Стартап проект, який шукає інвестиції diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.js b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.js index 3c05782ac..1c5ee59af 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.js @@ -1,6 +1,8 @@ +import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; import css from './FullField.module.css'; const FullField = (props) => { + return (
@@ -19,8 +21,11 @@ const FullField = (props) => { value={props.value} placeholder={props.fieldPlaceholder ? props.fieldPlaceholder: 'Введіть текст'} onChange={props.updateHandler} + onBlur={props.onBlur} + onKeyDown={preventEnterSubmit} required={(props.requredField) ? 'required' : ''} disabled={(props.name === 'email') ? 'disabled' : ''} + maxLength={props.maxLength} />
{(props.requredField || props.error) && diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.module.css b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.module.css index 50c812986..c62043ba4 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.module.css +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/FullField.module.css @@ -90,8 +90,8 @@ flex: 1 0 0; color: var(--red-red-100, #F34444); font-family: var(--font-error); - font-size: 14px; + font-size: 12px; font-style: normal; font-weight: 400; - line-height: 22px; + line-height: 16px; } \ No newline at end of file diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.js b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.js index 522db4675..5e5b0ca39 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.js @@ -1,7 +1,9 @@ import { PropTypes } from 'prop-types'; +import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; import css from './HalfFormField.module.css'; const HalfFormField = (props) => { + return (
@@ -19,17 +21,25 @@ const HalfFormField = (props) => { name={props.name} value={props.value} placeholder={props.fieldPlaceholder ? props.fieldPlaceholder : 'Введіть текст'} + onBlur={props.onBlur} + onKeyDown={preventEnterSubmit} onChange={props.updateHandler} required={(props.requredField) ? 'required' : ''} disabled={(props.name === 'email') ? 'disabled' : ''} maxLength={props.maxLength} />
- {(props.requredField || props.error) && + {(props.requiredField || props.error) && (
- {props.error} + {Array.isArray(props.error) ? ( + props.error.map((error, index) => + {error} + ) + ) : ( + {props.error} + )}
- } + )}
); }; @@ -48,5 +58,8 @@ HalfFormField.propTypes = { fieldPlaceholder: PropTypes.string, maxLength: PropTypes.number, updateHandler: PropTypes.func, - error:PropTypes.string, + error:PropTypes.oneOfType([ + PropTypes.string, + PropTypes.arrayOf(PropTypes.string), + ]), }; \ No newline at end of file diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.module.css b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.module.css index a2cf53e1e..fa232a782 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.module.css +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/HalfFormField.module.css @@ -2,7 +2,7 @@ display: flex; width: 257px; height: 84px; - padding-bottom: 5px; + padding-bottom: 10px; flex-direction: column; align-items: flex-start; } @@ -83,17 +83,17 @@ .error-message { display: flex; + flex-direction: column; padding: 1px 0px; align-items: flex-start; - gap: 10px; align-self: stretch; flex: 1 0 0; color: var(--red-red-100, #F34444); font-family: var(--font-error); - font-size: 14px; + font-size: 12px; font-style: normal; font-weight: 400; - line-height: 22px; + line-height: 16px; } .disabled__field { diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/ImageField.js b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/ImageField.js index 46d307855..20df95a10 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/ImageField.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/ImageField.js @@ -1,10 +1,13 @@ import classNames from 'classnames'; +import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; import css from './ImageField.module.css'; const ImageField = (props) => { + const backgroundImage = { background: `url(${props.value}) lightgray 50% / cover no-repeat`, }; + return (
@@ -14,7 +17,7 @@ const ImageField = (props) => { {props.label} {props.name === 'banner_image' && props.value && - ()} @@ -27,6 +30,7 @@ const ImageField = (props) => { className={css['upload-file__input']} name={props.name} onChange={props.updateHandler} + onKeyDown={preventEnterSubmit} required={(props.requredField) ? 'required' : ''} /> {!props.value && @@ -53,7 +57,7 @@ const ImageField = (props) => { {props.name === 'logo_image' && props.value && (
- diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/MultipleSelectChip.js b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/MultipleSelectChip.js index 83d028901..fac7c2928 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/MultipleSelectChip.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/MultipleSelectChip.js @@ -1,9 +1,11 @@ import { Select, Space } from 'antd'; import { PropTypes } from 'prop-types'; +import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; import css from './MultipleSelectChip.module.css'; export default function MultipleSelectChip(props) { + return (
@@ -29,6 +31,7 @@ export default function MultipleSelectChip(props) { borderRadius: '2px', }} onChange={props.updateHandler} + onKeyDown={preventEnterSubmit} options={props.options.map(option => ({ value: option.name ?? option.name_ukr, }))} @@ -44,7 +47,7 @@ export default function MultipleSelectChip(props) { } MultipleSelectChip.propTypes = { - requredField: PropTypes.bool.isRequired, + requredField: PropTypes.bool, name: PropTypes.string.isRequired, label: PropTypes.string.isRequired, value: PropTypes.array, diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/PasswordField.js b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/PasswordField.js index e772d4f07..d067df99d 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/PasswordField.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/FormFields/PasswordField.js @@ -2,6 +2,7 @@ import { useState } from 'react'; import { PropTypes } from 'prop-types'; import EyeInvisible from '../../../authorization/EyeInvisible'; import EyeVisible from '../../../authorization/EyeVisible'; +import preventEnterSubmit from '../../../../utils/preventEnterSubmit'; import css from './PasswordField.module.css'; import { PASSWORD_PATTERN } from '../../../../constants/constants'; @@ -45,6 +46,7 @@ const PasswordField = (props) => {
{ + return (
@@ -18,6 +20,7 @@ const TextField = (props) => { value={props.value} placeholder={props.fieldPlaceholder ? props.fieldPlaceholder : 'Введіть текст'} onChange={props.updateHandler} + onKeyDown={preventEnterSubmit} required={(props.requredField) ? 'required' : ''} disabled={(props.name === 'email') ? 'disabled' : ''} > diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/GeneralInfo.js b/FrontEnd/src/components/ProfilePage/FormComponents/GeneralInfo.js index b3c13f163..bcc4d0f08 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/GeneralInfo.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/GeneralInfo.js @@ -116,6 +116,12 @@ const GeneralInfo = (props) => { } } setFormStateErr({ ...formStateErr, ...newFormState }); + if (profile.official_name.length !== 0 && profile.official_name.length < 2) { + isValid = false; + } + if (profile.name.length < 2) { + isValid = false; + } if (profile.edrpou) { try { validateEdrpou(profile.edrpou); @@ -140,8 +146,25 @@ const GeneralInfo = (props) => { }; const onUpdateField = e => { + const { value: fieldValue, name: fieldName } = e.target; + const symbolCount = (fieldValue.replace(/[\s]/g,'')).length; + setFormStateErr({ ...formStateErr, [fieldName]: {'error': false, 'message': ''}}); + if (fieldName === 'name' && symbolCount < 2) { + setFormStateErr({ ...formStateErr, [fieldName]: {'error': true, 'message': 'Введіть від 2 до 100 символів'}}); + } + if (fieldName === 'official_name' && symbolCount !== 0 && symbolCount < 2) { + setFormStateErr({ ...formStateErr, [fieldName]: {'error': true, 'message': 'Введіть від 2 до 200 символів'}}); + } setProfile((prevState) => { - return { ...prevState, [e.target.name]: e.target.value }; + return { ...prevState, [fieldName]: fieldValue }; + }); + }; + + const onBlurHandler = (e) => { + const { value: rawFieldValue, name: fieldName } = e.target; + const fieldValue = rawFieldValue.replace(/\s{2,}/g,' ').trim(); + setProfile((prevState) => { + return { ...prevState, [fieldName]: fieldValue }; }); }; @@ -315,7 +338,9 @@ const GeneralInfo = (props) => { const handleSubmit = async (event) => { event.preventDefault(); - if (checkRequiredFields()) { + if (!checkRequiredFields()) { + toast.error('Зміни не можуть бути збережені, перевірте правильність заповнення полів'); + } else { try { const response = await axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/profiles/${user.profile_id}`, { name: profile.name, @@ -353,16 +378,21 @@ const GeneralInfo = (props) => { name="name" label={LABELS.name} updateHandler={onUpdateField} - error={formStateErr['name']['error'] ? formStateErr['name']['message'] : null} + onBlur={onBlurHandler} + error={formStateErr['name']?.['error'] ? formStateErr['name']['message'] : null} requredField={true} value={profile.name} + maxLength={100} />
{mainProfile?.is_fop ? diff --git a/FrontEnd/src/components/ProfilePage/FormComponents/UserInfo.js b/FrontEnd/src/components/ProfilePage/FormComponents/UserInfo.js index f7d902515..2eeaf420a 100644 --- a/FrontEnd/src/components/ProfilePage/FormComponents/UserInfo.js +++ b/FrontEnd/src/components/ProfilePage/FormComponents/UserInfo.js @@ -35,8 +35,6 @@ const UserInfo = (props) => { const [formStateErr, setFormStateErr] = useState(ERRORS); const { setFormIsDirty } = useContext(DirtyFormContext); - // TODO: update default values as new fields added - const fields = { 'surname': {defaultValue: user?.surname ?? '', context: 'user'}, 'name': {defaultValue: user?.name ?? '', context: 'user'}, @@ -52,6 +50,37 @@ const UserInfo = (props) => { props.currentFormNameHandler(props.curForm); }, []); + const errorMessageTemplates = { + fieldLength: 'Введіть від 2 до 50 символів', + notAllowedSymbols: 'Поле містить недопустимі символи та/або цифри', + }; + + const validateFields = (fieldName, fieldValue) => { + const allowedSymbolsPatterns = { + 'person_position': /^[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ\-'\s]+$/, + 'name': /^[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ'\s]+$/, + 'surname': /^[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ'\s]+$/, + }; + const letterCount = (fieldValue.match(/[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ]/g) || []).length; + const isValidLength = letterCount >= 2 || (fieldName === 'person_position' && letterCount === 0); + const isValidPattern = allowedSymbolsPatterns[fieldName].test(fieldValue); + let errorMessage = []; + + if (fieldValue && !isValidPattern) { + errorMessage.push(errorMessageTemplates.notAllowedSymbols); + } + if (!isValidLength) { + errorMessage.push(errorMessageTemplates.fieldLength); + } + + setFormStateErr(prevState => ({ + ...prevState, + [fieldName]: { 'error': !isValidLength || !isValidPattern, 'message': errorMessage } + })); + }; + + const errorsInNameSurname = formStateErr['name']['message'].length > 1 || formStateErr['surname']['message'].length > 1; + const checkRequiredFields = () => { let isValid = true; const newFormState = {}; @@ -70,31 +99,49 @@ const UserInfo = (props) => { } } setFormStateErr({ ...formStateErr, ...newFormState }); + + if (updateUser.name.length < 2 || updateUser.surname.length < 2) { + isValid = false; + } + if (updateProfile.person_position.length !== 0 && updateProfile.person_position.length < 2) { + isValid = false; + } + return isValid; }; const onUpdateField = e => { - if (e.target.name === 'person_position') { - setUpdateProfile((prevState) => { - return { ...prevState, [e.target.name]: e.target.value }; - }); + const { value: fieldValue, name: fieldName } = e.target; + validateFields(fieldName, fieldValue); + if (fieldName === 'person_position') { + setUpdateProfile(prevState => ({ ...prevState, [fieldName]: fieldValue })); } else { - setUpdateUser((prevState) => { - return { ...prevState, [e.target.name]: e.target.value }; - }); + setUpdateUser(prevState => ({ ...prevState, [fieldName]: fieldValue })); + } + }; + + const onBlurHandler = (e) => { + const { value: rawFieldValue, name: fieldName } = e.target; + const fieldValue = rawFieldValue.replace(/\s{2,}/g,' ').trim(); + if (fieldName === 'person_position') { + setUpdateProfile(prevState => ({ ...prevState, [fieldName]: fieldValue })); + } else { + setUpdateUser(prevState => ({ ...prevState, [fieldName]: fieldValue })); } }; const handleSubmit = async (event) => { event.preventDefault(); - if (checkRequiredFields()) { + if (!checkRequiredFields()) { + toast.error('Зміни не можуть бути збережені, перевірте правильність заповнення полів'); + } else { axios.all([ axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/`, { surname: updateUser.surname, name: updateUser.name }), axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/profiles/${user.profile_id}`, { - person_position: updateProfile.person_position , + person_position: updateProfile.person_position, }) ]) .then(axios.spread((updatedUserData , updatedProfileData ) => { @@ -117,25 +164,29 @@ const UserInfo = (props) => { {(updateUser && user && profile && updateProfile) ?
-
+
@@ -144,6 +195,8 @@ const UserInfo = (props) => { name="person_position" label={LABELS.person_position} updateHandler={onUpdateField} + onBlur={onBlurHandler} + error={formStateErr['person_position']?.['error'] ? formStateErr['person_position']['message'] : null} requredField={false} value={updateProfile.person_position ?? ''} /> diff --git a/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.js b/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.js index cbdc16aeb..35353b6d1 100644 --- a/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.js +++ b/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.js @@ -1,6 +1,7 @@ import React, { useEffect, useState , Suspense} from 'react'; import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; +import { toast } from 'react-toastify'; import axios from 'axios'; import { Tooltip } from 'antd'; import EyeInvisible from '../../../../authorization/EyeInvisible'; @@ -25,9 +26,13 @@ export function SignUpFormContentComponent(props) { const errorMessageTemplates = { required: 'Обов’язкове поле', - email: 'Email не відповідає вимогам', + requiredRepresentative: 'Будь ласка, оберіть кого ви представляєте', + email: 'Електронна пошта не відповідає вимогам', password: 'Пароль не відповідає вимогам', confirmPassword: 'Паролі не збігаються', + nameSurnameFieldLength: 'Введіть від 2 до 50 символів', + companyFieldLength: 'Введіть від 2 до 100 символів', + notAllowedSymbols: 'Поле містить недопустимі символи та/або цифри', }; const { @@ -68,12 +73,32 @@ export function SignUpFormContentComponent(props) { const otherOption = name === 'yurosoba' ? 'fop' : 'yurosoba'; setValue(otherOption, false); if (!getValues('yurosoba') && !getValues('fop')) { - setError('businessEntity', { type: 'manual', message: errorMessageTemplates.required }); + setError('businessEntity', { type: 'manual', message: errorMessageTemplates.requiredRepresentative }); } else { clearErrors('businessEntity'); } }; + const validateNameSurname = (value) => { + const allowedSymbolsPattern = /^[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ'\s]+$/; + const letterCount = (value.match(/[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ]/g) || []).length; + if (!allowedSymbolsPattern.test(value)) { + return errorMessageTemplates.notAllowedSymbols; + } + if (letterCount < 2) { + return errorMessageTemplates.nameSurnameFieldLength; + } + return true; + }; + + const onBlurHandler = (fieldName) => { + let fieldValue = getValues(fieldName); + if (fieldValue !== undefined && fieldValue !== null) { + fieldValue = fieldValue.replace(/\s{2,}/g,' ').trim(); + setValue(fieldName, fieldValue); + } +}; + useEffect(() => { setIsValid(isValid); }, [isValid, setIsValid]); @@ -109,6 +134,9 @@ export function SignUpFormContentComponent(props) { message: 'Вже зареєстрована пошта', }); } + if (error.response && error.response.status === 400) { + toast.error('Не вдалося зареєструвати користувача, сталася помилка'); + } }); }; @@ -146,7 +174,10 @@ export function SignUpFormContentComponent(props) { pattern: { value: COMPANY_NAME_PATTERN, }, + minLength: {value: 2, message: errorMessageTemplates.companyFieldLength} })} + maxLength={100} + onBlur={() => onBlurHandler('companyName')} />
@@ -210,6 +241,7 @@ export function SignUpFormContentComponent(props) { message: errorMessageTemplates.password, }, })} + maxLength={50} /> onBlurHandler('surname')} />
@@ -311,10 +345,11 @@ export function SignUpFormContentComponent(props) { placeholder="Ім‘я" {...register('name', { required: errorMessageTemplates.required, - pattern: { - value: NAME_SURNAME_PATTERN, + validate: validateNameSurname, }, - })} + )} + maxLength={50} + onBlur={() => onBlurHandler('name')} />
@@ -343,7 +378,7 @@ export function SignUpFormContentComponent(props) { name="company" value={'company'} {...register('representative', { - required: errorMessageTemplates.required + required: errorMessageTemplates.requiredRepresentative })} />
@@ -362,7 +397,7 @@ export function SignUpFormContentComponent(props) { name="startup" value={'startup'} {...register('representative', { - required: errorMessageTemplates.required + required: errorMessageTemplates.requiredRepresentative })} />
diff --git a/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.module.css b/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.module.css index 1143e78a4..32f5ece7d 100644 --- a/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.module.css +++ b/FrontEnd/src/components/SignUp/components/signup/signup-form/SignUpFormContent.module.css @@ -174,10 +174,10 @@ align-self: stretch; color: var(--red-red-100, #f34444); font-family: var(--font-messages); - font-size: 14px; + font-size: 12px; font-style: normal; font-weight: 400; - line-height: 22px; + line-height: 16px; } .signup-form__checkboxes-container { @@ -262,7 +262,6 @@ display: flex; flex-direction: row; align-items: flex-start; - flex: 1 0 0; } .representative__content { diff --git a/FrontEnd/src/constants/constants.js b/FrontEnd/src/constants/constants.js index f2ca3aad4..06257b9c5 100644 --- a/FrontEnd/src/constants/constants.js +++ b/FrontEnd/src/constants/constants.js @@ -1,4 +1,4 @@ export const EMAIL_PATTERN = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; export const PASSWORD_PATTERN = /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,20}$/; -export const NAME_SURNAME_PATTERN = /^.{2,50}$/; +export const NAME_SURNAME_PATTERN = /^(?=.{2,50}$)[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ']+(\s[a-zA-Zа-щюяьА-ЩЮЯЬїЇіІєЄґҐ']+)*$/; export const COMPANY_NAME_PATTERN = /^.{2,100}$/; diff --git a/FrontEnd/src/utils/preventEnterSubmit.js b/FrontEnd/src/utils/preventEnterSubmit.js new file mode 100644 index 000000000..768652001 --- /dev/null +++ b/FrontEnd/src/utils/preventEnterSubmit.js @@ -0,0 +1,7 @@ +const preventEnterSubmit = (event) => { + if (event.key === 'Enter') { + event.preventDefault(); + } +}; + +export default preventEnterSubmit; \ No newline at end of file