Compare commits
28 Commits
page_under
...
fixes_task
Author | SHA1 | Date | |
---|---|---|---|
7b4b4f37fc | |||
33af4ebbd6 | |||
5608e4e4f2 | |||
214d309ffb | |||
a156557d57 | |||
1254557a08 | |||
c22f26f6fe | |||
9cb59b61d6 | |||
4464324ae2 | |||
4cd3118649 | |||
16e3a2649d | |||
b61c9ba58a | |||
d75507ea46 | |||
b02eff466f | |||
a76725edf5 | |||
5cdf072551 | |||
9771d2a602 | |||
0a8ed604a0 | |||
4084c52a9b | |||
b6a4ff6652 | |||
15f8b51327 | |||
1d9a47def4 | |||
9909101660 | |||
ca0a509077 | |||
7e64150378 | |||
911b827e41 | |||
104f538e3a | |||
e27da9fca9 |
3
src/assets/icons/folder.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11.4339 2.66676H7.24725L7.03392 2.0001C6.89562 1.60892 6.63908 1.27043 6.29985 1.03154C5.96062 0.792642 5.55549 0.665163 5.14059 0.666763H2.10059C1.57015 0.666763 1.06145 0.877477 0.686373 1.25255C0.3113 1.62762 0.100586 2.13633 0.100586 2.66676V11.3334C0.100586 11.8639 0.3113 12.3726 0.686373 12.7476C1.06145 13.1227 1.57015 13.3334 2.10059 13.3334H11.4339C11.9644 13.3334 12.4731 13.1227 12.8481 12.7476C13.2232 12.3726 13.4339 11.8639 13.4339 11.3334V4.66676C13.4339 4.13633 13.2232 3.62762 12.8481 3.25255C12.4731 2.87748 11.9644 2.66676 11.4339 2.66676ZM12.1006 11.3334C12.1006 11.5102 12.0303 11.6798 11.9053 11.8048C11.7803 11.9299 11.6107 12.0001 11.4339 12.0001H2.10059C1.92378 12.0001 1.75421 11.9299 1.62918 11.8048C1.50416 11.6798 1.43392 11.5102 1.43392 11.3334V2.66676C1.43392 2.48995 1.50416 2.32038 1.62918 2.19536C1.75421 2.07033 1.92378 2.0001 2.10059 2.0001H5.14059C5.28035 1.99974 5.41669 2.04331 5.53034 2.12466C5.64399 2.20601 5.7292 2.32102 5.77392 2.45343L6.13392 3.54676C6.17864 3.67918 6.26385 3.79419 6.3775 3.87553C6.49115 3.95688 6.62749 4.00046 6.76725 4.0001H11.4339C11.6107 4.0001 11.7803 4.07033 11.9053 4.19536C12.0303 4.32038 12.1006 4.48995 12.1006 4.66676V11.3334Z" fill="#52B709"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
4
src/assets/icons/tgSettingsIcon.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 12.5C0 5.87258 5.37258 0.5 12 0.5H28C34.6274 0.5 40 5.87258 40 12.5V28.5C40 35.1274 34.6274 40.5 28 40.5H12C5.37258 40.5 0 35.1274 0 28.5V12.5Z" fill="#F0F4FA"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.4809 14.1916C26.6868 14.105 26.9122 14.0751 27.1336 14.1051C27.355 14.1351 27.5643 14.2239 27.7398 14.3622C27.9152 14.5006 28.0504 14.6834 28.1312 14.8917C28.212 15.1 28.2355 15.3262 28.1992 15.5466L26.3092 27.0108C26.1259 28.1166 24.9125 28.7508 23.8984 28.2C23.05 27.7391 21.79 27.0291 20.6567 26.2883C20.09 25.9175 18.3542 24.73 18.5675 23.885C18.7509 23.1625 21.6675 20.4475 23.3342 18.8333C23.9884 18.1991 23.69 17.8333 22.9175 18.4166C20.9984 19.865 17.9192 22.0675 16.9009 22.6875C16.0025 23.2341 15.5342 23.3275 14.9742 23.2341C13.9525 23.0641 13.005 22.8008 12.2317 22.48C11.1867 22.0466 11.2375 20.61 12.2309 20.1916L26.4809 14.1916Z" fill="#7992B2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 992 B |
BIN
src/assets/images/landing/reportingSystem.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/images/landing/searchIT.webp
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/images/landing/systemControlGit.webp
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src/assets/images/landing/taskManagement.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
src/assets/images/landingTracker/reportingSystem.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/images/landingTracker/searchIT.webp
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/images/landingTracker/systemControlGit.webp
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src/assets/images/landingTracker/target.webp
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
src/assets/images/landingTracker/taskManagement.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
@ -10,7 +10,6 @@ import { apiRequest } from "@api/request";
|
|||||||
|
|
||||||
import { Loader } from "@components/Common/Loader/Loader";
|
import { Loader } from "@components/Common/Loader/Loader";
|
||||||
import ModalErrorLogin from "@components/Modal/ModalErrorLogin/ModalErrorLogin";
|
import ModalErrorLogin from "@components/Modal/ModalErrorLogin/ModalErrorLogin";
|
||||||
import ModalRegistration from "@components/Modal/ModalRegistration/ModalRegistration";
|
|
||||||
import ModalResetPassword from "@components/Modal/ModalResetPassword/ModalResetPassword";
|
import ModalResetPassword from "@components/Modal/ModalResetPassword/ModalResetPassword";
|
||||||
|
|
||||||
import authHead from "assets/icons/authHead.svg";
|
import authHead from "assets/icons/authHead.svg";
|
||||||
@ -30,7 +29,6 @@ export const AuthBox = ({ title }) => {
|
|||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [modalError, setModalError] = useState(false);
|
const [modalError, setModalError] = useState(false);
|
||||||
const [modalReset, setModalReset] = useState(false);
|
const [modalReset, setModalReset] = useState(false);
|
||||||
const [modalReg, setModalReg] = useState(false);
|
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -128,19 +126,7 @@ export const AuthBox = ({ title }) => {
|
|||||||
Восстановить пароль
|
Восстановить пароль
|
||||||
</span>
|
</span>
|
||||||
<ModalResetPassword active={modalReset} setActive={setModalReset} />
|
<ModalResetPassword active={modalReset} setActive={setModalReset} />
|
||||||
<ModalRegistration active={modalReg} setActive={setModalReg} />
|
|
||||||
</div>
|
</div>
|
||||||
<p className="auth-box__registration">
|
|
||||||
У вас ещё нет аккаунта?
|
|
||||||
<span
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setModalReg(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Зарегистрироваться
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -117,25 +117,45 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__body {
|
&__body {
|
||||||
div {
|
&__week-days {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: #9babc5;
|
color: #9babc5;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-mobile {
|
||||||
|
display: none;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #9babc5;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
margin: 20px 0 20px;
|
margin: 20px 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__form {
|
&__form {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: repeat(7, 1fr);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@ -153,7 +173,7 @@
|
|||||||
|
|
||||||
.form-date {
|
.form-date {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 5px 0 0 15px;
|
padding: 5px 0 0 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,12 +225,10 @@
|
|||||||
|
|
||||||
@media (max-width: 550px) {
|
@media (max-width: 550px) {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 35px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 450px) {
|
@media (max-width: 450px) {
|
||||||
width: 45px;
|
width: 45px;
|
||||||
height: 35px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,6 +283,11 @@
|
|||||||
}
|
}
|
||||||
.form-box {
|
.form-box {
|
||||||
background-color: #fafbfe;
|
background-color: #fafbfe;
|
||||||
|
padding: 0 10px;
|
||||||
|
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.form-hours {
|
.form-hours {
|
||||||
color: #6dd077;
|
color: #6dd077;
|
||||||
@ -284,6 +307,11 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-hours::before {
|
.form-hours::before {
|
||||||
|
@ -4,6 +4,8 @@ import { Link, NavLink } from "react-router-dom";
|
|||||||
|
|
||||||
import { BurgerButton } from "@components/BurgerMenu/burgerButton";
|
import { BurgerButton } from "@components/BurgerMenu/burgerButton";
|
||||||
import { BurgerMenu } from "@components/BurgerMenu/burgerMenu";
|
import { BurgerMenu } from "@components/BurgerMenu/burgerMenu";
|
||||||
|
import ModalAuth from "@components/Modal/ModalAuth/ModalAuth";
|
||||||
|
import ModalRegistration from "@components/Modal/ModalRegistration/ModalRegistration";
|
||||||
|
|
||||||
import authIcon from "assets/icons/authIcon.svg";
|
import authIcon from "assets/icons/authIcon.svg";
|
||||||
|
|
||||||
@ -11,15 +13,23 @@ import "./authHeader.scss";
|
|||||||
|
|
||||||
export const AuthHeader = () => {
|
export const AuthHeader = () => {
|
||||||
const [actionMenu, setActionMenu] = useState(false);
|
const [actionMenu, setActionMenu] = useState(false);
|
||||||
|
const [modalReg, setModalReg] = useState(false);
|
||||||
|
const [modalAuth, setModalAuth] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="auth-header">
|
<div className="auth-header">
|
||||||
<BurgerMenu active={actionMenu} />
|
<BurgerMenu active={actionMenu} />
|
||||||
|
<ModalRegistration active={modalReg} setActive={setModalReg} />
|
||||||
|
<ModalAuth active={modalAuth} setActive={setModalAuth} />
|
||||||
<div className="auth-header__navigation">
|
<div className="auth-header__navigation">
|
||||||
<div className="auth__logo">
|
<div className="auth__logo">
|
||||||
<div>
|
<div>
|
||||||
<BurgerButton active={actionMenu} setActive={setActionMenu} />
|
<BurgerButton active={actionMenu} setActive={setActionMenu} />
|
||||||
</div>
|
</div>
|
||||||
<h3>IT GUILD</h3>
|
<NavLink to={"/"}>
|
||||||
|
<h3>IT GUILD</h3>
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Link to="/auth">
|
<Link to="/auth">
|
||||||
<SVG src={authIcon} />
|
<SVG src={authIcon} />
|
||||||
@ -29,28 +39,34 @@ export const AuthHeader = () => {
|
|||||||
<div className="auth-nav">
|
<div className="auth-nav">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<NavLink to={"/auth"}>кейсы</NavLink>
|
<NavLink to={"/stack"}>Аутстафинг</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<NavLink to={"/stack"}>стек</NavLink>
|
<NavLink to={"/tracker-intro"}>Трекер</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<NavLink to={"/tracker-intro"}>как это работает</NavLink>
|
<NavLink to={"/auth-candidate"}>Работа в IT</NavLink>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<NavLink to={"/auth-candidate"}>отзывы</NavLink>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<NavLink to={"/profile"}>наши продукты</NavLink>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="auth__buttons">
|
<div className="auth__buttons">
|
||||||
<button className="signIn">
|
<button
|
||||||
<Link to="/auth">войти</Link>
|
className="signIn"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setModalAuth(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
войти
|
||||||
</button>
|
</button>
|
||||||
<button className="signUp">
|
<button
|
||||||
<Link to="/auth">регистрация</Link>
|
className="signUp"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setModalReg(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
регистрация
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -130,9 +130,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.signUp {
|
.signUp {
|
||||||
a {
|
color: #a7ca60;
|
||||||
color: #a7ca60;
|
|
||||||
}
|
|
||||||
border: 1px solid #a7ca60;
|
border: 1px solid #a7ca60;
|
||||||
background: none;
|
background: none;
|
||||||
|
|
||||||
|
@ -24,19 +24,35 @@ export const Footer = () => {
|
|||||||
<div className="footer__bottom">
|
<div className="footer__bottom">
|
||||||
<div className="footer__social">
|
<div className="footer__social">
|
||||||
<div className="footer__social__icons">
|
<div className="footer__social__icons">
|
||||||
<a href="https://www.vk.com/">
|
<a
|
||||||
|
href="https://www.vk.com/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
<img src={vk} alt="vk" width={24} />
|
<img src={vk} alt="vk" width={24} />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.telegram.org/">
|
<a
|
||||||
|
href="https://www.telegram.org/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
<img src={tg} alt="tg" width={24} />
|
<img src={tg} alt="tg" width={24} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<a href="mailto:office@itguild.info">office@itguild.info</a>
|
<a
|
||||||
|
href="mailto:office@itguild.info"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
office@itguild.info
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="footer__info">
|
<div className="footer__info">
|
||||||
<div className="footer__mail">
|
<div className="footer__mail">
|
||||||
{/* <img src={email} alt="email" /> */}
|
{/* <img src={email} alt="email" /> */}
|
||||||
<a href="#">Присоединиться к команде</a>
|
<a href="#" target="_blank" rel="noopener noreferrer">
|
||||||
|
Присоединиться к команде
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
© {new Date().getFullYear()} - Outstaffing. Все права защищены
|
© {new Date().getFullYear()} - Outstaffing. Все права защищены
|
||||||
|
@ -119,6 +119,10 @@
|
|||||||
.create-ticket-project {
|
.create-ticket-project {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: white;
|
background: white;
|
||||||
|
|
||||||
|
@media (max-width: 770px) {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-editor {
|
.ck-editor {
|
||||||
|
124
src/components/Modal/ModalAuth/ModalAuth.jsx
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { loading, selectIsLoading } from "@redux/loaderSlice";
|
||||||
|
import { auth, setUserInfo } from "@redux/outstaffingSlice";
|
||||||
|
import { setRole } from "@redux/roleSlice";
|
||||||
|
|
||||||
|
import { apiRequest } from "@api/request";
|
||||||
|
|
||||||
|
// import { useNotification } from "@hooks/useNotification";
|
||||||
|
import BaseButton from "@components/Common/BaseButton/BaseButton";
|
||||||
|
import { Loader } from "@components/Common/Loader/Loader";
|
||||||
|
import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
|
||||||
|
|
||||||
|
import "./modalAuth.scss";
|
||||||
|
|
||||||
|
export const ModalAuth = ({ active, setActive }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const isLoading = useSelector(selectIsLoading);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
const [modalError, setModalError] = useState(false);
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
email: "",
|
||||||
|
password: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
setActive(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
[name]: value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitHandler = () => {
|
||||||
|
if (!isLoading) {
|
||||||
|
dispatch(loading(true));
|
||||||
|
apiRequest("/user/login", {
|
||||||
|
method: "POST",
|
||||||
|
data: formData
|
||||||
|
}).then((res) => {
|
||||||
|
if (!res.access_token) {
|
||||||
|
setError("Введены некорректные данные для входа");
|
||||||
|
setModalError(true);
|
||||||
|
dispatch(loading(false));
|
||||||
|
} else {
|
||||||
|
localStorage.setItem("auth_token", res.access_token);
|
||||||
|
localStorage.setItem("id", res.id);
|
||||||
|
localStorage.setItem("cardId", res.card_id);
|
||||||
|
localStorage.setItem("role_status", res.status);
|
||||||
|
localStorage.setItem(
|
||||||
|
"access_token_expired_at",
|
||||||
|
res.access_token_expired_at
|
||||||
|
);
|
||||||
|
dispatch(auth(true));
|
||||||
|
dispatch(setUserInfo(res));
|
||||||
|
dispatch(loading(false));
|
||||||
|
dispatch(setRole("ROLE_PARTNER"));
|
||||||
|
navigate("/profile");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalLayout active={active} setActive={closeModal} styles={"auth"}>
|
||||||
|
<div className="auth-body__main">
|
||||||
|
<h2 className="auth-body__main-title">
|
||||||
|
Войти к <span>ITguild</span>
|
||||||
|
</h2>
|
||||||
|
<div className="input-body">
|
||||||
|
<div className="input-body__box">
|
||||||
|
<div className="input-container">
|
||||||
|
<h5>E-mail</h5>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={formData.email}
|
||||||
|
placeholder="Почта"
|
||||||
|
id="authEmail"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-body__box">
|
||||||
|
<div className="input-container">
|
||||||
|
<h5>Пароль</h5>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={formData.password}
|
||||||
|
placeholder="Пароль"
|
||||||
|
id="authPassword"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className="error">{modalError ? error : ""}</span>
|
||||||
|
<div className="button-box">
|
||||||
|
<BaseButton
|
||||||
|
onClick={async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
submitHandler(e);
|
||||||
|
}}
|
||||||
|
styles="button-box__submit"
|
||||||
|
>
|
||||||
|
{isLoading ? <Loader /> : "Войти"}
|
||||||
|
</BaseButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span onClick={() => closeModal()} className="exit"></span>
|
||||||
|
</ModalLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModalAuth;
|
136
src/components/Modal/ModalAuth/modalAuth.scss
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
.auth {
|
||||||
|
background: white;
|
||||||
|
padding: 40px 20px 40px 20px;
|
||||||
|
border: 1px solid #dde2e4;
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 70%;
|
||||||
|
max-width: 900px;
|
||||||
|
font-family: "LabGrotesque", sans-serif;
|
||||||
|
|
||||||
|
&-body {
|
||||||
|
&__main {
|
||||||
|
width: 80%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
row-gap: 20px;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 35px;
|
||||||
|
line-height: 32px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 703px) {
|
||||||
|
align-items: center;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #52b709;
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
@media (max-width: 703px) {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-body {
|
||||||
|
margin-top: 44px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@media (max-width: 703px) {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 47%;
|
||||||
|
|
||||||
|
@media (max-width: 703px) {
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin: 0 0 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 43px;
|
||||||
|
background: #eff2f7;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: none;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 18px;
|
||||||
|
font-style: normal;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-align: left;
|
||||||
|
padding: 16px 15px 16px 22px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-container {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
&__submit {
|
||||||
|
width: 174px;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 28px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #406128;
|
||||||
|
text-decoration: underline;
|
||||||
|
margin: 0 0 0 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
border: 1px solid #dde2e4;
|
border: 1px solid #dde2e4;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: 60%;
|
width: 60%;
|
||||||
|
font-family: "LabGrotesque", sans-serif;
|
||||||
|
|
||||||
@media (max-width: 1375px) {
|
@media (max-width: 1375px) {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
@ -110,7 +111,14 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: none;
|
border: none;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
padding-left: 20px;
|
font-size: 15px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 18px;
|
||||||
|
font-style: normal;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-align: left;
|
||||||
|
padding: 16px 15px 16px 22px;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-container {
|
.input-container {
|
||||||
|
@ -122,15 +122,6 @@ export const ModalTiсket = ({
|
|||||||
setShowModalToReport(!showModalToReport);
|
setShowModalToReport(!showModalToReport);
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeModal = () => {
|
|
||||||
setActive(false);
|
|
||||||
const currentUrl = window.location.pathname;
|
|
||||||
const newUrl = currentUrl.replace(/\/task\/\d+$/, "");
|
|
||||||
window.history.replaceState({}, "", newUrl);
|
|
||||||
document.body.style.overflow = "auto";
|
|
||||||
console.log(task);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [isExpanded, setIsExpanded] = useState(false);
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
const toggleModalSize = () => {
|
const toggleModalSize = () => {
|
||||||
@ -310,6 +301,17 @@ export const ModalTiсket = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
if (timerStart) {
|
||||||
|
stopTaskTimer();
|
||||||
|
}
|
||||||
|
setActive(false);
|
||||||
|
const currentUrl = window.location.pathname;
|
||||||
|
const newUrl = currentUrl.replace(/\/task\/\d+$/, "");
|
||||||
|
window.history.replaceState({}, "", newUrl);
|
||||||
|
document.body.style.overflow = "auto";
|
||||||
|
};
|
||||||
|
|
||||||
function taskExecutor(person) {
|
function taskExecutor(person) {
|
||||||
apiRequest("/task/update-task", {
|
apiRequest("/task/update-task", {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@ -380,97 +382,135 @@ export const ModalTiсket = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initListeners();
|
if (active) {
|
||||||
apiRequest(
|
setStartDate(task.dead_line ? new Date(task.dead_line) : new Date());
|
||||||
`/comment/get-by-entity?entity_type=2&entity_id=${task.id}`
|
setTaskPriority(task.execution_priority);
|
||||||
).then((res) => {
|
setMembers(task.taskUsers);
|
||||||
const comments = res.reduce((acc, cur) => {
|
setTaskTags(task.mark);
|
||||||
if (!cur.parent_id) {
|
setExecutorId(task.executor_id);
|
||||||
acc.push({ ...cur, subComments: [] });
|
setDeadLine(task.dead_line);
|
||||||
} else {
|
setExecutor(task.executor);
|
||||||
acc.forEach((item) => {
|
setInputsValue({
|
||||||
if (item.id === cur.parent_id) item.subComments.push(cur);
|
title: task.title,
|
||||||
});
|
description: task.description,
|
||||||
}
|
comment: ""
|
||||||
return acc;
|
});
|
||||||
}, []);
|
|
||||||
setComments(comments);
|
initListeners();
|
||||||
});
|
|
||||||
apiRequest(`/timer/get-by-entity?entity_type=2&entity_id=${task.id}`).then(
|
apiRequest(
|
||||||
(res) => {
|
`/comment/get-by-entity?entity_type=2&entity_id=${task.id}`
|
||||||
let timerSeconds = 0;
|
).then((res) => {
|
||||||
res.length &&
|
const comments = res.reduce((acc, cur) => {
|
||||||
res.forEach((time) => {
|
if (!cur.parent_id) {
|
||||||
timerSeconds += time.deltaSeconds;
|
acc.push({ ...cur, subComments: [] });
|
||||||
setCurrentTimerCount({
|
} else {
|
||||||
hours: Math.floor(timerSeconds / 60 / 60),
|
acc.forEach((item) => {
|
||||||
minute: Math.floor((timerSeconds / 60) % 60),
|
if (item.id === cur.parent_id) item.subComments.push(cur);
|
||||||
seconds: timerSeconds % 60
|
|
||||||
});
|
});
|
||||||
updateTimerHours = Math.floor(timerSeconds / 60 / 60);
|
}
|
||||||
updateTimerMinute = Math.floor((timerSeconds / 60) % 60);
|
return acc;
|
||||||
updateTimerSec = timerSeconds % 60;
|
}, []);
|
||||||
if (!time.stopped_at) {
|
setComments(comments);
|
||||||
setTimerStart(true);
|
});
|
||||||
startTimer();
|
|
||||||
setTimerInfo(time);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
apiRequest(`/file/get-by-entity?entity_type=2&entity_id=${task.id}`).then(
|
apiRequest(
|
||||||
(res) => {
|
`/timer/get-by-entity?entity_type=2&entity_id=${task.id}`
|
||||||
|
).then((res) => {
|
||||||
if (Array.isArray(res)) {
|
if (Array.isArray(res)) {
|
||||||
setTaskFiles(res);
|
let timerSeconds = 0;
|
||||||
}
|
res.length &&
|
||||||
}
|
res.forEach((time) => {
|
||||||
);
|
timerSeconds += time.deltaSeconds;
|
||||||
|
setCurrentTimerCount({
|
||||||
|
hours: Math.floor(timerSeconds / 60 / 60),
|
||||||
|
minute: Math.floor((timerSeconds / 60) % 60),
|
||||||
|
seconds: timerSeconds % 60
|
||||||
|
});
|
||||||
|
updateTimerHours = Math.floor(timerSeconds / 60 / 60);
|
||||||
|
updateTimerMinute = Math.floor((timerSeconds / 60) % 60);
|
||||||
|
updateTimerSec = timerSeconds % 60;
|
||||||
|
|
||||||
if (
|
if (!time.stopped_at) {
|
||||||
localStorage.getItem("role_status") !== "18" &&
|
setTimerStart(true);
|
||||||
Boolean(
|
startTimer();
|
||||||
|
setTimerInfo(time);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setCurrentTimerCount({
|
||||||
|
hours: 0,
|
||||||
|
minute: 0,
|
||||||
|
seconds: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
apiRequest(`/file/get-by-entity?entity_type=2&entity_id=${task.id}`).then(
|
||||||
|
(res) => {
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
setTaskFiles(res);
|
||||||
|
} else {
|
||||||
|
setTaskFiles([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
localStorage.getItem("role_status") !== "18" &&
|
||||||
|
Array.isArray(correctProjectUsers) &&
|
||||||
!correctProjectUsers.find(
|
!correctProjectUsers.find(
|
||||||
(item) => item.user_id === profileInfo.id_user
|
(item) => item.user_id === profileInfo.id_user
|
||||||
)
|
)
|
||||||
)
|
) {
|
||||||
) {
|
setCorrectProjectUsers((prevState) => [
|
||||||
setCorrectProjectUsers((prevState) => [
|
...prevState,
|
||||||
...prevState,
|
{
|
||||||
{
|
user: {
|
||||||
user: {
|
avatar: profileInfo.photo,
|
||||||
avatar: profileInfo.photo,
|
fio: profileInfo.fio
|
||||||
fio: profileInfo.fio
|
},
|
||||||
},
|
user_id: profileInfo.id_user
|
||||||
user_id: profileInfo.id_user
|
}
|
||||||
}
|
]);
|
||||||
]);
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, [active]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let tagIds = taskTags.map((tag) => tag.id);
|
if (Array.isArray(taskTags)) {
|
||||||
setCorrectProjectTags(
|
const tagIds = taskTags.map((tag) => tag.id);
|
||||||
projectMarks.reduce((acc, cur) => {
|
setCorrectProjectTags(
|
||||||
if (!tagIds.includes(cur.id)) acc.push(cur);
|
projectMarks.reduce((acc, cur) => {
|
||||||
return acc;
|
if (!tagIds.includes(cur.id)) acc.push(cur);
|
||||||
}, [])
|
return acc;
|
||||||
);
|
}, [])
|
||||||
|
);
|
||||||
|
}
|
||||||
}, [taskTags]);
|
}, [taskTags]);
|
||||||
|
|
||||||
async function handleUpload(event) {
|
async function handleUpload(event) {
|
||||||
const formData = new FormData();
|
try {
|
||||||
formData.append("uploadFile", event.target.files[0]);
|
const formData = new FormData();
|
||||||
const res = await fetch("https://itguild.info/api/file/upload", {
|
formData.append("uploadFile", event.target.files[0]);
|
||||||
method: "POST",
|
|
||||||
body: formData,
|
|
||||||
headers: { ...getToken() }
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await res.json();
|
const res = await fetch("https://itguild.info/api/file/upload", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
headers: { ...getToken() }
|
||||||
|
});
|
||||||
|
|
||||||
// setUploadedFile(data);
|
const data = await res.json();
|
||||||
attachFile(data[0].id);
|
|
||||||
|
// setUploadedFile(data);
|
||||||
|
attachFile(data[0].id);
|
||||||
|
} catch {
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Неверный формат файла",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function deleteLoadedFile() {
|
// function deleteLoadedFile() {
|
||||||
@ -512,7 +552,7 @@ export const ModalTiсket = ({
|
|||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
updateTimerSec++;
|
updateTimerSec++;
|
||||||
if (updateTimerSec > 60) {
|
if (updateTimerSec > 59) {
|
||||||
updateTimerMinute++;
|
updateTimerMinute++;
|
||||||
updateTimerSec = 0;
|
updateTimerSec = 0;
|
||||||
}
|
}
|
||||||
@ -530,17 +570,19 @@ export const ModalTiсket = ({
|
|||||||
|
|
||||||
function correctTimerTime(time) {
|
function correctTimerTime(time) {
|
||||||
if (time < 10) return `0${time}`;
|
if (time < 10) return `0${time}`;
|
||||||
if (time > 10) return time;
|
if (time >= 10) return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let ids = members.map((user) => user.user_id);
|
if (Array.isArray(members)) {
|
||||||
setUsers(
|
const ids = members.map((user) => user.user_id);
|
||||||
projectUsers.reduce((acc, cur) => {
|
setUsers(
|
||||||
if (!ids.includes(cur.user_id)) acc.push(cur);
|
projectUsers.reduce((acc, cur) => {
|
||||||
return acc;
|
if (!ids.includes(cur.user_id)) acc.push(cur);
|
||||||
}, [])
|
return acc;
|
||||||
);
|
}, [])
|
||||||
|
);
|
||||||
|
}
|
||||||
}, [members]);
|
}, [members]);
|
||||||
|
|
||||||
function copyTicketLink() {
|
function copyTicketLink() {
|
||||||
@ -684,6 +726,7 @@ export const ModalTiсket = ({
|
|||||||
editor={ClassicEditor}
|
editor={ClassicEditor}
|
||||||
data={inputsValue.description}
|
data={inputsValue.description}
|
||||||
config={{
|
config={{
|
||||||
|
toolbar: ["link"],
|
||||||
removePlugins: [
|
removePlugins: [
|
||||||
"CKFinderUploadAdapter",
|
"CKFinderUploadAdapter",
|
||||||
"CKFinder",
|
"CKFinder",
|
||||||
@ -695,7 +738,10 @@ export const ModalTiсket = ({
|
|||||||
"ImageUpload",
|
"ImageUpload",
|
||||||
"MediaEmbed",
|
"MediaEmbed",
|
||||||
"BlockQuote"
|
"BlockQuote"
|
||||||
]
|
],
|
||||||
|
link: {
|
||||||
|
addTargetToExternalLinks: true
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onChange={(event, editor) => {
|
onChange={(event, editor) => {
|
||||||
const data = editor.getData();
|
const data = editor.getData();
|
||||||
@ -713,7 +759,7 @@ export const ModalTiсket = ({
|
|||||||
)}
|
)}
|
||||||
{/*<img src={taskImg} className="image-task"></img>*/}
|
{/*<img src={taskImg} className="image-task"></img>*/}
|
||||||
</div>
|
</div>
|
||||||
{Boolean(taskFiles.length) && (
|
{Boolean(taskFiles?.length) && (
|
||||||
<div className="task__files">
|
<div className="task__files">
|
||||||
{taskFiles.map((file) => {
|
{taskFiles.map((file) => {
|
||||||
return (
|
return (
|
||||||
@ -763,7 +809,7 @@ export const ModalTiсket = ({
|
|||||||
name="file"
|
name="file"
|
||||||
id="input__file"
|
id="input__file"
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*,.png,.jpg,.svg,.jpeg"
|
accept="image/*,.png,.jpg,.svg,.jpeg,.doc,.docx,.xls,.xlsx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
className="input__file"
|
className="input__file"
|
||||||
onChange={handleUpload}
|
onChange={handleUpload}
|
||||||
/>
|
/>
|
||||||
@ -873,7 +919,7 @@ export const ModalTiсket = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{Boolean(members.length) && (
|
{Boolean(members?.length) && (
|
||||||
<div className="members">
|
<div className="members">
|
||||||
<h5>Участники:</h5>
|
<h5>Участники:</h5>
|
||||||
<div className="members__list">
|
<div className="members__list">
|
||||||
@ -1005,23 +1051,24 @@ export const ModalTiсket = ({
|
|||||||
<div className="workers_box-tag">
|
<div className="workers_box-tag">
|
||||||
<div className="tags">
|
<div className="tags">
|
||||||
<div className="tags__selected">
|
<div className="tags__selected">
|
||||||
{taskTags.map((tag) => {
|
{Array.isArray(taskTags) &&
|
||||||
return (
|
taskTags.map((tag) => {
|
||||||
<div
|
return (
|
||||||
className="tags__selected__item"
|
<div
|
||||||
key={tag.id}
|
className="tags__selected__item"
|
||||||
style={{ background: tag.color }}
|
key={tag.id}
|
||||||
>
|
style={{ background: tag.color }}
|
||||||
<p>{tag.slug}</p>
|
>
|
||||||
<img
|
<p>{tag.slug}</p>
|
||||||
src={crossWhite}
|
<img
|
||||||
className="delete"
|
src={crossWhite}
|
||||||
alt="delete"
|
className="delete"
|
||||||
onClick={() => deleteTagFromTask(tag.id)}
|
alt="delete"
|
||||||
/>
|
onClick={() => deleteTagFromTask(tag.id)}
|
||||||
</div>
|
/>
|
||||||
);
|
</div>
|
||||||
})}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="tags__select"
|
className="tags__select"
|
||||||
|
@ -30,10 +30,6 @@
|
|||||||
max-height: 700px;
|
max-height: 700px;
|
||||||
max-width: 915px;
|
max-width: 915px;
|
||||||
|
|
||||||
@media (max-width: 990px) {
|
|
||||||
width: 96%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 880px) {
|
@media (max-width: 880px) {
|
||||||
max-height: none;
|
max-height: none;
|
||||||
overflow-y: inherit;
|
overflow-y: inherit;
|
||||||
@ -590,10 +586,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 880px) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.members {
|
.members {
|
||||||
@ -613,6 +605,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
border-left: 1px solid #f1f1f1;
|
border-left: 1px solid #f1f1f1;
|
||||||
width: 32%;
|
width: 32%;
|
||||||
|
padding: 0 10px 10px 0;
|
||||||
|
|
||||||
.exit {
|
.exit {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -381,7 +381,7 @@ export const TicketFullScreen = () => {
|
|||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
updateTimerSec++;
|
updateTimerSec++;
|
||||||
if (updateTimerSec > 60) {
|
if (updateTimerSec > 59) {
|
||||||
updateTimerMinute++;
|
updateTimerMinute++;
|
||||||
updateTimerSec = 0;
|
updateTimerSec = 0;
|
||||||
}
|
}
|
||||||
@ -399,7 +399,7 @@ export const TicketFullScreen = () => {
|
|||||||
|
|
||||||
function correctTimerTime(time) {
|
function correctTimerTime(time) {
|
||||||
if (time < 10) return `0${time}`;
|
if (time < 10) return `0${time}`;
|
||||||
if (time > 10) return time;
|
if (time >= 10) return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteTaskExecutor() {
|
function deleteTaskExecutor() {
|
||||||
@ -479,17 +479,27 @@ export const TicketFullScreen = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleUpload(event) {
|
async function handleUpload(event) {
|
||||||
const formData = new FormData();
|
try {
|
||||||
formData.append("uploadFile", event.target.files[0]);
|
const formData = new FormData();
|
||||||
const res = await fetch("https://itguild.info/api/file/upload", {
|
formData.append("uploadFile", event.target.files[0]);
|
||||||
method: "POST",
|
|
||||||
body: formData,
|
|
||||||
headers: { ...getToken() }
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await res.json();
|
const res = await fetch("https://itguild.info/api/file/upload", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
headers: { ...getToken() }
|
||||||
|
});
|
||||||
|
|
||||||
setUploadedFile(data);
|
const data = await res.json();
|
||||||
|
|
||||||
|
// setUploadedFile(data);
|
||||||
|
attachFile(data[0].id);
|
||||||
|
} catch {
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Неверный формат файла",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function attachFile() {
|
function attachFile() {
|
||||||
@ -774,7 +784,7 @@ export const TicketFullScreen = () => {
|
|||||||
name="file"
|
name="file"
|
||||||
id="input__file"
|
id="input__file"
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*,.png,.jpg,.svg,.jpeg"
|
accept="image/*,.png,.jpg,.svg,.jpeg,.doc,.docx,.xls,.xlsx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
className="input__file"
|
className="input__file"
|
||||||
onChange={handleUpload}
|
onChange={handleUpload}
|
||||||
/>
|
/>
|
||||||
|
@ -331,6 +331,7 @@ export const TrackerModal = ({
|
|||||||
status: 19
|
status: 19
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
|
console.log(res);
|
||||||
if (!Array.isArray(res.name)) {
|
if (!Array.isArray(res.name)) {
|
||||||
const result = { ...res, columns: [] };
|
const result = { ...res, columns: [] };
|
||||||
dispatch(setProject(result));
|
dispatch(setProject(result));
|
||||||
@ -625,7 +626,10 @@ export const TrackerModal = ({
|
|||||||
"numberedList"
|
"numberedList"
|
||||||
],
|
],
|
||||||
removePlugins: ["BlockQuote"],
|
removePlugins: ["BlockQuote"],
|
||||||
placeholder: "Описание задачи"
|
placeholder: "Описание задачи",
|
||||||
|
link: {
|
||||||
|
addTargetToExternalLinks: true
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onChange={(event, editor) => {
|
onChange={(event, editor) => {
|
||||||
const data = editor.getData();
|
const data = editor.getData();
|
||||||
@ -840,7 +844,7 @@ export const TrackerModal = ({
|
|||||||
)}
|
)}
|
||||||
{modalType === "create-project" && (
|
{modalType === "create-project" && (
|
||||||
<div>
|
<div>
|
||||||
<div className="title-project">
|
<div className="title-project" style={{ minWidth: "350px" }}>
|
||||||
<h4>{titleProject}</h4>
|
<h4>{titleProject}</h4>
|
||||||
<div className="input-container">
|
<div className="input-container">
|
||||||
<input
|
<input
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 700px;
|
||||||
|
|
||||||
|
@media (max-width: 770px) {
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.select-priority {
|
.select-priority {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@ -338,8 +344,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.create-task-body {
|
.create-task-body {
|
||||||
|
width: 100%;
|
||||||
padding: 15px 30px;
|
padding: 15px 30px;
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: 55% 45%;
|
||||||
column-gap: 20px;
|
column-gap: 20px;
|
||||||
|
|
||||||
&__left {
|
&__left {
|
||||||
@ -356,7 +364,7 @@
|
|||||||
.input-container {
|
.input-container {
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
margin: 0 0 17px;
|
margin: 0 0 17px;
|
||||||
width: 393px;
|
width: 100%;
|
||||||
height: 47px;
|
height: 47px;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@ -407,10 +415,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.tags {
|
.tags {
|
||||||
&__selected {
|
&__selected {
|
||||||
width: 250px;
|
width: 100%;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@ -538,10 +547,10 @@
|
|||||||
|
|
||||||
.select__priority {
|
.select__priority {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
&__name {
|
&__name {
|
||||||
color: #000;
|
color: #000;
|
||||||
width: 250px;
|
|
||||||
height: 47px;
|
height: 47px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -589,7 +598,7 @@
|
|||||||
|
|
||||||
.select__executor {
|
.select__executor {
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
width: 250px;
|
width: 100%;
|
||||||
height: 47px;
|
height: 47px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
@ -223,7 +223,7 @@ export const ProfileCalendarComponent = React.memo(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="calendar-component__body">
|
<div className="calendar-component__body">
|
||||||
<div>
|
<div className="calendar-component__body__week-days">
|
||||||
<p>Понедельник</p>
|
<p>Понедельник</p>
|
||||||
<p>Вторник</p>
|
<p>Вторник</p>
|
||||||
<p>Среда</p>
|
<p>Среда</p>
|
||||||
@ -232,6 +232,15 @@ export const ProfileCalendarComponent = React.memo(
|
|||||||
<p>Суббота</p>
|
<p>Суббота</p>
|
||||||
<p>Воскресенье</p>
|
<p>Воскресенье</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="calendar-component__body__week-days-mobile">
|
||||||
|
<p>ПН</p>
|
||||||
|
<p>ВТ</p>
|
||||||
|
<p>СР</p>
|
||||||
|
<p>ЧТ</p>
|
||||||
|
<p>ПТ</p>
|
||||||
|
<p>СБ</p>
|
||||||
|
<p>ВС</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="calendar-component__form">
|
<div className="calendar-component__form">
|
||||||
{calendar.map((week) =>
|
{calendar.map((week) =>
|
||||||
|
@ -19,8 +19,17 @@
|
|||||||
.summary__info {
|
.summary__info {
|
||||||
padding-right: 25px;
|
padding-right: 25px;
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 760px) {
|
||||||
padding-right: 5px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
row-gap: 25px;
|
||||||
|
padding: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary__person {
|
||||||
|
margin: 0 10px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary__skill {
|
.summary__skill {
|
||||||
@ -32,6 +41,12 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 10px;
|
column-gap: 10px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
@media (max-width: 425px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
@ -63,8 +63,8 @@ export const ProjectTicket = ({ project, index }) => {
|
|||||||
dispatch(deleteProject(project));
|
dispatch(deleteProject(project));
|
||||||
showNotification({
|
showNotification({
|
||||||
show: true,
|
show: true,
|
||||||
text: "Проект успешно был перемещен в архив",
|
text: "Проект успешно удален",
|
||||||
type: "archive"
|
type: "success"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -62,10 +62,14 @@ export const SideBar = () => {
|
|||||||
<Link to={"/forms"}>Формы</Link>
|
<Link to={"/forms"}>Формы</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Школа</a>
|
<a href="#" target="_blank" rel="noopener noreferrer">
|
||||||
|
Школа
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Контакты</a>
|
<a href="#" target="_blank" rel="noopener noreferrer">
|
||||||
|
Контакты
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link to={"/blog"}>Блог</Link>
|
<Link to={"/blog"}>Блог</Link>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { forwardRef, useEffect, useState } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
import { movePositionProjectTask } from "@redux/projectsTrackerSlice";
|
import { movePositionProjectTask } from "@redux/projectsTrackerSlice";
|
||||||
@ -14,173 +14,183 @@ import avatarMok from "assets/images/avatarMok.webp";
|
|||||||
|
|
||||||
import "./trackerCardTask.scss";
|
import "./trackerCardTask.scss";
|
||||||
|
|
||||||
const TrackerCardTask = ({
|
const TrackerCardTask = forwardRef(
|
||||||
task,
|
(
|
||||||
projectBoard,
|
{
|
||||||
titleColor,
|
task,
|
||||||
column,
|
projectBoard,
|
||||||
openTicket,
|
titleColor,
|
||||||
startWrapperIndexTest,
|
column,
|
||||||
setWrapperHover
|
openTicket,
|
||||||
}) => {
|
startWrapperIndexTest,
|
||||||
const dispatch = useDispatch();
|
setWrapperHover
|
||||||
const [taskHover, setTaskHover] = useState({});
|
},
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [taskHover, setTaskHover] = useState({});
|
||||||
|
|
||||||
const priority = {
|
const priority = {
|
||||||
2: "Высокий",
|
2: "Высокий",
|
||||||
1: "Средний",
|
1: "Средний",
|
||||||
0: "Низкий"
|
0: "Низкий"
|
||||||
};
|
};
|
||||||
|
|
||||||
const priorityClass = {
|
const priorityClass = {
|
||||||
2: "high",
|
2: "high",
|
||||||
1: "middle",
|
1: "middle",
|
||||||
0: "low"
|
0: "low"
|
||||||
};
|
};
|
||||||
|
|
||||||
function dragDropTaskHandler(e, task, column) {
|
function dragDropTaskHandler(e, task, column) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (task.id === startWrapperIndexTest.current.task.id) {
|
if (task.id === startWrapperIndexTest.current.task.id) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const finishTask = column.tasks.indexOf(task);
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
movePositionProjectTask({
|
||||||
|
startTask: startWrapperIndexTest.current.task,
|
||||||
|
finishTask: task,
|
||||||
|
finishIndex: finishTask
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const finishTask = column.tasks.indexOf(task);
|
function dragOverTaskHandler(e, task) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (startWrapperIndexTest.current.task.id === task.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTaskHover((prevState) => ({ [prevState]: false, [task.id]: true }));
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(
|
function dragStartHandler(e, task, columnId) {
|
||||||
movePositionProjectTask({
|
startWrapperIndexTest.current = { task: task, index: columnId };
|
||||||
startTask: startWrapperIndexTest.current.task,
|
}
|
||||||
finishTask: task,
|
|
||||||
finishIndex: finishTask
|
function dragLeaveTaskHandler() {
|
||||||
})
|
setTaskHover((prevState) => ({ [prevState]: false }));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragEndTaskHandler() {
|
||||||
|
setTaskHover((prevState) => ({ [prevState]: false }));
|
||||||
|
setWrapperHover((prevState) => ({
|
||||||
|
[prevState]: false
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const tasksHover = {};
|
||||||
|
const columnHover = {};
|
||||||
|
|
||||||
|
if (Object.keys(projectBoard).length) {
|
||||||
|
projectBoard.columns.forEach((column) => {
|
||||||
|
columnHover[column.id] = false;
|
||||||
|
column.tasks.forEach((task) => (tasksHover[task.id] = false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setWrapperHover(columnHover);
|
||||||
|
setTaskHover(tasksHover);
|
||||||
|
}, [projectBoard]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
key={task.id}
|
||||||
|
className={`tasks__board__item ${
|
||||||
|
taskHover[task.id] ? "task__hover" : ""
|
||||||
|
}`}
|
||||||
|
draggable={true}
|
||||||
|
onDragStart={(e) => dragStartHandler(e, task, column.id)}
|
||||||
|
onDragOver={(e) => dragOverTaskHandler(e, task)}
|
||||||
|
onDragLeave={(e) => dragLeaveTaskHandler(e)}
|
||||||
|
onDragEnd={() => dragEndTaskHandler()}
|
||||||
|
onDrop={(e) => dragDropTaskHandler(e, task, column)}
|
||||||
|
onClick={() => openTicket(task)}
|
||||||
|
>
|
||||||
|
<div className="tasks__board__item__title">
|
||||||
|
<p className="task__board__item__title">{task.title}</p>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: task.description
|
||||||
|
}}
|
||||||
|
className="tasks__board__item__description"
|
||||||
|
></p>
|
||||||
|
{Boolean(task.mark.length) && (
|
||||||
|
<div className="tasks__board__item__tags">
|
||||||
|
{task.mark.map((tag) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="tag-item"
|
||||||
|
key={tag.id}
|
||||||
|
style={{ background: tag.color }}
|
||||||
|
>
|
||||||
|
<p>{tag.slug}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="tasks__board__item__container">
|
||||||
|
{typeof task.execution_priority === "number" && (
|
||||||
|
<div className="tasks__board__item__priority">
|
||||||
|
<p>⚡</p>
|
||||||
|
<span className={priorityClass[task.execution_priority]}>
|
||||||
|
{priority[task.execution_priority]}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{task.dead_line && (
|
||||||
|
<div className="tasks__board__item__dead-line">
|
||||||
|
<p>⌛</p>
|
||||||
|
<span style={{ color: titleColor }}>
|
||||||
|
{getCorrectDate(task.dead_line)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="tasks__board__item__info">
|
||||||
|
<div className="tasks__board__item__executor">
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
task.executor?.avatar
|
||||||
|
? urlForLocal(task.executor?.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt="avatar"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
{removeLast(task.executor?.fio) || "Исполнитель не назначен"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="tasks__board__item__info__tags">
|
||||||
|
<div className="tasks__board__item__info__more">
|
||||||
|
<img src={commentsBoard} alt="commentsImg" />
|
||||||
|
<span>{task.comment_count}</span>
|
||||||
|
</div>
|
||||||
|
<div className="tasks__board__item__info__more">
|
||||||
|
<img src={filesBoard} alt="filesImg" />
|
||||||
|
<span>{task.file_count}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TrackerSelectColumn
|
||||||
|
columns={projectBoard.columns.filter((item) => item.id !== column.id)}
|
||||||
|
currentColumn={column}
|
||||||
|
task={task}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function dragOverTaskHandler(e, task) {
|
TrackerCardTask.displayName = "TrackerCardTask";
|
||||||
e.preventDefault();
|
|
||||||
if (startWrapperIndexTest.current.task.id === task.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setTaskHover((prevState) => ({ [prevState]: false, [task.id]: true }));
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragStartHandler(e, task, columnId) {
|
|
||||||
startWrapperIndexTest.current = { task: task, index: columnId };
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragLeaveTaskHandler() {
|
|
||||||
setTaskHover((prevState) => ({ [prevState]: false }));
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragEndTaskHandler() {
|
|
||||||
setTaskHover((prevState) => ({ [prevState]: false }));
|
|
||||||
setWrapperHover((prevState) => ({
|
|
||||||
[prevState]: false
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const tasksHover = {};
|
|
||||||
const columnHover = {};
|
|
||||||
|
|
||||||
if (Object.keys(projectBoard).length) {
|
|
||||||
projectBoard.columns.forEach((column) => {
|
|
||||||
columnHover[column.id] = false;
|
|
||||||
column.tasks.forEach((task) => (tasksHover[task.id] = false));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setWrapperHover(columnHover);
|
|
||||||
setTaskHover(tasksHover);
|
|
||||||
}, [projectBoard]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={task.id}
|
|
||||||
className={`tasks__board__item ${
|
|
||||||
taskHover[task.id] ? "task__hover" : ""
|
|
||||||
}`}
|
|
||||||
draggable={true}
|
|
||||||
onDragStart={(e) => dragStartHandler(e, task, column.id)}
|
|
||||||
onDragOver={(e) => dragOverTaskHandler(e, task)}
|
|
||||||
onDragLeave={(e) => dragLeaveTaskHandler(e)}
|
|
||||||
onDragEnd={() => dragEndTaskHandler()}
|
|
||||||
onDrop={(e) => dragDropTaskHandler(e, task, column)}
|
|
||||||
onClick={(e) => openTicket(e, task)}
|
|
||||||
>
|
|
||||||
<div className="tasks__board__item__title">
|
|
||||||
<p className="task__board__item__title">{task.title}</p>
|
|
||||||
</div>
|
|
||||||
<p
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: task.description
|
|
||||||
}}
|
|
||||||
className="tasks__board__item__description"
|
|
||||||
></p>
|
|
||||||
{Boolean(task.mark.length) && (
|
|
||||||
<div className="tasks__board__item__tags">
|
|
||||||
{task.mark.map((tag) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="tag-item"
|
|
||||||
key={tag.id}
|
|
||||||
style={{ background: tag.color }}
|
|
||||||
>
|
|
||||||
<p>{tag.slug}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="tasks__board__item__container">
|
|
||||||
{typeof task.execution_priority === "number" && (
|
|
||||||
<div className="tasks__board__item__priority">
|
|
||||||
<p>⚡</p>
|
|
||||||
<span className={priorityClass[task.execution_priority]}>
|
|
||||||
{priority[task.execution_priority]}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{task.dead_line && (
|
|
||||||
<div className="tasks__board__item__dead-line">
|
|
||||||
<p>⌛</p>
|
|
||||||
<span style={{ color: titleColor }}>
|
|
||||||
{getCorrectDate(task.dead_line)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="tasks__board__item__info">
|
|
||||||
<div className="tasks__board__item__executor">
|
|
||||||
<img
|
|
||||||
src={
|
|
||||||
task.executor?.avatar
|
|
||||||
? urlForLocal(task.executor?.avatar)
|
|
||||||
: avatarMok
|
|
||||||
}
|
|
||||||
alt="avatar"
|
|
||||||
/>
|
|
||||||
<span>
|
|
||||||
{removeLast(task.executor?.fio) || "Исполнитель не назначен"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="tasks__board__item__info__tags">
|
|
||||||
<div className="tasks__board__item__info__more">
|
|
||||||
<img src={commentsBoard} alt="commentsImg" />
|
|
||||||
<span>{task.comment_count}</span>
|
|
||||||
</div>
|
|
||||||
<div className="tasks__board__item__info__more">
|
|
||||||
<img src={filesBoard} alt="filesImg" />
|
|
||||||
<span>{task.file_count}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<TrackerSelectColumn
|
|
||||||
columns={projectBoard.columns.filter((item) => item.id !== column.id)}
|
|
||||||
currentColumn={column}
|
|
||||||
task={task}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TrackerCardTask;
|
export default TrackerCardTask;
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
row-gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 3px;
|
width: 3px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@ -61,7 +65,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: 0px 3px 2px -2px rgba(0, 0, 0, 0.06),
|
box-shadow: 0px 3px 2px -2px rgba(0, 0, 0, 0.06),
|
||||||
0px 5px 3px -2px rgba(0, 0, 0, 0.02);
|
0px 5px 3px -2px rgba(0, 0, 0, 0.02);
|
||||||
border-radius: 6px;
|
border-radius: 6px 6px 0 0;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -76,6 +80,7 @@
|
|||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 6px 10px 5px 10px;
|
||||||
max-height: none;
|
max-height: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
|
background: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 10px 0;
|
margin: 0 0 15px 0;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 2px 6px;
|
padding: 0 6px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid #e3e2e2;
|
border-top: 1px solid #e3e2e2;
|
||||||
border-radius: 8px;
|
border-radius: 0 0 6px 6px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
@ -121,6 +121,7 @@ export const TrackerTaskComment = ({
|
|||||||
editor={ClassicEditor}
|
editor={ClassicEditor}
|
||||||
data={commentsEditText}
|
data={commentsEditText}
|
||||||
config={{
|
config={{
|
||||||
|
toolbar: ["link"],
|
||||||
removePlugins: [
|
removePlugins: [
|
||||||
"CKFinderUploadAdapter",
|
"CKFinderUploadAdapter",
|
||||||
"CKFinder",
|
"CKFinder",
|
||||||
@ -132,7 +133,10 @@ export const TrackerTaskComment = ({
|
|||||||
"ImageUpload",
|
"ImageUpload",
|
||||||
"MediaEmbed",
|
"MediaEmbed",
|
||||||
"BlockQuote"
|
"BlockQuote"
|
||||||
]
|
],
|
||||||
|
link: {
|
||||||
|
addTargetToExternalLinks: true
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onChange={(event, editor) => {
|
onChange={(event, editor) => {
|
||||||
const data = editor.getData();
|
const data = editor.getData();
|
||||||
|
@ -90,7 +90,11 @@ export const FormPage = () => {
|
|||||||
Заявка на собеседование через телеграм
|
Заявка на собеседование через телеграм
|
||||||
</div>
|
</div>
|
||||||
<div className="form-page__telegram-icon">
|
<div className="form-page__telegram-icon">
|
||||||
<a href="https://t.me/st0kir" target="_blank" rel="noreferrer">
|
<a
|
||||||
|
href="https://t.me/st0kir"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
<SVG src={telegramIcon} />
|
<SVG src={telegramIcon} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,6 +5,7 @@ import { Link, NavLink } from "react-router-dom";
|
|||||||
import { BurgerButton } from "@components/BurgerMenu/burgerButton";
|
import { BurgerButton } from "@components/BurgerMenu/burgerButton";
|
||||||
import { BurgerMenu } from "@components/BurgerMenu/burgerMenu";
|
import { BurgerMenu } from "@components/BurgerMenu/burgerMenu";
|
||||||
import { Footer } from "@components/Common/Footer/Footer";
|
import { Footer } from "@components/Common/Footer/Footer";
|
||||||
|
import ModalAuth from "@components/Modal/ModalAuth/ModalAuth";
|
||||||
import ModalRegistration from "@components/Modal/ModalRegistration/ModalRegistration";
|
import ModalRegistration from "@components/Modal/ModalRegistration/ModalRegistration";
|
||||||
|
|
||||||
import arrow from "assets/icons/arrows/arrowLanding.svg";
|
import arrow from "assets/icons/arrows/arrowLanding.svg";
|
||||||
@ -13,11 +14,16 @@ import clue from "assets/icons/landingClue.svg";
|
|||||||
import tracker from "assets/icons/landingTracker.svg";
|
import tracker from "assets/icons/landingTracker.svg";
|
||||||
import codeBg from "assets/images/landing/backgroundCode.webp";
|
import codeBg from "assets/images/landing/backgroundCode.webp";
|
||||||
import cat from "assets/images/landing/landingCat.webp";
|
import cat from "assets/images/landing/landingCat.webp";
|
||||||
|
import reportingSystem from "assets/images/landing/reportingSystem.webp";
|
||||||
|
import searchIT from "assets/images/landing/searchIT.webp";
|
||||||
|
import systemControlGit from "assets/images/landing/systemControlGit.webp";
|
||||||
|
import taskManagement from "assets/images/landing/taskManagement.webp";
|
||||||
|
|
||||||
import "./landing.scss";
|
import "./landing.scss";
|
||||||
|
|
||||||
export const Landing = () => {
|
export const Landing = () => {
|
||||||
const [modalReg, setModalReg] = useState(false);
|
const [modalReg, setModalReg] = useState(false);
|
||||||
|
const [modalAuth, setModalAuth] = useState(false);
|
||||||
const [menuActive, setMenuActive] = useState(false);
|
const [menuActive, setMenuActive] = useState(false);
|
||||||
|
|
||||||
const opportunities = [
|
const opportunities = [
|
||||||
@ -29,22 +35,22 @@ export const Landing = () => {
|
|||||||
{
|
{
|
||||||
name: "<span>Найти</span> работу <br/> в IT",
|
name: "<span>Найти</span> работу <br/> в IT",
|
||||||
path: "/stack",
|
path: "/stack",
|
||||||
img: cat
|
img: searchIT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<span>Система</span> контроля версий GIT",
|
name: "<span>Система</span> контроля версий GIT",
|
||||||
path: "/stack",
|
path: "/stack",
|
||||||
img: cat
|
img: systemControlGit
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<span>Управление</span> задачами",
|
name: "<span>Управление</span> задачами",
|
||||||
path: "/landing-tracker",
|
path: "/landing-tracker",
|
||||||
img: cat
|
img: taskManagement
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<span>Система</span> для отчётности",
|
name: "<span>Система</span> для отчётности",
|
||||||
path: "/stack",
|
path: "/stack",
|
||||||
img: cat
|
img: reportingSystem
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Все наши предложения",
|
name: "Все наши предложения",
|
||||||
@ -57,14 +63,20 @@ export const Landing = () => {
|
|||||||
return (
|
return (
|
||||||
<section className="landing">
|
<section className="landing">
|
||||||
<ModalRegistration active={modalReg} setActive={setModalReg} />
|
<ModalRegistration active={modalReg} setActive={setModalReg} />
|
||||||
|
<ModalAuth active={modalAuth} setActive={setModalAuth} />
|
||||||
<BurgerMenu active={menuActive} />
|
<BurgerMenu active={menuActive} />
|
||||||
<div className="landing__container">
|
<div className="landing__container">
|
||||||
<div className="landing__head">
|
<div className="landing__head">
|
||||||
<h2 className="head__logo">ITGUILD</h2>
|
<h2 className="head__logo">ITGUILD</h2>
|
||||||
<Link className="head__signIn" to="/auth">
|
<div
|
||||||
|
className="head__signIn"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setModalAuth(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
войти в систему
|
войти в систему
|
||||||
</Link>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="head__signUp"
|
className="head__signUp"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -76,12 +88,12 @@ export const Landing = () => {
|
|||||||
регистрация
|
регистрация
|
||||||
</div>
|
</div>
|
||||||
<BurgerButton active={menuActive} setActive={setMenuActive} />
|
<BurgerButton active={menuActive} setActive={setMenuActive} />
|
||||||
<div className="head__tracker">
|
<Link className="head__tracker" to="/tracker-intro">
|
||||||
<div>
|
<div>
|
||||||
<img src={tracker} alt="tracker" />
|
<img src={tracker} alt="tracker" />
|
||||||
</div>
|
</div>
|
||||||
<span>трекер</span>
|
<span>трекер</span>
|
||||||
</div>
|
</Link>
|
||||||
<SVG className="head__auth" src={authIcon} />
|
<SVG className="head__auth" src={authIcon} />
|
||||||
</div>
|
</div>
|
||||||
<div className="landing__info">
|
<div className="landing__info">
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Link, NavLink } from "react-router-dom";
|
import { Link, NavLink } from "react-router-dom";
|
||||||
|
|
||||||
|
import { AuthHeader } from "@components/Common/AuthHeader/AuthHeader";
|
||||||
import { Footer } from "@components/Common/Footer/Footer";
|
import { Footer } from "@components/Common/Footer/Footer";
|
||||||
|
|
||||||
import arrow from "assets/icons/arrows/arrowLanding.svg";
|
import arrow from "assets/icons/arrows/arrowLanding.svg";
|
||||||
@ -12,6 +13,11 @@ import ellipseGreen from "assets/images/landingTracker/ellipseGreen.svg";
|
|||||||
import cat from "assets/images/landingTracker/landingCat.webp";
|
import cat from "assets/images/landingTracker/landingCat.webp";
|
||||||
import flag from "assets/images/landingTracker/projectsFlag.webp";
|
import flag from "assets/images/landingTracker/projectsFlag.webp";
|
||||||
import questionMark from "assets/images/landingTracker/questionMark.svg";
|
import questionMark from "assets/images/landingTracker/questionMark.svg";
|
||||||
|
import reportingSystem from "assets/images/landingTracker/reportingSystem.webp";
|
||||||
|
import searchIT from "assets/images/landingTracker/searchIT.webp";
|
||||||
|
import systemControlGit from "assets/images/landingTracker/systemControlGit.webp";
|
||||||
|
import target from "assets/images/landingTracker/target.webp";
|
||||||
|
import taskManagement from "assets/images/landingTracker/taskManagement.webp";
|
||||||
import trackerCup from "assets/images/landingTracker/trackerCup.webp";
|
import trackerCup from "assets/images/landingTracker/trackerCup.webp";
|
||||||
import trackerPreview from "assets/images/landingTracker/trackerPreview.webp";
|
import trackerPreview from "assets/images/landingTracker/trackerPreview.webp";
|
||||||
import trackerSign from "assets/images/landingTracker/trackerSign.webp";
|
import trackerSign from "assets/images/landingTracker/trackerSign.webp";
|
||||||
@ -21,20 +27,20 @@ import "./LandingTracker.scss";
|
|||||||
export const LandingTracker = () => {
|
export const LandingTracker = () => {
|
||||||
const goals = [
|
const goals = [
|
||||||
{
|
{
|
||||||
miniInfo: "Окунитесь в экосистему ITGUIL",
|
miniInfo: "Простота использования",
|
||||||
info: "<span>уточнение</span> деталей и <span>обсуждение</span> условий с менеджером ITGUILD"
|
info: "<span>интуитивно понятный интерфейс</span> делает работу с нашим сервисом легкой и приятной"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
miniInfo: "Окунитесь в экосистему ITGUIL",
|
miniInfo: "Гибкость и адаптивность",
|
||||||
info: "<span>подписание договора</span> без обязательств оплаты на данном этапе"
|
info: "мы предлогаем <span>инструменты, которые подойдут</span> именно вашему проекту"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
miniInfo: "Окунитесь в экосистему ITGUIL",
|
miniInfo: "Совместная работа без границ",
|
||||||
info: "<span>формирование</span> команды или подбор отдельных специалистов под требования клиентов"
|
info: "сотрудничайте, общайтесь и делитесь ресурсами <span>в реальном времени, в любой точке мира</span>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
miniInfo: "Окунитесь в экосистему ITGUIL",
|
miniInfo: "Безопасность и надежность",
|
||||||
info: "<span>интеграция специалистов</span> в команду клиента, ежедневная отчетность под контролем менеджера ITGUILD"
|
info: "постоянный мониторинг системы <span>позволяет обеспечивать безопасность</span> ваших данных"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -47,22 +53,22 @@ export const LandingTracker = () => {
|
|||||||
{
|
{
|
||||||
name: "<span>Найти</span> работу <br/> в IT",
|
name: "<span>Найти</span> работу <br/> в IT",
|
||||||
path: "/stack",
|
path: "/stack",
|
||||||
img: cat
|
img: searchIT
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<span>Система</span> контроля <br/> версий GIT",
|
name: "<span>Система</span> контроля <br/> версий GIT",
|
||||||
path: "/stack",
|
path: "/stack",
|
||||||
img: cat
|
img: systemControlGit
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<span>Управление</span> <br/> задачами",
|
name: "<span>Управление</span> <br/> задачами",
|
||||||
path: "/landing-tracker",
|
path: "/landing-tracker",
|
||||||
img: cat
|
img: taskManagement
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "<span>Система</span> для <br/> отчётности",
|
name: "<span>Система</span> для <br/> отчётности",
|
||||||
path: "/stack",
|
path: "/stack",
|
||||||
img: cat
|
img: reportingSystem
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Все наши <br/> предложения",
|
name: "Все наши <br/> предложения",
|
||||||
@ -74,6 +80,7 @@ export const LandingTracker = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="tracker">
|
<section className="tracker">
|
||||||
|
<AuthHeader />
|
||||||
<section className="tracker__intro">
|
<section className="tracker__intro">
|
||||||
<img className="intro__question-mark" src={questionMark} alt="" />
|
<img className="intro__question-mark" src={questionMark} alt="" />
|
||||||
<img className="intro__code" src={code} alt="" />
|
<img className="intro__code" src={code} alt="" />
|
||||||
@ -120,7 +127,7 @@ export const LandingTracker = () => {
|
|||||||
<Link to="/auth">войти</Link>
|
<Link to="/auth">войти</Link>
|
||||||
</button>
|
</button>
|
||||||
<button className="signUp">
|
<button className="signUp">
|
||||||
<Link to="/auth">регистрация</Link>
|
<Link to="/auth">авторизация</Link>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="presentation__tracker-preview">
|
<div className="presentation__tracker-preview">
|
||||||
@ -173,9 +180,9 @@ export const LandingTracker = () => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="steps__portfolio">
|
<div className="goals__target">
|
||||||
<img src={portfolio} alt="portfolio" />
|
<img src={target} alt="target" />
|
||||||
</div> */}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -195,7 +202,7 @@ export const LandingTracker = () => {
|
|||||||
<Link to="/auth">войти</Link>
|
<Link to="/auth">войти</Link>
|
||||||
</button>
|
</button>
|
||||||
<button className="signUp">
|
<button className="signUp">
|
||||||
<Link to="/auth">регистрация</Link>
|
<Link to="/auth">авторизация</Link>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -205,6 +212,14 @@ export const LandingTracker = () => {
|
|||||||
</h3>
|
</h3>
|
||||||
<img className="invite__logo__sign" src={trackerSign} alt="" />
|
<img className="invite__logo__sign" src={trackerSign} alt="" />
|
||||||
<img className="invite__logo__ellipse" src={ellipseGreen} alt="" />
|
<img className="invite__logo__ellipse" src={ellipseGreen} alt="" />
|
||||||
|
<div className="invite-auth__buttons">
|
||||||
|
<button className="signUp-modile">
|
||||||
|
<Link to="/auth">авторизация</Link>
|
||||||
|
</button>
|
||||||
|
<button className="signIn-modile">
|
||||||
|
<Link to="/auth">войти</Link>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,6 +1,31 @@
|
|||||||
.tracker {
|
.tracker {
|
||||||
font-family: "GT Eesti Pro Display";
|
font-family: "GT Eesti Pro Display";
|
||||||
|
|
||||||
|
// section:not(:nth-child(2)):not(:nth-child(3)):not(:nth-child(4)):not(
|
||||||
|
// :nth-child(5)
|
||||||
|
// ):not(:nth-child(6)) {
|
||||||
|
// display: none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.auth-header {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: flex;
|
||||||
|
background-color: #a7ca60;
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger__line {
|
||||||
|
background-color: #4a4a4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth__buttons {
|
||||||
|
.signIn {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
// padding: 85px 0 90px;
|
// padding: 85px 0 90px;
|
||||||
@ -12,22 +37,39 @@
|
|||||||
background-color: #a7ca60;
|
background-color: #a7ca60;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
height: 485px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.intro {
|
.intro {
|
||||||
&__question-mark {
|
&__question-mark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 15%;
|
right: 15%;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__code {
|
&__code {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
mix-blend-mode: plus-lighter;
|
mix-blend-mode: plus-lighter;
|
||||||
bottom: 96px;
|
bottom: 96px;
|
||||||
left: 16%;
|
left: 16%;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__code--top {
|
&__code--top {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
mix-blend-mode: plus-lighter;
|
mix-blend-mode: plus-lighter;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
left: 38%;
|
left: 38%;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
@ -37,6 +79,9 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
align-items: center;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +96,10 @@
|
|||||||
font-size: 343px;
|
font-size: 343px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 325.92px;
|
line-height: 325.92px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cup {
|
&__cup {
|
||||||
@ -58,6 +107,17 @@
|
|||||||
bottom: -85px;
|
bottom: -85px;
|
||||||
right: -150px;
|
right: -150px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
position: static;
|
||||||
|
margin: -90px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
height: 350px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: "Не нужно заваривать мышь";
|
content: "Не нужно заваривать мышь";
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -82,6 +142,12 @@
|
|||||||
line-height: 19.72px;
|
line-height: 19.72px;
|
||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
width: 125px;
|
||||||
|
height: 106px;
|
||||||
|
left: 170px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,9 +158,17 @@
|
|||||||
color: #607536;
|
color: #607536;
|
||||||
max-width: 455px;
|
max-width: 455px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
margin: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
&__sublogo {
|
&__sublogo {
|
||||||
margin-top: 37px;
|
margin-top: 37px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
font-size: 29px;
|
font-size: 29px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
@ -122,6 +196,13 @@
|
|||||||
line-height: 37.29px;
|
line-height: 37.29px;
|
||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
margin: 101px 0 34px 0;
|
margin: 101px 0 34px 0;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 29px;
|
||||||
|
line-height: 32.77px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 21px 0 26px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@ -129,6 +210,12 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 37.29px;
|
line-height: 37.29px;
|
||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 28.25px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,12 +231,20 @@
|
|||||||
mix-blend-mode: plus-lighter;
|
mix-blend-mode: plus-lighter;
|
||||||
bottom: 225px;
|
bottom: 225px;
|
||||||
right: 18%;
|
right: 18%;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__code--top {
|
&__code--top {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
mix-blend-mode: plus-lighter;
|
mix-blend-mode: plus-lighter;
|
||||||
top: 60px;
|
top: 60px;
|
||||||
left: 25%;
|
left: 25%;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&__ellipse {
|
&__ellipse {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -158,6 +253,10 @@
|
|||||||
top: -90px;
|
top: -90px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%);
|
transform: translate(-50%);
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
@ -170,6 +269,7 @@
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
|
height: 660px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
@ -178,6 +278,13 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 38.28px;
|
line-height: 38.28px;
|
||||||
margin-top: 95px;
|
margin-top: 95px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 22.04px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 37px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
@ -187,6 +294,13 @@
|
|||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
line-height: 119.48px;
|
line-height: 119.48px;
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 50px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 58px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@ -198,6 +312,13 @@
|
|||||||
max-width: 609px;
|
max-width: 609px;
|
||||||
margin-bottom: 52px;
|
margin-bottom: 52px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 17.4px;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 370px;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@ -208,6 +329,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
column-gap: 29px;
|
column-gap: 29px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
column-gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 185px;
|
width: 185px;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
@ -238,6 +363,13 @@
|
|||||||
margin-top: 61px;
|
margin-top: 61px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
margin-top: 37px;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 315px;
|
||||||
|
left: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
.tracker-preview {
|
.tracker-preview {
|
||||||
&__buttons {
|
&__buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -278,12 +410,24 @@
|
|||||||
left: 21%;
|
left: 21%;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
width: 255px;
|
||||||
|
height: 102px;
|
||||||
|
left: -22.26px;
|
||||||
|
border-radius: 24px 0px 44px 0px;
|
||||||
|
padding: 25px 0 0 60px;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
line-height: 28.34px;
|
line-height: 28.34px;
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
max-width: 174px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@ -291,6 +435,10 @@
|
|||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
line-height: 19.65px;
|
line-height: 19.65px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,6 +455,10 @@
|
|||||||
bottom: -96px;
|
bottom: -96px;
|
||||||
left: 7%;
|
left: 7%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
@ -315,6 +467,11 @@
|
|||||||
height: 720px;
|
height: 720px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
height: 1020px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-head {
|
&-head {
|
||||||
@ -333,6 +490,13 @@
|
|||||||
filter: drop-shadow(7px 0px 10px rgba(0, 0, 0, 0.1294117647));
|
filter: drop-shadow(7px 0px 10px rgba(0, 0, 0, 0.1294117647));
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 110px;
|
||||||
|
line-height: 110px;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__info {
|
&__info {
|
||||||
@ -345,6 +509,11 @@
|
|||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
color: #eeeeee;
|
color: #eeeeee;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
bottom: -55px;
|
||||||
|
max-width: 372px;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@ -358,9 +527,10 @@
|
|||||||
column-gap: 48px;
|
column-gap: 48px;
|
||||||
|
|
||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
flex-direction: column;
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
row-gap: 86px;
|
row-gap: 86px;
|
||||||
margin-top: 65px;
|
margin-top: 95px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@ -369,9 +539,17 @@
|
|||||||
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
margin-right: 41px;
|
margin-right: 41px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&:nth-child(3) {
|
&:nth-child(3) {
|
||||||
margin-left: 41px;
|
margin-left: 41px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,8 +575,9 @@
|
|||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
|
|
||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
font-size: 14px;
|
font-size: 12px;
|
||||||
max-width: 124px;
|
font-weight: 700;
|
||||||
|
max-width: 107px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,8 +603,8 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
width: 324px;
|
width: 200px;
|
||||||
height: 153px;
|
height: 205px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@ -446,6 +625,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__target {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,15 +650,33 @@
|
|||||||
height: 582px;
|
height: 582px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
column-gap: 133px;
|
column-gap: 133px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
height: auto;
|
||||||
|
padding-top: 35px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__info {
|
&__info {
|
||||||
max-width: 541px;
|
max-width: 541px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
max-width: 377px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
color: #607536;
|
color: #607536;
|
||||||
font-size: 44px;
|
font-size: 44px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 51.04px;
|
line-height: 51.04px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 29px;
|
||||||
|
line-height: 33.64px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@ -484,6 +686,10 @@
|
|||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
line-height: 19.72px;
|
line-height: 19.72px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
margin: 30px 0 22px 0;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@ -494,6 +700,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
column-gap: 29px;
|
column-gap: 29px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 185px;
|
width: 185px;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
@ -509,6 +720,18 @@
|
|||||||
}
|
}
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-modile {
|
||||||
|
a {
|
||||||
|
color: #607536;
|
||||||
|
}
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.signUp {
|
.signUp {
|
||||||
@ -517,6 +740,18 @@
|
|||||||
}
|
}
|
||||||
border: 1px solid #ffffff;
|
border: 1px solid #ffffff;
|
||||||
background: none;
|
background: none;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-modile {
|
||||||
|
a {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
border: 1px solid #ffffff;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,6 +761,12 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
flex-direction: row;
|
||||||
|
padding-left: 18px;
|
||||||
|
column-gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-family: "Geraspoheko";
|
font-family: "Geraspoheko";
|
||||||
@ -534,6 +775,13 @@
|
|||||||
line-height: 325.92px;
|
line-height: 325.92px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 140px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 140px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__sign {
|
&__sign {
|
||||||
@ -541,6 +789,12 @@
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
left: -180px;
|
left: -180px;
|
||||||
top: 70px;
|
top: 70px;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
width: 90px;
|
||||||
|
left: -40px;
|
||||||
|
top: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__ellipse {
|
&__ellipse {
|
||||||
@ -548,6 +802,11 @@
|
|||||||
width: 463px;
|
width: 463px;
|
||||||
height: 563px;
|
height: 563px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,6 +830,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
height: 1170px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__project {
|
&__project {
|
||||||
@ -582,6 +845,15 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid #f8f8f8;
|
border: 1px solid #f8f8f8;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
align-items: normal;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 32px;
|
||||||
|
height: 266px;
|
||||||
|
max-width: 397px;
|
||||||
|
padding: 32px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
.project__img {
|
.project__img {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: 99px;
|
width: 99px;
|
||||||
@ -620,6 +892,11 @@
|
|||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 42px 0 77px 0;
|
margin: 42px 0 77px 0;
|
||||||
|
|
||||||
|
@media (max-width: 431px) {
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 22.04px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__opportunities {
|
&__opportunities {
|
||||||
@ -649,6 +926,8 @@
|
|||||||
@media (max-width: 431px) {
|
@media (max-width: 431px) {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -663,6 +942,7 @@
|
|||||||
border: 0.5px solid #ffffff;
|
border: 0.5px solid #ffffff;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
height: 221px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,13 +92,13 @@ export const PartnerEmployeeReport = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="employee-report__info">
|
<div className="employee-report__info">
|
||||||
<div className="employee-report__name">
|
<div className="employee-report__name">
|
||||||
<h2>{userInfo.fio}</h2>
|
<h2>{userInfo?.userCard.fio}</h2>
|
||||||
<p>{userInfo.position}</p>
|
<p>{userInfo?.userCard.position.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="employee-report__skills">
|
<div className="employee-report__skills">
|
||||||
{userInfo?.stack &&
|
{userInfo?.userCard?.skillValues &&
|
||||||
userInfo.stack.map((skill, index) => {
|
userInfo?.userCard?.skillValues.map((skill) => {
|
||||||
return <span key={index}>{skill}</span>;
|
return <span key={skill.id}>{skill.skill.name}</span>;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { apiRequest } from "@api/request";
|
import { apiRequest } from "@api/request";
|
||||||
|
|
||||||
@ -11,6 +11,7 @@ import { Navigation } from "@components/Navigation/Navigation";
|
|||||||
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
|
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
|
||||||
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
|
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
|
||||||
|
|
||||||
|
import tgSettingsIcon from "assets/icons/tgSettingsIcon.svg";
|
||||||
import astral from "assets/images/logo/astralLogo.png";
|
import astral from "assets/images/logo/astralLogo.png";
|
||||||
import kontur from "assets/images/logo/konturLogo.png";
|
import kontur from "assets/images/logo/konturLogo.png";
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ import "./partnerSettings.scss";
|
|||||||
|
|
||||||
export const PartnerSettings = () => {
|
export const PartnerSettings = () => {
|
||||||
const { showNotification } = useNotification();
|
const { showNotification } = useNotification();
|
||||||
|
const [tgToken, setTgToken] = useState();
|
||||||
const [inputsValue, setInputsValue] = useState({
|
const [inputsValue, setInputsValue] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
oldPassword: "",
|
oldPassword: "",
|
||||||
@ -30,6 +32,15 @@ export const PartnerSettings = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [loader, setLoader] = useState(false);
|
const [loader, setLoader] = useState(false);
|
||||||
|
const [tgLoader, setTgLoader] = useState(false);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// apiRequest("/user-tg-bot/get-token", {
|
||||||
|
// method: "GET"
|
||||||
|
// }).then((data) => {
|
||||||
|
// setTgToken(data.token);
|
||||||
|
// });
|
||||||
|
// }, []);
|
||||||
|
|
||||||
const setSettings = () => {
|
const setSettings = () => {
|
||||||
if (inputsValue.name.length < 2) {
|
if (inputsValue.name.length < 2) {
|
||||||
@ -80,6 +91,49 @@ export const PartnerSettings = () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleGenerate = async () => {
|
||||||
|
if (tgToken == undefined) {
|
||||||
|
setTgLoader(true);
|
||||||
|
apiRequest("/user-tg-bot/get-token", {
|
||||||
|
method: "GET"
|
||||||
|
}).then((data) => {
|
||||||
|
setTgToken(data.token);
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Телеграм токен успешно сгенерирован",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
setTgLoader(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCopy = async () => {
|
||||||
|
if (tgToken !== undefined) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(tgToken);
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Телеграм токен успешно скопирован",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Ошибка копирования",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Необходимо сгенерировать код",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="settings">
|
<div className="settings">
|
||||||
<ProfileHeader />
|
<ProfileHeader />
|
||||||
@ -183,6 +237,40 @@ export const PartnerSettings = () => {
|
|||||||
использования персональных данных
|
использования персональных данных
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="partner-settings__report">
|
||||||
|
<h3 className="settings__title">Телеграмм бот</h3>
|
||||||
|
|
||||||
|
<p className="settings__label">Тelegram токен</p>
|
||||||
|
<div className="settings__input">
|
||||||
|
<span>{tgToken}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="settings__buttons">
|
||||||
|
{tgLoader ? (
|
||||||
|
<Loader style={"green"} width={"40px"} height={"40px"} />
|
||||||
|
) : (
|
||||||
|
<BaseButton
|
||||||
|
onClick={handleGenerate}
|
||||||
|
styles={"settings__buttons-save"}
|
||||||
|
>
|
||||||
|
Сгенерировать
|
||||||
|
</BaseButton>
|
||||||
|
)}
|
||||||
|
<BaseButton
|
||||||
|
onClick={handleCopy}
|
||||||
|
styles={"settings__buttons-save"}
|
||||||
|
>
|
||||||
|
Скопировать
|
||||||
|
</BaseButton>
|
||||||
|
</div>
|
||||||
|
<div className="settings__agreement-tg">
|
||||||
|
<a href="#" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src={tgSettingsIcon} alt="" />
|
||||||
|
</a>
|
||||||
|
Ссылка на телеграм бот с инструкцией
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{/* <div className="partner-settings__report">
|
{/* <div className="partner-settings__report">
|
||||||
<h3 className="settings__title">Документы и отчеты</h3>
|
<h3 className="settings__title">Документы и отчеты</h3>
|
||||||
<p className="settings__label">Изменить провадера ЭДО</p>
|
<p className="settings__label">Изменить провадера ЭДО</p>
|
||||||
|
@ -29,13 +29,14 @@
|
|||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
margin: 15px 0 10px 0;
|
margin: 30px 0 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__input {
|
&__input {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
row-gap: 5px;
|
row-gap: 5px;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
background: #eff2f7;
|
background: #eff2f7;
|
||||||
@ -46,6 +47,16 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #eff2f7;
|
||||||
|
border-radius: 8px;
|
||||||
|
height: 35px;
|
||||||
|
border: none;
|
||||||
|
font-size: 15px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
color: red;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -65,14 +76,25 @@
|
|||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
|
||||||
|
&-tg {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 18px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__buttons {
|
&__buttons {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: space-around;
|
||||||
gap: 20px;
|
|
||||||
margin: 30px 0 20px;
|
margin: 30px 0 20px;
|
||||||
|
|
||||||
&-cancel,
|
&-cancel,
|
||||||
@ -107,21 +129,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 440px) {
|
||||||
&__input {
|
|
||||||
width: 95%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__buttons {
|
&__buttons {
|
||||||
margin: 15px 0 14px 0;
|
flex-direction: column;
|
||||||
width: 100%;
|
gap: 10px;
|
||||||
flex-direction: column-reverse;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0px;
|
|
||||||
|
|
||||||
&-save {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,6 +152,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
|
column-gap: 40px;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__report,
|
&__report,
|
||||||
|
@ -6,7 +6,6 @@ import { useTheme } from "@table-library/react-table-library/theme";
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link, Navigate } from "react-router-dom";
|
import { Link, Navigate } from "react-router-dom";
|
||||||
|
|
||||||
import { LEVELS, SKILLS } from "@utils/constants";
|
|
||||||
import { urlForLocal } from "@utils/helper";
|
import { urlForLocal } from "@utils/helper";
|
||||||
|
|
||||||
import { apiRequest } from "@api/request";
|
import { apiRequest } from "@api/request";
|
||||||
@ -18,26 +17,12 @@ import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadc
|
|||||||
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
|
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
|
||||||
|
|
||||||
import rightArrow from "assets/icons/arrows/arrowRight.svg";
|
import rightArrow from "assets/icons/arrows/arrowRight.svg";
|
||||||
|
import folder from "assets/icons/folder.svg";
|
||||||
import report from "assets/icons/report.svg";
|
import report from "assets/icons/report.svg";
|
||||||
|
|
||||||
// import PartnerPersonCard from "@components/PartnerPersonCard/PartnerPersonCard";
|
|
||||||
// import { useDispatch } from "react-redux";
|
|
||||||
// import { setPartnerEmployees } from "@redux/outstaffingSlice";
|
|
||||||
// import rightArrow from "assets/icons/arrows/arrowRight.svg";
|
|
||||||
// import avatarImg from "assets/images/avatarMok.png";
|
|
||||||
// import AdminImg from "assets/images/partnerProfile/PersonalAdmin.svg";
|
|
||||||
// import ArchitectureImg from "assets/images/partnerProfile/PersonalArchitecture.svg";
|
|
||||||
// import CopyImg from "assets/images/partnerProfile/PersonalCopy.svg";
|
|
||||||
// import DesignImg from "assets/images/partnerProfile/PersonalDesign.svg";
|
|
||||||
// import FrontendImg from "assets/images/partnerProfile/PersonalFrontend.svg";
|
|
||||||
// import ManageImg from "assets/images/partnerProfile/PersonalMng.svg";
|
|
||||||
// import SmmImg from "assets/images/partnerProfile/PersonalSMM.svg";
|
|
||||||
// import TestImg from "assets/images/partnerProfile/PersonalTesters.svg";
|
|
||||||
// import BackEndImg from "assets/images/partnerProfile/personalBackEnd.svg";
|
|
||||||
import "./partnerСategories.scss";
|
import "./partnerСategories.scss";
|
||||||
|
|
||||||
export const PartnerCategories = () => {
|
export const PartnerCategories = () => {
|
||||||
// const dispatch = useDispatch();
|
|
||||||
if (localStorage.getItem("role_status") !== "18") {
|
if (localStorage.getItem("role_status") !== "18") {
|
||||||
return <Navigate to="/profile" replace />;
|
return <Navigate to="/profile" replace />;
|
||||||
}
|
}
|
||||||
@ -46,7 +31,7 @@ export const PartnerCategories = () => {
|
|||||||
const theme = useTheme(getTheme());
|
const theme = useTheme(getTheme());
|
||||||
const [nodes, setNodes] = useState([]);
|
const [nodes, setNodes] = useState([]);
|
||||||
const [initialNodes, setInitialNodes] = useState([]);
|
const [initialNodes, setInitialNodes] = useState([]);
|
||||||
const [activeTab, setActiveTab] = useState("Все");
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
|
|
||||||
@ -65,32 +50,39 @@ export const PartnerCategories = () => {
|
|||||||
{
|
{
|
||||||
label: "",
|
label: "",
|
||||||
renderCell: (item) => (
|
renderCell: (item) => (
|
||||||
<img
|
<Link to={`/profile/summary/${item.user_id}`}>
|
||||||
className="table__avatar"
|
<img
|
||||||
src={urlForLocal(item?.employee.avatar)}
|
className="table__avatar"
|
||||||
alt="avatar"
|
src={urlForLocal(item?.employee.avatar)}
|
||||||
/>
|
alt="avatar"
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Данные",
|
label: "Данные",
|
||||||
renderCell: (item) => (
|
renderCell: (item) => (
|
||||||
<div className="table__info">
|
<Link className="table__info" to={`/profile/summary/${item.user_id}`}>
|
||||||
<p>{item?.employee.fio}</p>
|
<p>{item?.employee.fio}</p>
|
||||||
<span>
|
<span>
|
||||||
{LEVELS[item?.resume.userCard.level]} /{" "}
|
{item?.employee.level_title} / {item?.employee.position.name}
|
||||||
{SKILLS[item?.resume.userCard.position_id]}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</Link>
|
||||||
)
|
)
|
||||||
// sort: { sortKey: "NAME" }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Участвует в проекте",
|
label: "Участвует в проекте",
|
||||||
renderCell: (item) => (
|
renderCell: (item) => (
|
||||||
<div className="table__project">
|
<div className="table__project">
|
||||||
{item.resume.userCard.at_project ? (
|
{item?.employee.projects.length ? (
|
||||||
<div>item.resume.userCard.at_project</div>
|
item.employee.projects.map((project) => {
|
||||||
|
return (
|
||||||
|
<div className="table__project__item" key={project.id}>
|
||||||
|
<img src={folder} alt="folder" />{" "}
|
||||||
|
<p>{project.project.name}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
) : (
|
) : (
|
||||||
<span>Нет проектов</span>
|
<span>Нет проектов</span>
|
||||||
)}
|
)}
|
||||||
@ -143,23 +135,9 @@ export const PartnerCategories = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoader(true);
|
setLoader(true);
|
||||||
apiRequest("/project/my-employee").then((el) => {
|
apiRequest("/project/my-employee").then((el) => {
|
||||||
const fetchResumes = async () => {
|
setNodes(el.managerEmployees);
|
||||||
const promises = el.managerEmployees.map(async (manager) => {
|
setInitialNodes(el.managerEmployees);
|
||||||
const resume = await apiRequest(`/resume?userId=${manager.user_id}`);
|
setLoader(false);
|
||||||
return { ...manager, resume }; // Возвращаем объект с добавленным ключом resume
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const updatedManagers = await Promise.all(promises);
|
|
||||||
setInitialNodes(updatedManagers);
|
|
||||||
setNodes(updatedManagers);
|
|
||||||
setLoader(false);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка при получении резюме:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchResumes();
|
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -178,108 +156,6 @@ export const PartnerCategories = () => {
|
|||||||
console.log(action, state);
|
console.log(action, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const [personalInfoItems] = useState([
|
|
||||||
// {
|
|
||||||
// title: "Backend разработчики",
|
|
||||||
// link: "/profile/categories/employees",
|
|
||||||
// description:
|
|
||||||
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
|
|
||||||
// available: true,
|
|
||||||
// img: BackEndImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Frontend разработчики",
|
|
||||||
// link: "/profile/categories/employees",
|
|
||||||
// description:
|
|
||||||
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
|
|
||||||
// available: true,
|
|
||||||
// img: FrontendImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Архитектура проектов",
|
|
||||||
// link: "/profile/categories/employees",
|
|
||||||
// description: "Потоки данных ER ERP CRM CQRS UML BPMN",
|
|
||||||
// available: true,
|
|
||||||
// img: ArchitectureImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Дизайн проектов",
|
|
||||||
// link: "/profile/categories/employees",
|
|
||||||
// description:
|
|
||||||
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
|
|
||||||
// available: true,
|
|
||||||
// img: DesignImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Тестирование проектов",
|
|
||||||
// link: "/profile/add-request",
|
|
||||||
// description: "SQL Postman TestRail Kibana Ручное тестирование",
|
|
||||||
// available: false,
|
|
||||||
// img: TestImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Администрирование проектов",
|
|
||||||
// link: "/profile/add-request",
|
|
||||||
// description: "DevOps ELK Kubernetes Docker Bash Apache Oracle Git",
|
|
||||||
// available: false,
|
|
||||||
// img: AdminImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Управление проектом",
|
|
||||||
// link: "/profile/add-request",
|
|
||||||
// description: "Scrum Kanban Agile Miro CustDev",
|
|
||||||
// available: false,
|
|
||||||
// img: ManageImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Копирайтинг проектов",
|
|
||||||
// link: "/profile/add-request",
|
|
||||||
// description: "Теги Заголовок H1 Дескриптор Абзац Сценарий",
|
|
||||||
// available: false,
|
|
||||||
// img: CopyImg
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Реклама и SMM",
|
|
||||||
// link: "/profile/add-request",
|
|
||||||
// description:
|
|
||||||
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript",
|
|
||||||
// available: false,
|
|
||||||
// img: SmmImg
|
|
||||||
// }
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// const [mokPersons] = useState([
|
|
||||||
// {
|
|
||||||
// personAvatar: avatarImg,
|
|
||||||
// name: "Макаренко Дмитрий",
|
|
||||||
// qualification: "PHP Backend - разработчик",
|
|
||||||
// level: "Middle",
|
|
||||||
// project: "Админка НВД Консалтинг",
|
|
||||||
// tasks_in_progress: 5,
|
|
||||||
// month_hours: 140,
|
|
||||||
// id: 1
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// personAvatar: avatarImg,
|
|
||||||
// name: "Макаренко Дмитрий",
|
|
||||||
// qualification: "PHP Backend - разработчик",
|
|
||||||
// level: "Middle",
|
|
||||||
// project: "Админка НВД Консалтинг",
|
|
||||||
// tasks_in_progress: 5,
|
|
||||||
// month_hours: 140,
|
|
||||||
// id: 2
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// personAvatar: avatarImg,
|
|
||||||
// name: "Макаренко Дмитрий",
|
|
||||||
// qualification: "PHP Backend - разработчик",
|
|
||||||
// level: "Middle",
|
|
||||||
// project: "Админка НВД Консалтинг",
|
|
||||||
// tasks_in_progress: 5,
|
|
||||||
// month_hours: 140,
|
|
||||||
// id: 3
|
|
||||||
// }
|
|
||||||
// ]);
|
|
||||||
return (
|
return (
|
||||||
<div className="partner-categories">
|
<div className="partner-categories">
|
||||||
<ProfileHeader />
|
<ProfileHeader />
|
||||||
@ -311,11 +187,11 @@ export const PartnerCategories = () => {
|
|||||||
<div className="table__tabs">
|
<div className="table__tabs">
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveTab("Все");
|
setActiveTab(0);
|
||||||
setNodes(initialNodes);
|
setNodes(initialNodes);
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
activeTab === "Все"
|
activeTab === 0
|
||||||
? "table__tab table__tab--active"
|
? "table__tab table__tab--active"
|
||||||
: "table__tab"
|
: "table__tab"
|
||||||
}
|
}
|
||||||
@ -329,8 +205,7 @@ export const PartnerCategories = () => {
|
|||||||
setActiveTab(tab.name);
|
setActiveTab(tab.name);
|
||||||
setNodes(
|
setNodes(
|
||||||
initialNodes.filter(
|
initialNodes.filter(
|
||||||
(item) =>
|
(item) => item.employee.position.id === tab.value
|
||||||
item.resume.userCard.position_id === tab.value
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@ -353,54 +228,61 @@ export const PartnerCategories = () => {
|
|||||||
sort={sort}
|
sort={sort}
|
||||||
pagination={pagination}
|
pagination={pagination}
|
||||||
/>
|
/>
|
||||||
<div className="table__pagination">
|
{Boolean(nodes.length) &&
|
||||||
<button
|
pagination.state.getPages(data.nodes).length > 1 && (
|
||||||
className={
|
<div className="table__pagination">
|
||||||
pagination.state.page === 0 ? "switch disable" : "switch"
|
|
||||||
}
|
|
||||||
type="button"
|
|
||||||
disabled={pagination.state.page === 0}
|
|
||||||
onClick={() =>
|
|
||||||
pagination.fns.onSetPage(pagination.state.page - 1)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{"<"}
|
|
||||||
</button>
|
|
||||||
<span className="table__pages">
|
|
||||||
{pagination.state.getPages(data.nodes).map((_, index) => (
|
|
||||||
<button
|
<button
|
||||||
key={index}
|
|
||||||
type="button"
|
|
||||||
className={
|
className={
|
||||||
pagination.state.page === index
|
pagination.state.page === 0
|
||||||
? "page page--active "
|
? "switch disable"
|
||||||
: "page"
|
: "switch"
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
disabled={pagination.state.page === 0}
|
||||||
|
onClick={() =>
|
||||||
|
pagination.fns.onSetPage(pagination.state.page - 1)
|
||||||
}
|
}
|
||||||
onClick={() => pagination.fns.onSetPage(index)}
|
|
||||||
>
|
>
|
||||||
{index + 1}
|
{"<"}
|
||||||
</button>
|
</button>
|
||||||
))}
|
<span className="table__pages">
|
||||||
</span>
|
{pagination.state
|
||||||
<button
|
.getPages(data.nodes)
|
||||||
className={
|
.map((_, index) => (
|
||||||
pagination.state.page + 1 ===
|
<button
|
||||||
pagination.state.getPages(data.nodes).length
|
key={index}
|
||||||
? "switch disable"
|
type="button"
|
||||||
: "switch"
|
className={
|
||||||
}
|
pagination.state.page === index
|
||||||
type="button"
|
? "page page--active "
|
||||||
disabled={
|
: "page"
|
||||||
pagination.state.page + 1 ===
|
}
|
||||||
pagination.state.getPages(data.nodes).length
|
onClick={() => pagination.fns.onSetPage(index)}
|
||||||
}
|
>
|
||||||
onClick={() =>
|
{index + 1}
|
||||||
pagination.fns.onSetPage(pagination.state.page + 1)
|
</button>
|
||||||
}
|
))}
|
||||||
>
|
</span>
|
||||||
{">"}
|
<button
|
||||||
</button>
|
className={
|
||||||
</div>
|
pagination.state.page + 1 ===
|
||||||
|
pagination.state.getPages(data.nodes).length
|
||||||
|
? "switch disable"
|
||||||
|
: "switch"
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
disabled={
|
||||||
|
pagination.state.page + 1 ===
|
||||||
|
pagination.state.getPages(data.nodes).length
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
pagination.fns.onSetPage(pagination.state.page + 1)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="partner-categories__empty">
|
<div className="partner-categories__empty">
|
||||||
@ -411,39 +293,6 @@ export const PartnerCategories = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/*{personalInfoItems.map((item, index) => {*/}
|
|
||||||
{/* return (*/}
|
|
||||||
{/* <Link*/}
|
|
||||||
{/* to={item.link}*/}
|
|
||||||
{/* key={index}*/}
|
|
||||||
{/* className={*/}
|
|
||||||
{/* item.available*/}
|
|
||||||
{/* ? "partner-categories__item item"*/}
|
|
||||||
{/* : "partner-categories__item item item__disable"*/}
|
|
||||||
{/* }*/}
|
|
||||||
{/* onClick={() => {*/}
|
|
||||||
{/* dispatch(setPartnerEmployees(mokPersons));*/}
|
|
||||||
{/* }}*/}
|
|
||||||
{/* >*/}
|
|
||||||
{/* <div className="item__title">*/}
|
|
||||||
{/* <img src={item.img} alt={item.title} />*/}
|
|
||||||
{/* <h4>{item.title}</h4>*/}
|
|
||||||
{/* </div>*/}
|
|
||||||
{/* <div className="item__info">*/}
|
|
||||||
{/* <p>{item.description}</p>*/}
|
|
||||||
{/* <div className="more">*/}
|
|
||||||
{/* <img src={rightArrow} alt="arrow" />*/}
|
|
||||||
{/* </div>*/}
|
|
||||||
{/* </div>*/}
|
|
||||||
{/* {!item.available && (*/}
|
|
||||||
{/* <div className="item__disable-hover">*/}
|
|
||||||
{/* <p>У вас нет персонала из категории</p>*/}
|
|
||||||
{/* <button>Подобрать</button>*/}
|
|
||||||
{/* </div>*/}
|
|
||||||
{/* )}*/}
|
|
||||||
{/* </Link>*/}
|
|
||||||
{/* );*/}
|
|
||||||
{/*})}*/}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -255,6 +255,26 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 17.5px;
|
line-height: 17.5px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 11px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 8px;
|
||||||
|
color: rgba(46, 58, 89, 1);
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid rgba(237, 237, 237, 1);
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
max-width: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__action {
|
&__action {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useLocation, useParams } from "react-router-dom";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
activeLoader,
|
activeLoader,
|
||||||
@ -51,6 +51,9 @@ import avatarMok from "assets/images/avatarMok.webp";
|
|||||||
export const ProjectTracker = () => {
|
export const ProjectTracker = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const projectId = useParams();
|
const projectId = useParams();
|
||||||
|
const taskParams = useParams();
|
||||||
|
const taskRefs = useRef([]);
|
||||||
|
const hasRunEffect = useRef(false);
|
||||||
|
|
||||||
const [openColumnSelect, setOpenColumnSelect] = useState({});
|
const [openColumnSelect, setOpenColumnSelect] = useState({});
|
||||||
const [selectedTab, setSelectedTab] = useState(0);
|
const [selectedTab, setSelectedTab] = useState(0);
|
||||||
@ -78,6 +81,19 @@ export const ProjectTracker = () => {
|
|||||||
initListeners();
|
initListeners();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (projectBoard.columns && taskParams.taskId && !hasRunEffect.current) {
|
||||||
|
for (const column of projectBoard.columns) {
|
||||||
|
const task = column.tasks.find((task) => task.id == taskParams.taskId);
|
||||||
|
if (task) {
|
||||||
|
openTicket(task);
|
||||||
|
hasRunEffect.current = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [projectBoard]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let columnsTasksEmpty = true;
|
let columnsTasksEmpty = true;
|
||||||
if (Object.keys(projectBoard).length) {
|
if (Object.keys(projectBoard).length) {
|
||||||
@ -145,21 +161,32 @@ export const ProjectTracker = () => {
|
|||||||
setPriorityTask(length);
|
setPriorityTask(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
function openTicket(e, task) {
|
const updateUrlWithTaskId = (taskId) => {
|
||||||
|
const currentUrl = window.location.pathname;
|
||||||
|
const taskUrlSegment = `/task/`;
|
||||||
|
|
||||||
|
if (currentUrl.includes(taskUrlSegment)) {
|
||||||
|
// Если URL содержит '/task/', заменяем старый ID на новый
|
||||||
|
const baseUrl = currentUrl.substring(
|
||||||
|
0,
|
||||||
|
currentUrl.indexOf(taskUrlSegment) + taskUrlSegment.length
|
||||||
|
);
|
||||||
|
const newUrl = `${baseUrl}${taskId}`;
|
||||||
|
window.history.pushState({}, "", newUrl);
|
||||||
|
} else {
|
||||||
|
// Если URL не содержит '/task/', добавляем '/task/${taskId}'
|
||||||
|
const newUrl = `${currentUrl}${taskUrlSegment}${taskId}`;
|
||||||
|
window.history.pushState({}, "", newUrl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function openTicket(task) {
|
||||||
setSelectedTicket(task);
|
setSelectedTicket(task);
|
||||||
setModalActiveTicket(true);
|
setModalActiveTicket(true);
|
||||||
const currentUrl = window.location.pathname;
|
updateUrlWithTaskId(task.id);
|
||||||
const newUrl = `${currentUrl}/task/${task.id}`;
|
|
||||||
window.history.pushState({}, "", newUrl);
|
|
||||||
document.body.style.overflow = "hidden";
|
document.body.style.overflow = "hidden";
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const currentUrl = window.location.pathname;
|
|
||||||
const newUrl = currentUrl.replace(/\/task\/\d+$/, "");
|
|
||||||
window.history.replaceState({}, "", newUrl);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function deleteColumn(column) {
|
function deleteColumn(column) {
|
||||||
const priorityColumns = [];
|
const priorityColumns = [];
|
||||||
apiRequest("/project-column/update-column", {
|
apiRequest("/project-column/update-column", {
|
||||||
@ -421,19 +448,16 @@ export const ProjectTracker = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ModalTicket
|
||||||
{Boolean(modalActiveTicket) && (
|
active={modalActiveTicket}
|
||||||
<ModalTicket
|
setActive={setModalActiveTicket}
|
||||||
active={modalActiveTicket}
|
task={selectedTicket}
|
||||||
setActive={setModalActiveTicket}
|
projectId={projectBoard.id}
|
||||||
task={selectedTicket}
|
projectName={projectBoard.name}
|
||||||
projectId={projectBoard.id}
|
projectUsers={projectBoard.projectUsers}
|
||||||
projectName={projectBoard.name}
|
projectOwnerId={projectBoard.owner_id}
|
||||||
projectUsers={projectBoard.projectUsers}
|
projectMarks={projectBoard.mark}
|
||||||
projectOwnerId={projectBoard.owner_id}
|
/>
|
||||||
projectMarks={projectBoard.mark}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="tasks__container">
|
<div className="tasks__container">
|
||||||
{Boolean(projectBoard?.columns) &&
|
{Boolean(projectBoard?.columns) &&
|
||||||
@ -535,6 +559,9 @@ export const ProjectTracker = () => {
|
|||||||
startWrapperIndexTest={startWrapperIndexTest}
|
startWrapperIndexTest={startWrapperIndexTest}
|
||||||
task={task}
|
task={task}
|
||||||
titleColor={titleColor}
|
titleColor={titleColor}
|
||||||
|
ref={(el) => {
|
||||||
|
taskRefs.current[task.id] = el;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -648,9 +648,15 @@ export const Stack = () => {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
<p>
|
<p>
|
||||||
Соглашаюсь с <a href="">Пользовательским соглашением</a> и
|
Соглашаюсь с{" "}
|
||||||
|
<a href="" target="_blank" rel="noopener noreferrer">
|
||||||
|
Пользовательским соглашением
|
||||||
|
</a>{" "}
|
||||||
|
и
|
||||||
<br />
|
<br />
|
||||||
<a href="">Политикой обработки данных</a>
|
<a href="" target="_blank" rel="noopener noreferrer">
|
||||||
|
Политикой обработки данных
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ const Statistics = () => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {}, [projectInfo]);
|
||||||
|
|
||||||
const teams = [
|
const teams = [
|
||||||
{
|
{
|
||||||
avatar: mockAvatar,
|
avatar: mockAvatar,
|
||||||
@ -121,7 +123,7 @@ const Statistics = () => {
|
|||||||
<img src={link} alt="#" />
|
<img src={link} alt="#" />
|
||||||
<span
|
<span
|
||||||
className="return-text"
|
className="return-text"
|
||||||
onClick={() => copyProjectLink("62")}
|
onClick={() => copyProjectLink(projectInfo.id)}
|
||||||
>
|
>
|
||||||
ссылка на проект
|
ссылка на проект
|
||||||
</span>
|
</span>
|
||||||
@ -190,38 +192,36 @@ const Statistics = () => {
|
|||||||
<div className="list-team__body">
|
<div className="list-team__body">
|
||||||
{projectStatistic?.participants.map((person, index) => {
|
{projectStatistic?.participants.map((person, index) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="list-team__item" key={index}>
|
||||||
<div className="list-team__item" key={index}>
|
<div className="person-name">
|
||||||
<div className="person-name">
|
<img
|
||||||
<img
|
src={
|
||||||
src={
|
person.avatar
|
||||||
person.avatar
|
? urlForLocal(person.avatar)
|
||||||
? urlForLocal(person.avatar)
|
: mockAvatar
|
||||||
: mockAvatar
|
|
||||||
}
|
|
||||||
alt="avatar"
|
|
||||||
/>
|
|
||||||
<p>{person.username}</p>
|
|
||||||
</div>
|
|
||||||
<div className="person-email">
|
|
||||||
<img src={emailImg} alt="#" />
|
|
||||||
<p>{person.email}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p className="person-type">
|
|
||||||
{person.role ? person.role : "-"}
|
|
||||||
</p>
|
|
||||||
<span
|
|
||||||
className={
|
|
||||||
person.status
|
|
||||||
? "status status-active"
|
|
||||||
: "status status-none"
|
|
||||||
}
|
}
|
||||||
>
|
alt="avatar"
|
||||||
{person.status ? "Активно" : "Не активно"}
|
/>
|
||||||
</span>
|
<p>{person.username}</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
<div className="person-email">
|
||||||
|
<img src={emailImg} alt="#" />
|
||||||
|
<p>{person.email}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="person-type">
|
||||||
|
{person.role ? person.role : "-"}
|
||||||
|
</p>
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
person.status
|
||||||
|
? "status status-active"
|
||||||
|
: "status status-none"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{person.status ? "Активно" : "Не активно"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 15px 0 0 0;
|
margin: 15px 0 0 0;
|
||||||
|
padding: 0 20px;
|
||||||
|
|
||||||
&__return {
|
&__return {
|
||||||
img {
|
img {
|
||||||
@ -106,6 +107,7 @@
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
padding-left: 31px;
|
padding-left: 31px;
|
||||||
|
margin: 0 10px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: #5b6871;
|
color: #5b6871;
|
||||||
|
@ -2,7 +2,7 @@ import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
|||||||
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { Navigate } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { getProfileInfo } from "@redux/outstaffingSlice";
|
import { getProfileInfo } from "@redux/outstaffingSlice";
|
||||||
|
|
||||||
@ -27,19 +27,18 @@ import avatarMok from "assets/images/avatarMok.webp";
|
|||||||
import "./summary.scss";
|
import "./summary.scss";
|
||||||
|
|
||||||
export const Summary = () => {
|
export const Summary = () => {
|
||||||
if (localStorage.getItem("role_status") === "18") {
|
|
||||||
return <Navigate to="/profile" replace />;
|
|
||||||
}
|
|
||||||
const profileInfo = useSelector(getProfileInfo);
|
const profileInfo = useSelector(getProfileInfo);
|
||||||
const [openGit, setOpenGit] = useState(false);
|
const [openGit, setOpenGit] = useState(false);
|
||||||
const [gitInfo, setGitInfo] = useState([]);
|
const [gitInfo, setGitInfo] = useState([]);
|
||||||
const [editSummaryOpen, setEditSummaryOpen] = useState(false);
|
const [editSummaryOpen, setEditSummaryOpen] = useState(false);
|
||||||
const [editSkills, setEditSkills] = useState(false);
|
const [editSkills, setEditSkills] = useState(false);
|
||||||
|
const [userInfo, setUserInfo] = useState({});
|
||||||
const [summary, setSummary] = useState("");
|
const [summary, setSummary] = useState("");
|
||||||
const [selectedSkills, setSelectedSkills] = useState([]);
|
const [selectedSkills, setSelectedSkills] = useState([]);
|
||||||
const [selectSkillsOpen, setSelectSkillsOpen] = useState(false);
|
const [selectSkillsOpen, setSelectSkillsOpen] = useState(false);
|
||||||
const [skillsList, seSkillsList] = useState([]);
|
const [skillsList, seSkillsList] = useState([]);
|
||||||
const { showNotification } = useNotification();
|
const { showNotification } = useNotification();
|
||||||
|
const { id: userId } = useParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
apiRequest(
|
apiRequest(
|
||||||
@ -48,8 +47,10 @@ export const Summary = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSummary(profileInfo.vc_text);
|
if (!userId) {
|
||||||
setSelectedSkills(profileInfo.skillValues);
|
setSummary(profileInfo.vc_text);
|
||||||
|
setSelectedSkills(profileInfo.skillValues);
|
||||||
|
}
|
||||||
}, [profileInfo]);
|
}, [profileInfo]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -58,6 +59,41 @@ export const Summary = () => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (userId) {
|
||||||
|
apiRequest(`/resume?userId=${userId}`).then((res) => {
|
||||||
|
setUserInfo({
|
||||||
|
photo: res.userCard.photo,
|
||||||
|
fio: res.userCard.fio,
|
||||||
|
specification: res.userCard.specification,
|
||||||
|
level: res.userCard.level_title,
|
||||||
|
position: res.userCard.position.name
|
||||||
|
});
|
||||||
|
setSummary(res.userCard.vc_text);
|
||||||
|
setSelectedSkills(res.userCard.skillValues);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [userId]);
|
||||||
|
|
||||||
|
const addSkill = (skill) => {
|
||||||
|
const isSkillFound = selectedSkills.some(
|
||||||
|
(item) => item.skill_id == skill.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isSkillFound) {
|
||||||
|
setSelectedSkills((prevValue) => [
|
||||||
|
...prevValue,
|
||||||
|
{ skill: skill, skill_id: skill.id }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteSkill = (skill) => {
|
||||||
|
setSelectedSkills((prevValue) =>
|
||||||
|
prevValue.filter((item) => item.skill_id !== skill.skill_id)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
function setSkills() {
|
function setSkills() {
|
||||||
apiRequest("/resume/edit-skills", {
|
apiRequest("/resume/edit-skills", {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@ -66,7 +102,13 @@ export const Summary = () => {
|
|||||||
skill: selectedSkills.map((item) => item.skill_id)
|
skill: selectedSkills.map((item) => item.skill_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).then(() => {});
|
}).then(() => {
|
||||||
|
showNotification({
|
||||||
|
show: true,
|
||||||
|
text: "Изменения успешно сохранены",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function editSummary() {
|
function editSummary() {
|
||||||
@ -108,7 +150,9 @@ export const Summary = () => {
|
|||||||
<div className="summary__person">
|
<div className="summary__person">
|
||||||
<img
|
<img
|
||||||
src={
|
src={
|
||||||
profileInfo?.photo
|
userId
|
||||||
|
? urlForLocal(userInfo.photo)
|
||||||
|
: profileInfo?.photo
|
||||||
? urlForLocal(profileInfo.photo)
|
? urlForLocal(profileInfo.photo)
|
||||||
: avatarMok
|
: avatarMok
|
||||||
}
|
}
|
||||||
@ -116,12 +160,18 @@ export const Summary = () => {
|
|||||||
alt="avatar"
|
alt="avatar"
|
||||||
/>
|
/>
|
||||||
<p className="summary__name">
|
<p className="summary__name">
|
||||||
{profileInfo?.fio || profileInfo?.username}{" "}
|
{userId
|
||||||
{profileInfo.specification}
|
? userInfo.fio
|
||||||
|
: profileInfo?.fio || profileInfo?.username}{" "}
|
||||||
|
{userId ? userInfo.specification : profileInfo.specification}
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
<div className="summary__direction">Front End</div>
|
<div className="summary__direction">
|
||||||
<div className="summary__level">Middle+</div>
|
{userId ? userInfo.position : profileInfo?.position?.name}
|
||||||
|
</div>
|
||||||
|
<div className="summary__level">
|
||||||
|
{userId ? userInfo.level : profileInfo?.level_title}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!openGit && (
|
{!openGit && (
|
||||||
<button className="summary__git" onClick={() => setOpenGit(true)}>
|
<button className="summary__git" onClick={() => setOpenGit(true)}>
|
||||||
@ -134,17 +184,19 @@ export const Summary = () => {
|
|||||||
<div className="summary__skills skills__section">
|
<div className="summary__skills skills__section">
|
||||||
<div className="summary__sections__head">
|
<div className="summary__sections__head">
|
||||||
<h3>Основной стек</h3>
|
<h3>Основной стек</h3>
|
||||||
<button
|
{!userId && (
|
||||||
className={editSkills ? "edit" : ""}
|
<button
|
||||||
onClick={() => {
|
className={editSkills ? "edit" : ""}
|
||||||
if (editSkills) {
|
onClick={() => {
|
||||||
setSkills();
|
if (editSkills) {
|
||||||
}
|
setSkills();
|
||||||
setEditSkills(!editSkills);
|
}
|
||||||
}}
|
setEditSkills(!editSkills);
|
||||||
>
|
}}
|
||||||
{editSkills ? "Сохранить" : "Редактировать"}
|
>
|
||||||
</button>
|
{editSkills ? "Сохранить" : "Редактировать"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="skills__section__items">
|
<div className="skills__section__items">
|
||||||
{editSkills ? (
|
{editSkills ? (
|
||||||
@ -157,13 +209,7 @@ export const Summary = () => {
|
|||||||
<img
|
<img
|
||||||
src={deleteIcon}
|
src={deleteIcon}
|
||||||
alt="deleteIcon"
|
alt="deleteIcon"
|
||||||
onClick={() =>
|
onClick={() => deleteSkill(skill)}
|
||||||
setSelectedSkills((prevValue) =>
|
|
||||||
prevValue.filter(
|
|
||||||
(item) => item.skill_id !== skill.skill_id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
@ -184,12 +230,7 @@ export const Summary = () => {
|
|||||||
{skillsList.map((skill) => {
|
{skillsList.map((skill) => {
|
||||||
return (
|
return (
|
||||||
<p
|
<p
|
||||||
onClick={() =>
|
onClick={() => addSkill(skill)}
|
||||||
setSelectedSkills((prevValue) => [
|
|
||||||
...prevValue,
|
|
||||||
{ skill: skill, skill_id: skill.id }
|
|
||||||
])
|
|
||||||
}
|
|
||||||
key={skill.id}
|
key={skill.id}
|
||||||
className="select-skills__item"
|
className="select-skills__item"
|
||||||
>
|
>
|
||||||
@ -205,7 +246,7 @@ export const Summary = () => {
|
|||||||
<div className="skills__section__items__wrapper">
|
<div className="skills__section__items__wrapper">
|
||||||
{selectedSkills &&
|
{selectedSkills &&
|
||||||
selectedSkills.map((skill, index) => (
|
selectedSkills.map((skill, index) => (
|
||||||
<span key={skill.id} className="skill_item">
|
<span key={skill.skill_id} className="skill_item">
|
||||||
{skill.skill.name}
|
{skill.skill.name}
|
||||||
{selectedSkills.length > index + 1 && ","}
|
{selectedSkills.length > index + 1 && ","}
|
||||||
</span>
|
</span>
|
||||||
@ -225,17 +266,19 @@ export const Summary = () => {
|
|||||||
<div className="experience__block">
|
<div className="experience__block">
|
||||||
<div className="summary__sections__head">
|
<div className="summary__sections__head">
|
||||||
<h3>Опыт работы</h3>
|
<h3>Опыт работы</h3>
|
||||||
<button
|
{!userId && (
|
||||||
className={editSummaryOpen ? "edit" : ""}
|
<button
|
||||||
onClick={() => {
|
className={editSummaryOpen ? "edit" : ""}
|
||||||
if (editSummaryOpen) {
|
onClick={() => {
|
||||||
editSummary();
|
if (editSummaryOpen) {
|
||||||
}
|
editSummary();
|
||||||
setEditSummaryOpen(!editSummaryOpen);
|
}
|
||||||
}}
|
setEditSummaryOpen(!editSummaryOpen);
|
||||||
>
|
}}
|
||||||
{editSummaryOpen ? "Сохранить" : "Редактировать"}
|
>
|
||||||
</button>
|
{editSummaryOpen ? "Сохранить" : "Редактировать"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{editSummaryOpen ? (
|
{editSummaryOpen ? (
|
||||||
<CKEditor
|
<CKEditor
|
||||||
@ -284,7 +327,7 @@ export const Summary = () => {
|
|||||||
<a
|
<a
|
||||||
href={itemGit.link}
|
href={itemGit.link}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noopener noreferrer"
|
||||||
key={itemGit.id}
|
key={itemGit.id}
|
||||||
className="summary__section-git-item git-item"
|
className="summary__section-git-item git-item"
|
||||||
>
|
>
|
||||||
@ -305,7 +348,7 @@ export const Summary = () => {
|
|||||||
className="git-item__link"
|
className="git-item__link"
|
||||||
href={itemGit.link}
|
href={itemGit.link}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<img src={rightArrow} alt="arrowRight" />
|
<img src={rightArrow} alt="arrowRight" />
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Route, Routes } from "react-router-dom";
|
import { Navigate, Route, Routes } from "react-router-dom";
|
||||||
|
|
||||||
|
import { Auth } from "@pages/Auth/Auth";
|
||||||
|
import { CompanyInfo } from "@pages/CompanyInfo/CompanyInfo";
|
||||||
|
import { Forms } from "@pages/Forms/Forms";
|
||||||
|
import { Landing } from "@pages/Landing/Landing";
|
||||||
|
import { LandingTracker } from "@pages/LandingTracker/LandingTracker";
|
||||||
import { OpenRequest } from "@pages/OpenRequests/OpenRequest";
|
import { OpenRequest } from "@pages/OpenRequests/OpenRequest";
|
||||||
import { PartnerSettings } from "@pages/PartnerSettings/PartnerSettings";
|
import { PartnerSettings } from "@pages/PartnerSettings/PartnerSettings";
|
||||||
import { PartnerTreaties } from "@pages/PartnerTreaties/PartnerTreaties";
|
import { PartnerTreaties } from "@pages/PartnerTreaties/PartnerTreaties";
|
||||||
@ -10,11 +15,14 @@ import { ProjectTracker } from "@pages/ProjectTracker/ProjectTracker";
|
|||||||
import { PassingTests } from "@pages/Quiz/PassingTests";
|
import { PassingTests } from "@pages/Quiz/PassingTests";
|
||||||
import { QuizPage } from "@pages/Quiz/QuizPage";
|
import { QuizPage } from "@pages/Quiz/QuizPage";
|
||||||
import { QuizReportPage } from "@pages/Quiz/QuizReportPage";
|
import { QuizReportPage } from "@pages/Quiz/QuizReportPage";
|
||||||
|
import { Stack } from "@pages/Stack/Stack";
|
||||||
import Statistics from "@pages/Statistics/Statistics";
|
import Statistics from "@pages/Statistics/Statistics";
|
||||||
import { Summary } from "@pages/Summary/Summary";
|
import { Summary } from "@pages/Summary/Summary";
|
||||||
import { Tracker } from "@pages/Tracker/Tracker";
|
import { Tracker } from "@pages/Tracker/Tracker";
|
||||||
|
import { TrackerIntro } from "@pages/TrackerIntro/TrackerIntro";
|
||||||
import { Vacancy } from "@pages/Vacancy/Vacancy";
|
import { Vacancy } from "@pages/Vacancy/Vacancy";
|
||||||
import { ViewReport } from "@pages/ViewReport/ViewReport";
|
import { ViewReport } from "@pages/ViewReport/ViewReport";
|
||||||
|
import { WelcomePage } from "@pages/WelcomePage/WelcomePage";
|
||||||
|
|
||||||
import TicketFullScreen from "@components/Modal/Tracker/TicketFullScreen/TicketFullScreen";
|
import TicketFullScreen from "@components/Modal/Tracker/TicketFullScreen/TicketFullScreen";
|
||||||
import { ProfileCalendar } from "@components/ProfileCalendar/ProfileCalendar";
|
import { ProfileCalendar } from "@components/ProfileCalendar/ProfileCalendar";
|
||||||
@ -23,6 +31,16 @@ import { ReportForm } from "@components/ReportForm/ReportForm";
|
|||||||
export const DeveloperPage = () => {
|
export const DeveloperPage = () => {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
|
<Route exact path="/auth" element={<Auth />} />
|
||||||
|
<Route exact path="/welcome-page" element={<WelcomePage />} />
|
||||||
|
<Route exact path="/stack" element={<Stack />} />
|
||||||
|
<Route exact path="/landing-tracker" element={<LandingTracker />} />
|
||||||
|
<Route exact path="/" element={<Landing />} />
|
||||||
|
<Route path="*" element={<Navigate to="/auth" replace />} />
|
||||||
|
<Route exact path="/tracker-intro" element={<TrackerIntro />} />
|
||||||
|
<Route exact path="/forms" element={<Forms />} />
|
||||||
|
<Route exact path="/company" element={<CompanyInfo />} />
|
||||||
|
|
||||||
<Route exact path="/tracker/task/:id" element={<TicketFullScreen />} />
|
<Route exact path="/tracker/task/:id" element={<TicketFullScreen />} />
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Navigate, Route, Routes } from "react-router-dom";
|
import { Navigate, Route, Routes } from "react-router-dom";
|
||||||
|
|
||||||
|
import { Auth } from "@pages/Auth/Auth";
|
||||||
|
import { CompanyInfo } from "@pages/CompanyInfo/CompanyInfo";
|
||||||
import { FormPage } from "@pages/FormPage/FormPage";
|
import { FormPage } from "@pages/FormPage/FormPage";
|
||||||
|
import { Forms } from "@pages/Forms/Forms";
|
||||||
import { Home } from "@pages/Home/Home";
|
import { Home } from "@pages/Home/Home";
|
||||||
|
import { Landing } from "@pages/Landing/Landing";
|
||||||
|
import { LandingTracker } from "@pages/LandingTracker/LandingTracker";
|
||||||
import { PartnerAddRequest } from "@pages/PartnerAddRequest/PartnerAddRequest";
|
import { PartnerAddRequest } from "@pages/PartnerAddRequest/PartnerAddRequest";
|
||||||
import { PartnerBid } from "@pages/PartnerBid/PartnerBid";
|
import { PartnerBid } from "@pages/PartnerBid/PartnerBid";
|
||||||
import { PartnerEmployeeReport } from "@pages/PartnerEmployeeReport/PartnerEmployeeReport";
|
import { PartnerEmployeeReport } from "@pages/PartnerEmployeeReport/PartnerEmployeeReport";
|
||||||
@ -13,20 +18,36 @@ import { PartnerTreaties } from "@pages/PartnerTreaties/PartnerTreaties";
|
|||||||
import { PartnerCategories } from "@pages/PartnerСategories/PartnerСategories";
|
import { PartnerCategories } from "@pages/PartnerСategories/PartnerСategories";
|
||||||
import { Profile } from "@pages/Profile/Profile";
|
import { Profile } from "@pages/Profile/Profile";
|
||||||
import { ProjectTracker } from "@pages/ProjectTracker/ProjectTracker";
|
import { ProjectTracker } from "@pages/ProjectTracker/ProjectTracker";
|
||||||
|
import { Stack } from "@pages/Stack/Stack";
|
||||||
import Statistics from "@pages/Statistics/Statistics";
|
import Statistics from "@pages/Statistics/Statistics";
|
||||||
|
import { Summary } from "@pages/Summary/Summary";
|
||||||
import { Tracker } from "@pages/Tracker/Tracker";
|
import { Tracker } from "@pages/Tracker/Tracker";
|
||||||
|
import { TrackerIntro } from "@pages/TrackerIntro/TrackerIntro";
|
||||||
import { ViewReport } from "@pages/ViewReport/ViewReport";
|
import { ViewReport } from "@pages/ViewReport/ViewReport";
|
||||||
|
import { WelcomePage } from "@pages/WelcomePage/WelcomePage";
|
||||||
|
|
||||||
import { Calendar } from "@components/Calendar/Calendar";
|
import { Calendar } from "@components/Calendar/Calendar";
|
||||||
import { Candidate } from "@components/Candidate/Candidate";
|
import { Candidate } from "@components/Candidate/Candidate";
|
||||||
|
import TicketFullScreen from "@components/Modal/Tracker/TicketFullScreen/TicketFullScreen";
|
||||||
|
|
||||||
export const PartnerPage = () => {
|
export const PartnerPage = () => {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
|
<Route exact path="/auth" element={<Auth />} />
|
||||||
|
<Route exact path="/welcome-page" element={<WelcomePage />} />
|
||||||
|
<Route exact path="/stack" element={<Stack />} />
|
||||||
|
<Route exact path="/landing-tracker" element={<LandingTracker />} />
|
||||||
|
<Route exact path="/" element={<Landing />} />
|
||||||
|
<Route path="*" element={<Navigate to="/auth" replace />} />
|
||||||
|
<Route exact path="/tracker-intro" element={<TrackerIntro />} />
|
||||||
|
<Route exact path="/forms" element={<Forms />} />
|
||||||
|
<Route exact path="/company" element={<CompanyInfo />} />
|
||||||
|
|
||||||
<Route exact path="/candidate/:id" element={<Candidate />} />
|
<Route exact path="/candidate/:id" element={<Candidate />} />
|
||||||
<Route exact path="/candidate/:id/form" element={<FormPage />} />
|
<Route exact path="/candidate/:id/form" element={<FormPage />} />
|
||||||
<Route path="/:userId/calendar" element={<Calendar />} />
|
<Route path="/:userId/calendar" element={<Calendar />} />
|
||||||
|
|
||||||
|
<Route exact path="/tracker/task/:id" element={<TicketFullScreen />} />
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/tracker/project/:id/task/:taskId"
|
path="/tracker/project/:id/task/:taskId"
|
||||||
@ -46,6 +67,7 @@ export const PartnerPage = () => {
|
|||||||
<Route exact path="requests-edit" element={<PartnerAddRequest />} />
|
<Route exact path="requests-edit" element={<PartnerAddRequest />} />
|
||||||
<Route exact path="requests-bid" element={<PartnerBid />} />
|
<Route exact path="requests-bid" element={<PartnerBid />} />
|
||||||
<Route exact path="employees" element={<PartnerCategories />} />
|
<Route exact path="employees" element={<PartnerCategories />} />
|
||||||
|
<Route exact path="summary/:id" element={<Summary />} />
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="employees/report/:uuid"
|
path="employees/report/:uuid"
|
||||||
|