Skip to content

Commit

Permalink
Resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
YanZhylavy committed Oct 11, 2024
2 parents 6816d8e + a1cacec commit bbc4eb4
Show file tree
Hide file tree
Showing 28 changed files with 662 additions and 174 deletions.
36 changes: 24 additions & 12 deletions FrontEnd/src/components/BreadCrumbs/BreadCrumbs.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className={css['content']}>
<button
className={css['goback__button']}
type="button"
onClick={goBackHandler}
>
<i className={css['left']}></i>Назад
</button>
<Link className={css['main-page__button']} to="/">
Головна
</Link>
{ !isStaff ? (
<button
className={css['goback__button']}
type="button"
onClick={goBackHandler}
>
<i className={css['left']}></i>Назад
</button>
) : null
}
{!isStaff ? (
<Link className={css['main-page__button']} to="/">
Головна
</Link>
) : (
<Link className={css['main-page__button']} to="/customadmin">
Панель адміністратора
</Link>)
}
<i className={css['right']}></i>
<div className={css['current-page__button']}>{currentPage}</div>
</div>
Expand Down
16 changes: 11 additions & 5 deletions FrontEnd/src/components/Header/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import css from './Header.module.css';
import { useLocation } from 'react-router-dom';

import HeaderMenu from './Menu/HeaderMenu';
import Navbar from './Navbar/Navbar';

import css from './Header.module.css';

function Header(props) {
const { pathname } = useLocation();
const hideMenu = pathname === '/login' || pathname === '/sign-up' || pathname.includes('/customadmin');

return (
<header>
<div className={css['header-content']}>
<Navbar isAuthorized={props.isAuthorized} page={props.page}></Navbar>
<Navbar isAuthorized={props.isAuthorized} page={pathname}></Navbar>
<div className={css['header-divider']}></div>
{props.page === 'login' || props.page === 'registration' ? null : (
<HeaderMenu />
)}
{hideMenu ? null : (
<HeaderMenu />
)}
<div className={css['header-divider']}></div>
</div>
</header>
Expand Down
4 changes: 2 additions & 2 deletions FrontEnd/src/components/Header/Navbar/Buttons.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import css from './Buttons.module.css';
import { Link } from 'react-router-dom';

function Buttons() {
function Buttons({adminPage}) {
return (
<div className={css['header-buttons-section']}>
<Link className={css['header-login__button']} to="/login">Увійти</Link>
<Link className={css['header-register__button']} to="/sign-up">Зареєструватися</Link>
{!adminPage && <Link className={css['header-register__button']} to="/sign-up">Зареєструватися</Link>}
</div>
);
}
Expand Down
18 changes: 12 additions & 6 deletions FrontEnd/src/components/Header/Navbar/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import css from './Navbar.module.css';
import { Link } from 'react-router-dom';

import { useAuth } from '../../../hooks';

import Menu from './Menu';
import SearchBox from './SearchBox';
import Profile from './Profile';
import Buttons from './Buttons';
import { Link } from 'react-router-dom';

function Navbar(props) {
import css from './Navbar.module.css';

function Navbar (props) {
const { isStaff} = useAuth();
const hideMenu = props.page === '/login' || props.page === '/sign-up' || props.page.includes('/customadmin');
return (
<div className={css['navbar-content']}>
<div className={css['navbar-logo__text']}>
<Link to="/">
<Link to="/" target={isStaff ? '_blank' : null}>
<img
className={css['navbar-main-logo']}
src={`${process.env.REACT_APP_PUBLIC_URL}/craftMerge-logo.svg`}
Expand All @@ -18,13 +24,13 @@ function Navbar(props) {
</Link>
</div>
<div className={css['navbar-utility-bar']}>
{props.page === 'login' || props.page === 'registration' ? null : (
{ hideMenu ? null : (
<>
<Menu />
<SearchBox></SearchBox>
</>
)}
{props.isAuthorized === true ? <Profile /> : <Buttons />}
{props.isAuthorized === true ? <Profile /> : <Buttons adminPage={props.page.includes('/customadmin')} />}
</div>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions FrontEnd/src/components/Header/Navbar/Navbar.module.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
.navbar-content {
display: flex;
width: 70%;
padding: 8px 104px;
align-items: center;
justify-content: space-between;
height: var(--navbar-content-height);
}

.navbar-logo__text{
.navbar-logo__text {
display: flex;
}

.navbar-main-logo{
.navbar-main-logo {
display: flex;
width: 199px;
height: 24px;
Expand Down
12 changes: 6 additions & 6 deletions FrontEnd/src/components/Header/Navbar/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import css from './Profile.module.css';


function Profile() {
const { user, isAuth, logout } = useAuth();
const { user, isAuth, logout, isStaff } = useAuth();
const navigate = useNavigate();

const navigateToProfile = () => {
Expand All @@ -31,12 +31,12 @@ function Profile() {
className={css['header-profile__avatar']}
src={`${process.env.REACT_APP_PUBLIC_URL}/img/Avatar.png`}
alt="Avatar"
onClick={navigateToProfile}
onClick={!isStaff ? navigateToProfile : null}
/>
<DropdownMenu toggleText="Профіль">
<Link to="/profile/user-info">Профіль</Link>
<button onClick={performLogout}>Вихід</button>
</DropdownMenu>
<DropdownMenu toggleText={isStaff ? 'Адміністратор' : 'Профіль'}>
<Link to={isStaff ? '/customadmin/admin-profile/admin-info' : '/profile/user-info'}>Профіль</Link>
<button onClick={performLogout}>Вихід</button>
</DropdownMenu>
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions FrontEnd/src/components/Header/Navbar/SearchBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function SearchBox() {
<div className={css['header-search-form']}>
<input
className={css['header-search-form__input']}
id="search_box"
value={searchTerm}
type="text"
placeholder="Пошук"
Expand Down
17 changes: 17 additions & 0 deletions FrontEnd/src/components/MiniComponents/AdminSubmitButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import classes from './AdminSubmitButton.module.css';

const AdminSubmitButton = ({ disabled }) => {
return (
<div className={classes['admin-submit__container']}>
<button
className={classes['admin-submit__button']}
type="submit"
disabled={disabled}
>
Зберегти зміни
</button>
</div>
);
};

export default AdminSubmitButton;
Original file line number Diff line number Diff line change
@@ -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);
}
13 changes: 8 additions & 5 deletions FrontEnd/src/pages/AdminPage/AdminGlobal.css
Original file line number Diff line number Diff line change
@@ -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;
}
--background-input__admin-panel: #FFF;
--border-input__admin-panel: #d9d9d9;
--background-butons__admin-panel: #1F9A7C;
--button-color__admin-panel: #1F9A7C;
}
139 changes: 139 additions & 0 deletions FrontEnd/src/pages/AdminPage/AdminProfile/AdminInfo.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className={classes['admin-info-form']}>
<form onSubmit={handleSubmit(onSubmit)}>
<div className={classes['admin-info-form__container']}>
<div className={classes['admin-info-form__column']}>
<div className={classes['admin-info-form__label']}>
<label className={classes['admin-info-form__label--required']} htmlFor="name">
*
</label>
<label className={classes['admin-info-form__label--text']} htmlFor="name">Ім‘я</label>
</div>
<div className={classes['admin-info-form__field']}>
<input
className={classes['admin-info-form__input']}
id="name"
autoComplete="name"
type="text"
placeholder="Ім‘я"
{...register('name', {
required: errorMessageTemplates.required,
validate: validateNameSurname,
maxLength: {
value: 50,
message: errorMessageTemplates.maxLength
},
})}
onBlur={() => onBlurHandler('name')}
/>
</div>
<div className={classes['admin-info-form__error']}>
{errors.name && errors.name.message}
</div>
</div>
<div className={classes['admin-info-form__column']}>
<div className={classes['admin-info-form__label']}>
<label className={classes['admin-info-form__label--required']} htmlFor="surname">
*
</label>
<label className={classes['admin-info-form__label--text']} htmlFor="surname">
Прізвище
</label>
</div>
<div className={classes['admin-info-form__field']}>
<input
className={classes['admin-info-form__input']}
id="surname"
autoComplete="family-name"
type="text"
placeholder="Прізвище"
{...register('surname', {
required: errorMessageTemplates.required,
validate: validateNameSurname,
maxLength: {
value: 50,
message: errorMessageTemplates.maxLength
},
})}
onBlur={() => onBlurHandler('surname')}
/>
</div>
<div className={classes['admin-info-form__error']}>
{errors.surname && errors.surname.message}
</div>
</div>
<AdminSubmitButton disabled={!isDirty}/>
</div>
</form>
</div>
);
};

export default AdminInfo;
Loading

0 comments on commit bbc4eb4

Please sign in to comment.