diff --git a/FrontEnd/src/components/BreadCrumbs/BreadCrumbs.jsx b/FrontEnd/src/components/BreadCrumbs/BreadCrumbs.jsx
index 25437e2cf..a18553893 100644
--- a/FrontEnd/src/components/BreadCrumbs/BreadCrumbs.jsx
+++ b/FrontEnd/src/components/BreadCrumbs/BreadCrumbs.jsx
@@ -1,25 +1,37 @@
-import css from './BreadCrumbs.module.css';
import { Link, useNavigate } from 'react-router-dom';
import { PropTypes } from 'prop-types';
+import { useAuth } from '../../hooks';
+
+import css from './BreadCrumbs.module.css';
+
const BreadCrumbs = ({ currentPage }) => {
const navigate = useNavigate();
-
+ const { isStaff } = useAuth();
const goBackHandler = () => {
navigate(-1);
};
return (
{
+ return (
+
+
+ Зберегти зміни
+
+
+ );
+};
+
+export default AdminSubmitButton;
\ No newline at end of file
diff --git a/FrontEnd/src/components/MiniComponents/AdminSubmitButton.module.css b/FrontEnd/src/components/MiniComponents/AdminSubmitButton.module.css
new file mode 100644
index 000000000..c25fea2fe
--- /dev/null
+++ b/FrontEnd/src/components/MiniComponents/AdminSubmitButton.module.css
@@ -0,0 +1,27 @@
+.admin-submit__container {
+ margin-top: 16px;
+}
+
+.admin-submit__button {
+ display: block;
+ width: 100%;
+ border-radius: 4px;
+ border: 1px solid var(--main-button-color);
+ background: var(--main-button-color);
+ box-shadow: 0px 2px 0px 0px rgba(0, 0, 0, 0.04);
+ color: var(--light-button-text-color);
+ font-feature-settings: 'calt' off;
+ font-style: normal;
+ padding: 5px 15px 5px 15px;
+ font-family: var(--font-main);
+ font-size: 16px;
+ font-weight: 600;
+ line-height: 20px;
+ letter-spacing: -0.01em;
+ text-align: center;
+ cursor: pointer;
+}
+
+.admin-submit__button:active {
+ transform: translateY(2px);
+}
diff --git a/FrontEnd/src/pages/AdminPage/AdminGlobal.css b/FrontEnd/src/pages/AdminPage/AdminGlobal.css
index e717c8da6..ec7e45384 100644
--- a/FrontEnd/src/pages/AdminPage/AdminGlobal.css
+++ b/FrontEnd/src/pages/AdminPage/AdminGlobal.css
@@ -1,10 +1,13 @@
:root {
--font__admin-panel: "Inter", sans-serif;
- --block-size__admin-panel: 1500px;
- --menu-size__admin-panel: 120px;
+ --block-size__admin-panel: 1512px;
+ --menu-size__admin-panel: 222px;
--table-size__admin-panel: 1000px;
--font-color__admin-panel: #292E32;
+ --notification-text-color__admin-panel: #ff4d4f;
--background__admin-panel: #F1FFF7;
- --background-butons__admin-panel: #0B6C61;
- --button-color__admin-panel: #0B6C61;
-}
\ No newline at end of file
+ --background-input__admin-panel: #FFF;
+ --border-input__admin-panel: #d9d9d9;
+ --background-butons__admin-panel: #1F9A7C;
+ --button-color__admin-panel: #1F9A7C;
+}
diff --git a/FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.jsx b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.jsx
new file mode 100644
index 000000000..d4e2455c3
--- /dev/null
+++ b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.jsx
@@ -0,0 +1,139 @@
+import axios from 'axios';
+import { toast } from 'react-toastify';
+import { useForm } from 'react-hook-form';
+
+import AdminSubmitButton from '../../../components/MiniComponents/AdminSubmitButton';
+
+import classes from './AdminInfo.module.css';
+
+const AdminInfo = ({ user, mutate }) => {
+ const {
+ register,
+ handleSubmit,
+ setValue,
+ getValues,
+ formState: { errors, isDirty },
+ } = useForm({
+ defaultValues: {
+ 'name': user.name,
+ 'surname': user.surname,
+ },
+ });
+
+ const onSubmit = (data) => {
+ axios.patch(`${process.env.REACT_APP_BASE_API_URL}/api/auth/users/me/`, data)
+ .then(() => {
+ toast.success('Зміни успішно збережено');
+ mutate();
+ })
+ .catch((error) => {
+ console.error(
+ 'Помилка:',
+ error.response ? error.response.data : error.message
+ );
+ if (!error.response || error.response.status !== 401) {
+ toast.error('Не вдалося зберегти зміни, сталася помилка');
+ }
+ });
+ };
+
+ const errorMessageTemplates = {
+ required: 'Обов’язкове поле',
+ nameSurnameFieldLength: 'Введіть від 2 до 50 символів',
+ notAllowedSymbols: 'Поле містить недопустимі символи та/або цифри',
+ maxLength: 'Кількість символів перевищує максимально допустиму (50 символів)',
+ };
+
+ 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);
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default AdminInfo;
\ No newline at end of file
diff --git a/FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.module.css b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.module.css
new file mode 100644
index 000000000..7b5eeff6a
--- /dev/null
+++ b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.module.css
@@ -0,0 +1,109 @@
+.admin-info-form {
+ display: flex;
+ padding: 0px 24px;
+}
+
+.admin-info-form__container {
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+}
+
+.admin-info-form__column {
+ display: flex;
+ width: 257px;
+ min-height: 84px;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 4px;
+}
+
+.admin-info-form__label {
+ display: flex;
+ gap: 4px;
+ align-self: stretch;
+ color: var(--font-color__admin-panel);
+ font-feature-settings: "calt" off;
+ font-family: var(--font-main);
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px;
+ letter-spacing: -0.14px;
+ text-align: left;
+}
+
+.admin-info-form__label--hint {
+ align-self: stretch;
+ font-size: 8px;
+ line-height: 16px;
+ position: relative;
+ top: 0px;
+}
+
+.admin-info-form__label--required {
+ color: var(--notification-text-color__admin-panel);
+ text-align: right;
+ font-family: var(--font-messages);
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 22.001px;
+ position: relative;
+ top: 10%;
+}
+
+.admin-info-form__label--text {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ flex: 1 0 0;
+ font-family: var(--font-main);
+ font-size: 14px;
+ font-weight: 400;
+ color: var(--main-text-color);
+}
+
+.admin-info-form__field {
+ display: flex;
+ align-items: center;
+ align-self: stretch;
+ border-radius: 2px;
+ background: var(--background-input__admin-panel);
+}
+
+.admin-info-form__input {
+ display: flex;
+ height: 22px;
+ padding: 5px 12px;
+ align-items: center;
+ gap: 4px;
+ flex: 1 0 0;
+ border-radius: 2px;
+ border: 1px solid var(--border-input__admin-panel);
+ background: var(--background-input__admin-panel);
+ color: var(--character-title-85, rgba(0, 0, 0, 0.85));
+ font-family: var(--font-messages);
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 22px;
+}
+
+.admin-info-form__input:focus {
+ border: 1px solid var(--main-header-color);
+ outline: none;
+}
+
+.admin-info-form__error {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ align-self: stretch;
+ color: var(--notification-text-color__admin-panel);
+ font-family: var(--font-messages);
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 16px;
+}
diff --git a/FrontEnd/src/pages/AdminPage/AdminProfile/AdminProfilePage.jsx b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminProfilePage.jsx
new file mode 100644
index 000000000..89f7fc9ad
--- /dev/null
+++ b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminProfilePage.jsx
@@ -0,0 +1,54 @@
+import { NavLink, Route, Routes } from 'react-router-dom';
+
+import { useAuth } from '../../../hooks';
+
+import BreadCrumbs from '../../../components/BreadCrumbs/BreadCrumbs';
+import ChangeAdminPassword from './ChangeAdminPassword';
+import AdminInfo from './AdminInfo';
+
+import classes from './AdminProfilePage.module.css';
+
+const ADMIN_PAGE_TABS = [
+ {
+ title: 'Загальна інформація',
+ link: '/admin-info',
+ },
+ {
+ title: 'Змінити пароль',
+ link: '/change-password',
+ },
+];
+
+const AdminProfilePage = () => {
+
+ const { user, mutate } = useAuth();
+
+ return (
+
+
+
+
+ {ADMIN_PAGE_TABS.map((element) => (
+ (`${classes['infolink']} ${isActive && classes['infolink__active']}`)}
+ to={`/customadmin/admin-profile${element.link}`}
+ key={element.title}
+ >
+ {element.title}
+
+ ))}
+
+
+ } />
+ } />
+
+
+
+ );
+};
+
+export default AdminProfilePage;
\ No newline at end of file
diff --git a/FrontEnd/src/pages/AdminPage/AdminProfile/AdminProfilePage.module.css b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminProfilePage.module.css
new file mode 100644
index 000000000..f377308ca
--- /dev/null
+++ b/FrontEnd/src/pages/AdminPage/AdminProfile/AdminProfilePage.module.css
@@ -0,0 +1,39 @@
+.admin-profile__container {
+ margin-top: 40px;
+ display: flex;
+ align-items: flex-start;
+ gap: 20px;
+ flex-direction: column;
+}
+
+.admin-profile__content {
+ display: flex;
+ flex-direction: row;
+}
+
+.admin-profile__links {
+ display: flex;
+ flex-direction: column;
+ padding-left: 10%;
+ align-items: flex-start;
+ width: var(--menu-size__admin-panel);
+ gap: 12px;
+}
+
+.infolink {
+ color: var(--font-color__admin-panel);
+ font-family: var(--font-main);
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 20px;
+ letter-spacing: -0.01em;
+ text-align: left;
+ text-decoration: none;
+}
+
+.infolink__active {
+ font-family: var(--font-main);
+ font-weight: 600;
+ color: #000000;
+ text-decoration: none;
+}
diff --git a/FrontEnd/src/pages/AdminPage/AdminProfile/ChangeAdminPassword.jsx b/FrontEnd/src/pages/AdminPage/AdminProfile/ChangeAdminPassword.jsx
new file mode 100644
index 000000000..a9b33873e
--- /dev/null
+++ b/FrontEnd/src/pages/AdminPage/AdminProfile/ChangeAdminPassword.jsx
@@ -0,0 +1,115 @@
+import axios from 'axios';
+import { PropTypes } from 'prop-types';
+import { toast } from 'react-toastify';
+import { useForm } from 'react-hook-form';
+
+import PasswordField from '../../ProfilePage/FormComponents/FormFields/PasswordField';
+import Loader from '../../../components/Loader/Loader';
+import AdminSubmitButton from '../../../components/MiniComponents/AdminSubmitButton';
+
+import classes from './ChangeAdminPassword.module.css';
+
+export default function ChangeAdminPassword(props) {
+
+ const {
+ register,
+ handleSubmit,
+ getValues,
+ watch,
+ reset,
+ formState: { errors, isDirty },
+ } = useForm({
+ mode: 'all',
+ defaultValues: {
+ currentPassword: '',
+ newPassword: '',
+ reNewPassword: '',
+ },
+ });
+
+ const handleFormSubmit = () => {
+ axios
+ .post(
+ `${process.env.REACT_APP_BASE_API_URL}/api/auth/users/set_password/`,
+ {
+ current_password: getValues('currentPassword'),
+ new_password: getValues('newPassword'),
+ re_new_password: getValues('reNewPassword'),
+ }
+ )
+ .then(() => toast.success('Пароль успішно змінено'))
+ .catch((error) => {
+ if (error.response && error.response.data && error.response.data['new_password']) {
+ const newPasswordError = error.response.data['new_password'][0];
+ if (newPasswordError === 'This password is too common.') {
+ toast.error('Пароль занадто поширений. Створіть інший пароль.');
+ } else if (newPasswordError.startsWith('The password is too similar to the')) {
+ toast.error('Пароль подібний на іншу персональну інформацію облікового запису. Створіть інший пароль.');
+ }
+ } else
+ toast.error('Виникла помилка. Можливо, вказано невірний поточний пароль');
+ });
+ reset();
+ };
+
+ return (
+
+ {props.user ? (
+
+ ) : (
+
+ )}
+
+ );
+}
+
+ChangeAdminPassword.propTypes = {
+ user: PropTypes.shape({
+ id: PropTypes.number.isRequired,
+ email: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
+ surname: PropTypes.string.isRequired,
+ is_staff: PropTypes.bool.isRequired,
+ }).isRequired,
+};
diff --git a/FrontEnd/src/pages/AdminPage/AdminProfile/ChangeAdminPassword.module.css b/FrontEnd/src/pages/AdminPage/AdminProfile/ChangeAdminPassword.module.css
new file mode 100644
index 000000000..e70e6bbcd
--- /dev/null
+++ b/FrontEnd/src/pages/AdminPage/AdminProfile/ChangeAdminPassword.module.css
@@ -0,0 +1,14 @@
+.form__container {
+ display: flex;
+ flex-direction: column;
+ padding: 0px 24px;
+ word-wrap: break-word;
+
+}
+
+.form-new-password {
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+ align-items: center;
+}
diff --git a/FrontEnd/src/pages/AdminPage/Header/Header.jsx b/FrontEnd/src/pages/AdminPage/Header/Header.jsx
deleted file mode 100644
index 6fe6c511a..000000000
--- a/FrontEnd/src/pages/AdminPage/Header/Header.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import css from './Header.module.css';
-import { Link } from 'react-router-dom';
-
-function Header() {
- return (
-
- );
-}
-
-export default Header;
diff --git a/FrontEnd/src/pages/AdminPage/Header/Header.module.css b/FrontEnd/src/pages/AdminPage/Header/Header.module.css
deleted file mode 100644
index 10c4f48a9..000000000
--- a/FrontEnd/src/pages/AdminPage/Header/Header.module.css
+++ /dev/null
@@ -1,51 +0,0 @@
-.header-content {
- display: flex;
- margin: 10px;
- justify-content: space-between;
- align-items: center;
-}
-
-.header-divider {
- width: 100%;
- height: 2px;
- background: var(--main-black-20, #E2E5EB);
-}
-
-.header-logo__text {
- color: #292E32;
- font-feature-settings: 'calt' off;
- text-decoration: none;
- font-family: var(--font__admin-panel);
- font-size: 24px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px;
- letter-spacing: -0.24px;
-}
-
-.header-view__button {
- display: flex;
- padding: 5px 15px;
- justify-content: center;
- align-items: center;
- gap: 10px;
-
- border-radius: 4px;
- border: 1px solid var(--button-color__admin-panel);
- background: var(--button-color__admin-panel);
-
- box-shadow: 0px 2px 0px 0px rgba(0, 0, 0, 0.04);
- color: #FFF;
- text-align: center;
- font-family: var(--font__admin-panel);
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 20px;
- letter-spacing: -0.16px;
-}
-
-.header-view__button:hover {
- background: #FFF;
- color: var(--button-color__admin-panel);
-}
\ No newline at end of file
diff --git a/FrontEnd/src/pages/AdminPage/MainPage/MainPage.jsx b/FrontEnd/src/pages/AdminPage/MainPage/MainPage.jsx
index e560d3e18..5bb5d5eb6 100644
--- a/FrontEnd/src/pages/AdminPage/MainPage/MainPage.jsx
+++ b/FrontEnd/src/pages/AdminPage/MainPage/MainPage.jsx
@@ -4,8 +4,8 @@ import css from './mainPage.module.css';
function MainPage() {
return (
-
Welcome to the admin panel
-
Here, you can:
+
Вітаємо в панелі адміністратора.
+
Тут ви можете:
{MAIN_PAGE_TEXT.map((element) => (
diff --git a/FrontEnd/src/pages/AdminPage/MainPage/Text.js b/FrontEnd/src/pages/AdminPage/MainPage/Text.js
index 808413785..a0390b101 100644
--- a/FrontEnd/src/pages/AdminPage/MainPage/Text.js
+++ b/FrontEnd/src/pages/AdminPage/MainPage/Text.js
@@ -1,22 +1,26 @@
export const MAIN_PAGE_TEXT = [
{
- title: 'Check Profiles:',
- text: 'Review user and company profiles.'
+ title: 'Перевіряти профілі:',
+ text: 'Переглянути профілі користувачів та компаній.'
},
{
- title: 'Edit Profiles:',
- text: 'Make necessary updates to profiles for accuracy.'
+ title: 'Редагувати профілі:',
+ text: 'Внести необхідні зміни в профілі.'
},
{
- title: 'Approve Profiles:',
- text: 'Give the green light to new profiles.'
+ title: 'Затверджувати профілі:',
+ text: 'Підтвердити дійсність нових профілів та затвердити зміни в існуючих.'
},
{
- title: 'Delete Profiles:',
- text: 'In case of policy violations or other issues.'
+ title: 'Видаляти профілі:',
+ text: 'Видалити профіль у разі порушення правил користування сайтом або з інших причин.'
},
{
- title: 'Set autoapprove timeout:',
- text: 'Specify the time (from 1 to 48 hours) after which the user\'s request to change the banner/logo will be approved automatically.'
+ title: 'Встановлювати таймаут для автозатвердження:',
+ text: 'Вказати час (від 1 до 48 годин), після якого запит користувача на зміну банера/логотипу буде підтверджено автоматично.'
+ },
+ {
+ title: 'Встановити електронну адресу модератора:',
+ text: 'Вказати електронну адресу, на яку будуть приходити листи із запитом на затвердження зміни банера/логотипу в профілі.'
}
];
diff --git a/FrontEnd/src/pages/AdminPage/MainPage/mainPage.module.css b/FrontEnd/src/pages/AdminPage/MainPage/mainPage.module.css
index 3484ba4b4..556778fd5 100644
--- a/FrontEnd/src/pages/AdminPage/MainPage/mainPage.module.css
+++ b/FrontEnd/src/pages/AdminPage/MainPage/mainPage.module.css
@@ -6,10 +6,10 @@
}
.main-page-section h1 {
- font-size: 40px;
+ font-size: 20px;
margin-bottom: 50px;
}
.main-page-section p {
- font-size: 30px;
+ font-size: 20px;
}
diff --git a/FrontEnd/src/pages/AdminPage/Menu/Menu.jsx b/FrontEnd/src/pages/AdminPage/Menu/Menu.jsx
index a1995dc15..93544cea8 100644
--- a/FrontEnd/src/pages/AdminPage/Menu/Menu.jsx
+++ b/FrontEnd/src/pages/AdminPage/Menu/Menu.jsx
@@ -1,8 +1,6 @@
-import css from './Menu.module.css';
-import { Link } from 'react-router-dom';
-import { useAuth } from '../../../hooks';
-import axios from 'axios';
+import { NavLink } from 'react-router-dom';
+import css from './Menu.module.css';
const MENU = [
{
@@ -38,23 +36,15 @@ const MENU = [
];
function Menu() {
- const { isAuth, logout } = useAuth();
- const handleLogout = async () => {
- if (isAuth) {
- axios.post(`${process.env.REACT_APP_BASE_API_URL}/api/auth/token/logout`)
- .then(() => {
- logout();
- });
- }
- };
return (
{MENU.map((element) => (
-
{element.title}
+
(`${css['menu-section-element']} ${isActive && css['menu-section-element__active']}`)}
+ key={element.id} to={element.link}>{element.title}
+
))}
-
-
Вихід
);
}
diff --git a/FrontEnd/src/pages/AdminPage/Menu/Menu.module.css b/FrontEnd/src/pages/AdminPage/Menu/Menu.module.css
index 1309e1632..93170f61f 100644
--- a/FrontEnd/src/pages/AdminPage/Menu/Menu.module.css
+++ b/FrontEnd/src/pages/AdminPage/Menu/Menu.module.css
@@ -1,7 +1,7 @@
.menu-section {
display: flex;
width: var(--menu-size__admin-panel);
- padding: 20px;
+ padding: 30px;
flex-direction: column;
align-items: flex-start;
gap: 23px;
@@ -14,26 +14,11 @@
font-family: var(--font__admin-panel);
font-size: 20px;
font-style: normal;
- font-weight: 600;
+ font-weight: 400;
line-height: 22px;
letter-spacing: -0.14px;
}
-.menu-section-divider {
- height: 1px;
- align-self: stretch;
- width: var(--menu-size__admin-panel);
- background: var(--main-black-20, #E2E5EB);
-}
-
-.menu-section-logout {
- color: var(--system-red-100, #F15831);
- font-feature-settings: 'calt' off;
- text-decoration: none;
- font-family: var(--font__admin-panel);
- font-size: 20px;
- font-style: normal;
+.menu-section-element__active {
font-weight: 600;
- line-height: 22px;
- letter-spacing: -0.14px;
-}
\ No newline at end of file
+}
diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx
index 32b408fd7..d466d07bf 100644
--- a/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx
+++ b/FrontEnd/src/pages/ProfilePage/FormComponents/ChangePassword.jsx
@@ -71,7 +71,6 @@ export default function ChangePassword(props) {
label="Поточний пароль"
register={register}
error={errors}
- showError={false}
watch={watch}
checkValid={false}
checkMatch={{
@@ -85,7 +84,6 @@ export default function ChangePassword(props) {
label="Новий пароль"
error={errors}
register={register}
- showError={true}
watch={watch}
checkValid={true}
checkMatch={{
diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.jsx b/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.jsx
index 79359eadc..5f0060e1f 100644
--- a/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.jsx
+++ b/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.jsx
@@ -1,11 +1,15 @@
import { useState } from 'react';
import { PropTypes } from 'prop-types';
+import classNames from 'classnames';
+
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';
+import css from './PasswordField.module.css';
+
const PasswordField = (props) => {
const errorMessages = {
invalidPassword: 'Пароль не відповідає вимогам',
@@ -34,11 +38,18 @@ const PasswordField = (props) => {
{label}
+ {label !== 'Поточний пароль' &&
+
+ (Повинен містити від 8 символів, A-Z, a-z, 0-9)
+
+ }
@@ -47,7 +58,6 @@ const PasswordField = (props) => {
id={inputId}
type={showPassword ? 'text' : 'password'}
placeholder={label}
- required
{...register(name, {
required: errorMessages.requiredField,
pattern: checkValid && {
diff --git a/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.module.css b/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.module.css
index bdc08c98b..1d9636d5b 100644
--- a/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.module.css
+++ b/FrontEnd/src/pages/ProfilePage/FormComponents/FormFields/PasswordField.module.css
@@ -6,10 +6,10 @@
align-items: flex-start;
}
-.password-field__item label {
+.password-field__label--content {
font-feature-settings: "calt" off;
align-items: center;
- color: #292e32;
+ color: var(--main-black-90);
display: flex;
font-family: var(--font-main);
font-size: 14px;
@@ -18,11 +18,24 @@
gap: 4px;
letter-spacing: -.14px;
line-height: 20px;
- padding-bottom: 8px;
+}
+
+.password-field__label--gap {
+ padding-bottom: 10px;
}
.password-field__label-wrapper {
- padding-bottom: 9px;
+ display: flex;
+ flex-direction: column;
+ margin-left: 10px;
+}
+
+.password-field__label--hint {
+ align-self: stretch;
+ font-size: 8px;
+ line-height: 16px;
+ position: relative;
+ top: 0px;
}
.password-field__label-wrapper span {
@@ -33,6 +46,7 @@
.password-field__item input {
border: none;
}
+
.password-field__item input:focus {
border: none;
outline: none;
@@ -48,6 +62,7 @@
text-align: left;
color: #00000040;
}
+
.password-field__password {
display: flex;
padding: 4px 12px;
@@ -70,7 +85,7 @@
border-radius: 2px;
border: 1px solid #1f9a7c;
background: #fff;
- }
+}
.password-field__password__wrapper {
display: flex;
@@ -98,7 +113,7 @@
.error-dot::before {
position: absolute;
- margin-left: -10px;
+ margin-left: -8px;
content: "*";
color: #ff4d4f;
text-align: right;
@@ -107,4 +122,4 @@
font-style: normal;
font-weight: 400;
line-height: 22.001px;
- }
\ No newline at end of file
+}
diff --git a/FrontEnd/src/pages/SearchPage/tests/Search.test.js b/FrontEnd/src/pages/SearchPage/tests/Search.test.js
index 3c56e8436..f5a1dd22d 100644
--- a/FrontEnd/src/pages/SearchPage/tests/Search.test.js
+++ b/FrontEnd/src/pages/SearchPage/tests/Search.test.js
@@ -3,6 +3,10 @@ import { MemoryRouter } from 'react-router-dom';
import Search from '../Search';
+jest.mock('../../../hooks', () => ({
+ useAuth: () => ({isStaff: false}),
+}));
+
afterEach(() => {
jest.resetAllMocks();
});
diff --git a/FrontEnd/src/routes/AdminRouter.jsx b/FrontEnd/src/routes/AdminRouter.jsx
index 25e8b3c2e..a9fc3c41e 100644
--- a/FrontEnd/src/routes/AdminRouter.jsx
+++ b/FrontEnd/src/routes/AdminRouter.jsx
@@ -1,25 +1,30 @@
import { ToastContainer } from 'react-toastify';
-import '../pages/AdminPage/AdminGlobal.css';
-import Header from '../pages/AdminPage/Header/Header';
+import { Routes, Route, useLocation } from 'react-router-dom';
+
+import { useAuth } from '../hooks';
+
+import Header from '../components/Header/Header';
import Menu from '../pages/AdminPage/Menu/Menu';
import UserDetail from '../pages/AdminPage/DetailView/UserDetail';
import UserTable from '../pages/AdminPage/UserProfilesTable/UserTable';
import ProfilesTable from '../pages/AdminPage/UserProfilesTable/ProfilesTable';
import ProfileDetail from '../pages/AdminPage/DetailView/ProfileDetail';
-import css from '../pages/AdminPage/AdminPage.module.css';
-import { Routes, Route } from 'react-router-dom';
import MainPage from '../pages/AdminPage/MainPage/MainPage';
-import { useAuth } from '../hooks';
import Loader from '../components/Loader/Loader';
import AutoApproveDelay from '../pages/AdminPage/AutoApproveDelay/AutoApproveDelay';
import ModerationEmail from '../pages/AdminPage/DetailView/ModerationEmail';
import Contacts from '../pages/AdminPage/DetailView/Contacts';
+import AdminProfilePage from '../pages/AdminPage/AdminProfile/AdminProfilePage';
import AdminRegistration from '../pages/AdminPage/AdminRegistration/AdminRegistration';
+import '../pages/AdminPage/AdminGlobal.css';
+import css from '../pages/AdminPage/AdminPage.module.css';
function AdminRouter() {
- const { isLoading, isAuth, isStaff } = useAuth();
- const renderMenu = isStaff && isAuth ?
: null;
+ const { isLoading, isAuth, isStaff, user } = useAuth();
+ const { pathname } = useLocation();
+ const hideMenu = pathname.includes('/admin-profile/');
+ const renderMenu = isStaff && isAuth && !hideMenu ?
: null;
const authRoutes = isStaff && isAuth ? (
<>
} />
@@ -30,6 +35,7 @@ function AdminRouter() {
} />
} />
} />
+
} />
} />
>
) : (
@@ -38,7 +44,7 @@ function AdminRouter() {
return (
-
+
{isLoading ?
:
{renderMenu}