Compare commits

..

No commits in common. "06f5cda1e89f12e90897cc64d40ad26eb174f3df" and "66e6b4c7d7f9d22d95a221689015db8d98c5c67a" have entirely different histories.

14 changed files with 193 additions and 377 deletions

View File

@ -101,21 +101,6 @@
line-height: 32px; line-height: 32px;
color: white; color: white;
height: 45px; height: 45px;
@media (max-width: 900px) {
max-width: 185px;
}
@media (max-width: 450px) {
width: 100%;
max-width: none;
margin-right: 0;
}
}
@media (max-width: 450px) {
flex-direction: column;
row-gap: 10px;
} }
} }
@ -154,11 +139,6 @@
transform: scale(1.03); transform: scale(1.03);
color: white; color: white;
} }
@media (max-width: 450px) {
width: 100%;
max-width: none;
}
} }
&__img { &__img {

View File

@ -1,5 +1,4 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom";
import close from "assets/icons/closeProjectPersons.svg"; import close from "assets/icons/closeProjectPersons.svg";
@ -17,13 +16,12 @@ export const ModalTrackerRegistration = ({ setModalReset, email }) => {
для активации вашего аккаунта на почту для активации вашего аккаунта на почту
<br /> <span>{email}</span> <br /> <span>{email}</span>
</p> </p>
<Link <button
to={"/registration-setting"}
onClick={() => setModalReset(false)} onClick={() => setModalReset(false)}
className="modalConfirmTracker__btn" className="modalConfirmTracker__btn"
> >
Понятно Понятно
</Link> </button>
<img <img
onClick={() => setModalReset(false)} onClick={() => setModalReset(false)}
src={close} src={close}

View File

@ -1,29 +0,0 @@
import React from "react";
import { Link } from "react-router-dom";
import { urlForLocal } from "@utils/helper";
import rightArrow from "assets/icons/arrows/arrowRight.svg";
import "./partnerPersonCard.scss";
export const PartnerPersonCard = ({ name, img, userId }) => {
return (
<div className="partnerPersonCard">
<div className="partnerPersonCard__img">
<img src={urlForLocal(img)} alt="avatar" />
</div>
<div className="partnerPersonCard__info">
<h2 className="partnerPersonCard__name">{name}</h2>
<Link className="partnerPersonCard__report" to={`calendar/${userId}`}>
Подробный отчет
<div className="partnerPersonCard__more">
<img src={rightArrow} alt="arrow" />
</div>
</Link>
</div>
</div>
);
};
export default PartnerPersonCard;

View File

@ -1,45 +0,0 @@
.partnerPersonCard {
display: flex;
position: relative;
&__img {
background: white;
border-radius: 12px;
padding: 25px;
z-index: 2;
img {
width: 77px;
height: 77px;
}
}
&__info {
position: relative;
background: #E1FCCF;
z-index: 1;
padding: 15px 15px 15px 30px;
left: -15px;
border-radius: 12px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
&__report {
display: flex;
column-gap: 10px;
color: black;
font-size: 16px;
align-items: center;
}
&__more {
width: 41px;
height: 41px;
background: white;
border-radius: 50px;
display: flex;
justify-content: center;
align-items: center;
}
}

View File

@ -51,7 +51,9 @@ export const ProfileCalendar = () => {
return; return;
} }
apiRequest( apiRequest(
`/reports/index?${requestDates}&user_id =${localStorage.getItem("id")}` `/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem(
"cardId"
)}`
).then((reports) => { ).then((reports) => {
let spendTime = 0; let spendTime = 0;

View File

@ -114,7 +114,9 @@ export const ProfileCalendarComponent = React.memo(
startDate._d startDate._d
)}`; )}`;
apiRequest( apiRequest(
`/reports/index?${requestDates}&user_id =${localStorage.getItem("id")}` `/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem(
"cardId"
)}`
).then((reports) => { ).then((reports) => {
let spendTime = 0; let spendTime = 0;
reports.map((report) => { reports.map((report) => {

View File

@ -97,7 +97,6 @@ const ReportForm = () => {
apiRequest("/reports/create", { apiRequest("/reports/create", {
method: "POST", method: "POST",
data: { data: {
user_id: localStorage.getItem("id"),
tasks: inputs, tasks: inputs,
difficulties: troublesInputValue, difficulties: troublesInputValue,
tomorrow: scheduledInputValue, tomorrow: scheduledInputValue,

View File

@ -39,7 +39,9 @@ export const ShortReport = () => {
setTomorrowTask([]); setTomorrowTask([]);
setTotalHours(0); setTotalHours(0);
apiRequest( apiRequest(
`reports/find-by-date?user_id=${localStorage.getItem("id")}&date=${day}` `reports/find-by-date?user_card_id=${localStorage.getItem(
"cardId"
)}&date=${day}`
).then((res) => { ).then((res) => {
let spendTime = 0; let spendTime = 0;
for (const item of res) { for (const item of res) {

View File

@ -504,13 +504,13 @@ $maxWidthContainer: 1123;
} }
} }
&__finished { &__finished {
background: white; background: rgba(255, 255, 255, 0.76);
mix-blend-mode: normal; mix-blend-mode: normal;
border: 3px solid #52b709; border: 3px solid #52b709;
border-radius: 12px; border-radius: 12px;
padding: 13px 16px; padding: 13px 16px;
position: absolute; position: absolute;
bottom: 4px; bottom: 0;
left: 0; left: 0;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,146 +1,137 @@
import React, { useEffect, useState } from "react"; import React, { useState } from "react";
// import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
// import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { apiRequest } from "@api/request"; import { setPartnerEmployees } from "@redux/outstaffingSlice";
// import { setPartnerEmployees } from "@redux/outstaffingSlice";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
import { Navigation } from "@components/Navigation/Navigation";
import PartnerPersonCard from "@components/PartnerPersonCard/PartnerPersonCard";
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 rightArrow from "assets/icons/arrows/arrowRight.svg"; import rightArrow from "assets/icons/arrows/arrowRight.svg";
// import avatarImg from "assets/images/avatarMok.png"; import avatarImg from "assets/images/avatarMok.png";
// import AdminImg from "assets/images/partnerProfile/PersonalAdmin.svg"; import AdminImg from "assets/images/partnerProfile/PersonalAdmin.svg";
// import ArchitectureImg from "assets/images/partnerProfile/PersonalArchitecture.svg"; import ArchitectureImg from "assets/images/partnerProfile/PersonalArchitecture.svg";
// import CopyImg from "assets/images/partnerProfile/PersonalCopy.svg"; import CopyImg from "assets/images/partnerProfile/PersonalCopy.svg";
// import DesignImg from "assets/images/partnerProfile/PersonalDesign.svg"; import DesignImg from "assets/images/partnerProfile/PersonalDesign.svg";
// import FrontendImg from "assets/images/partnerProfile/PersonalFrontend.svg"; import FrontendImg from "assets/images/partnerProfile/PersonalFrontend.svg";
// import ManageImg from "assets/images/partnerProfile/PersonalMng.svg"; import ManageImg from "assets/images/partnerProfile/PersonalMng.svg";
// import SmmImg from "assets/images/partnerProfile/PersonalSMM.svg"; import SmmImg from "assets/images/partnerProfile/PersonalSMM.svg";
// import TestImg from "assets/images/partnerProfile/PersonalTesters.svg"; import TestImg from "assets/images/partnerProfile/PersonalTesters.svg";
// import BackEndImg from "assets/images/partnerProfile/personalBackEnd.svg"; import BackEndImg from "assets/images/partnerProfile/personalBackEnd.svg";
import { Navigation } from "../../components/Navigation/Navigation";
import "./partnerСategories.scss"; import "./partnerСategories.scss";
export const PartnerCategories = () => { export const PartnerCategories = () => {
// const dispatch = useDispatch(); 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 />;
} }
const [staff, setStaff] = useState([]); 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
}
]);
useEffect(() => { const [mokPersons] = useState([
apiRequest("/project/my-employee").then((el) => { {
setStaff(el.managerEmployees); personAvatar: avatarImg,
}); name: "Макаренко Дмитрий",
}, []); qualification: "PHP Backend - разработчик",
level: "Middle",
// const [personalInfoItems] = useState([ project: "Админка НВД Консалтинг",
// { tasks_in_progress: 5,
// title: "Backend разработчики", month_hours: 140,
// link: "/profile/categories/employees", id: 1
// description: },
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript", {
// available: true, personAvatar: avatarImg,
// img: BackEndImg name: "Макаренко Дмитрий",
// }, qualification: "PHP Backend - разработчик",
// { level: "Middle",
// title: "Frontend разработчики", project: "Админка НВД Консалтинг",
// link: "/profile/categories/employees", tasks_in_progress: 5,
// description: month_hours: 140,
// "Java PHP Python C# React Vue.js NodeJs Golang Ruby JavaScript", id: 2
// available: true, },
// img: FrontendImg {
// }, personAvatar: avatarImg,
// { name: "Макаренко Дмитрий",
// title: "Архитектура проектов", qualification: "PHP Backend - разработчик",
// link: "/profile/categories/employees", level: "Middle",
// description: "Потоки данных ER ERP CRM CQRS UML BPMN", project: "Админка НВД Консалтинг",
// available: true, tasks_in_progress: 5,
// img: ArchitectureImg month_hours: 140,
// }, id: 3
// { }
// 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="partnerCategories"> <div className="partnerCategories">
<ProfileHeader /> <ProfileHeader />
@ -154,49 +145,39 @@ export const PartnerCategories = () => {
/> />
<h2 className="partnerCategories__title">Данные персонала</h2> <h2 className="partnerCategories__title">Данные персонала</h2>
<div className="partnerCategories__items"> <div className="partnerCategories__items">
{staff.map((card) => { {personalInfoItems.map((item, index) => {
return ( return (
<PartnerPersonCard <Link
key={card.id} to={item.link}
name={card.employee.fio} key={index}
img={card.employee.avatar} className={
userId={card.user_id} item.available
/> ? "partnerCategories__item item"
: "partnerCategories__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__disableHover">
<p>У вас нет персонала из категории</p>
<button>Подобрать</button>
</div>
)}
</Link>
); );
})} })}
{/*{personalInfoItems.map((item, index) => {*/}
{/* return (*/}
{/* <Link*/}
{/* to={item.link}*/}
{/* key={index}*/}
{/* className={*/}
{/* item.available*/}
{/* ? "partnerCategories__item item"*/}
{/* : "partnerCategories__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__disableHover">*/}
{/* <p>У вас нет персонала из категории</p>*/}
{/* <button>Подобрать</button>*/}
{/* </div>*/}
{/* )}*/}
{/* </Link>*/}
{/* );*/}
{/*})}*/}
</div> </div>
</div> </div>
<Footer /> <Footer />

View File

@ -13,12 +13,10 @@
&__items { &__items {
display: flex; display: flex;
gap: 10px;
flex-wrap: wrap; flex-wrap: wrap;
//flex-wrap: wrap; margin-top: 25px;
//margin-top: 25px; row-gap: 24px;
//row-gap: 24px; column-gap: 21px;
//column-gap: 21px;
} }

View File

@ -1,8 +1,4 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Navigate } from "react-router-dom";
import { useFormValidation } from "@hooks/useFormValidation";
import { useNotification } from "@hooks/useNotification";
import AuthHeader from "@components/Common/AuthHeader/AuthHeader"; import AuthHeader from "@components/Common/AuthHeader/AuthHeader";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
@ -18,38 +14,9 @@ import "./trackerRegistration.scss";
export const TrackerRegistration = () => { export const TrackerRegistration = () => {
const [modalConfirmOpen, setModalConfirm] = useState(false); const [modalConfirmOpen, setModalConfirm] = useState(false);
const fields = { const [inputs, setInputs] = useState({
username: "", email: ""
email: "",
password: "",
secondPassword: ""
};
const apiEndpoint = "/register/sign-up";
const { showNotification } = useNotification();
const showNotificationError = () => {
showNotification({
show: true,
text: "Аккаунт с таким логином или email уже существует",
type: "error"
}); });
};
const showNotificationTrue = () => {
showNotification({
show: true,
text: "Аккаунт успешно создан",
type: "success"
});
};
const { formData, validationErrors, handleChange, handleSubmit } =
useFormValidation(
apiEndpoint,
fields,
showNotificationError,
showNotificationTrue
);
return ( return (
<div className="tracker-registration"> <div className="tracker-registration">
@ -67,65 +34,33 @@ export const TrackerRegistration = () => {
<div className="tracker-registration__form"> <div className="tracker-registration__form">
<div className="tracker-registration__form__inputs"> <div className="tracker-registration__form__inputs">
<div className="tracker-registration__inputContainer"> <div className="tracker-registration__inputContainer">
<h5>Ваше имя</h5> <span>Ваше имя</span>
<input <input placeholder="Имя" />
placeholder="Имя"
className={validationErrors.username ? "error" : ""}
onChange={handleChange}
value={formData.username}
id="username"
/>
<span>{validationErrors.username}</span>
</div> </div>
<div className="tracker-registration__inputContainer"> <div className="tracker-registration__inputContainer">
<h5>Ваш e-mail</h5> <span>Ваш e-mail</span>
<input <input
onChange={handleChange}
className={validationErrors.email ? "error" : ""}
placeholder="E-mail" placeholder="E-mail"
onChange={(e) =>
setInputs((prevState) => ({
...prevState,
email: e.target.value
}))
}
type="email" type="email"
id="email"
value={formData.email}
/> />
<span>{validationErrors.email}</span>
</div> </div>
<div className="tracker-registration__inputContainer"> <div className="tracker-registration__inputContainer">
<h5>Придумайте пароль</h5> <span>Придумайте пароль</span>
<input <input placeholder="Пароль" />
placeholder="Пароль"
className={validationErrors.password ? "error" : ""}
onChange={handleChange}
value={formData.password}
type="password"
id="password"
/>
<span>{validationErrors.password}</span>
</div> </div>
<div className="tracker-registration__inputContainer"> <div className="tracker-registration__inputContainer">
<h5>Повторите пароль</h5> <span>Повторите пароль</span>
<input <input placeholder="Повторите пароль" />
placeholder="Повторите пароль"
className={validationErrors.secondPassword ? "error" : ""}
value={formData.secondPassword}
type="password"
onChange={handleChange}
id="secondPassword"
/>
<span>{validationErrors.secondPassword}</span>
</div> </div>
</div> </div>
<div className="tracker-registration__form__submit"> <div className="tracker-registration__form__submit">
<button <button onClick={() => setModalConfirm(true)}>Отправить</button>
onClick={async (e) => {
e.preventDefault();
const result = await handleSubmit(e);
if (result === true) {
setModalConfirm(true);
}
}}
>
Отправить
</button>
<div className="tracker-registration__form__info"> <div className="tracker-registration__form__info">
<img src={authImg} alt="img" /> <img src={authImg} alt="img" />
<p> <p>
@ -145,7 +80,7 @@ export const TrackerRegistration = () => {
<ModalLayout active={modalConfirmOpen} setActive={setModalConfirm}> <ModalLayout active={modalConfirmOpen} setActive={setModalConfirm}>
<ModalTrackerRegistration <ModalTrackerRegistration
setModalReset={setModalConfirm} setModalReset={setModalConfirm}
email={formData.email} email={inputs.email}
/> />
</ModalLayout> </ModalLayout>
)} )}

View File

@ -41,7 +41,6 @@
&__submit { &__submit {
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 5px;
button { button {
border-radius: 44px; border-radius: 44px;
@ -107,18 +106,15 @@
&__inputContainer { &__inputContainer {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
row-gap: 15px;
max-width: 300px; max-width: 300px;
width: 100%; width: 100%;
margin-bottom: 44px; margin-bottom: 44px;
h5 {
font-size: 15px;
}
span { span {
font-weight: 400; font-weight: 400;
font-size: 12px; font-size: 15px;
color: red; color: #000;
} }
input { input {
@ -126,7 +122,6 @@
padding: 8px 12px 9px; padding: 8px 12px 9px;
background-color: #EFF2F7; background-color: #EFF2F7;
border-radius: 8px; border-radius: 8px;
margin: 10px 0;
border: none; border: none;
font-weight: 400; font-weight: 400;
font-size: 15px; font-size: 15px;
@ -137,9 +132,5 @@
margin-bottom: 0; margin-bottom: 0;
max-width: none; max-width: none;
} }
.error {
border: 1px solid red;
}
} }
} }

View File

@ -41,7 +41,9 @@ export const ViewReport = () => {
setDifficulties([]); setDifficulties([]);
setTomorrowTask([]); setTomorrowTask([]);
apiRequest( apiRequest(
`reports/find-by-date?user_id=${localStorage.getItem("id")}&date=${day}` `reports/find-by-date?user_card_id=${localStorage.getItem(
"cardId"
)}&date=${day}`
).then((res) => { ).then((res) => {
let spendTime = 0; let spendTime = 0;
for (const item of res) { for (const item of res) {