trackerTask #12

Merged
nik.polishuk merged 4 commits from trackerTask into main 2024-02-01 23:15:29 +03:00
14 changed files with 381 additions and 197 deletions

View File

@ -101,6 +101,21 @@
line-height: 32px;
color: white;
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;
}
}
@ -139,6 +154,11 @@
transform: scale(1.03);
color: white;
}
@media (max-width: 450px) {
width: 100%;
max-width: none;
}
}
&__img {

View File

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

View File

@ -0,0 +1,29 @@
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

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

View File

@ -114,9 +114,7 @@ export const ProfileCalendarComponent = React.memo(
startDate._d
)}`;
apiRequest(
`/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem(
"cardId"
)}`
`/reports/index?${requestDates}&user_id =${localStorage.getItem("id")}`
).then((reports) => {
let spendTime = 0;
reports.map((report) => {
@ -273,15 +271,15 @@ export const ProfileCalendarComponent = React.memo(
? `${getCorrectDate(startDate)} - ${getCorrectDate(endDate)}`
: `${getCorrectDate(endDate)} - ${getCorrectDate(startDate)}`
: activePeriod
? "Выберите диапазон на календаре"
: "Выбрать диапазон"}
? "Выберите диапазон на календаре"
: "Выбрать диапазон"}
</span>
<span>
{totalRangeHours
? `${totalRangeHours} ${hourOfNum(totalRangeHours)}`
: endDate
? "0 часов"
: ""}
? "0 часов"
: ""}
</span>
{endDate && (
<BaseButton

View File

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

View File

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

View File

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

View File

@ -1,137 +1,146 @@
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import React, { useEffect, useState } from "react";
// import { useDispatch } from "react-redux";
// import { Link } from "react-router-dom";
import { Navigate } from "react-router-dom";
import { setPartnerEmployees } from "@redux/outstaffingSlice";
import { apiRequest } from "@api/request";
// import { setPartnerEmployees } from "@redux/outstaffingSlice";
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 { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
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 { Navigation } from "../../components/Navigation/Navigation";
// 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";
export const PartnerCategories = () => {
const dispatch = useDispatch();
// const dispatch = useDispatch();
if (localStorage.getItem("role_status") !== "18") {
return <Navigate to="/profile" replace />;
}
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 [staff, setStaff] = useState([]);
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
}
]);
useEffect(() => {
apiRequest("/project/my-employee").then((el) => {
setStaff(el.managerEmployees);
});
}, []);
// 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 (
<div className="partnerCategories">
<ProfileHeader />
@ -145,39 +154,49 @@ export const PartnerCategories = () => {
/>
<h2 className="partnerCategories__title">Данные персонала</h2>
<div className="partnerCategories__items">
{personalInfoItems.map((item, index) => {
{staff.map((card) => {
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>
<PartnerPersonCard
key={card.id}
name={card.employee.fio}
img={card.employee.avatar}
userId={card.user_id}
/>
);
})}
{/*{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>
<Footer />

View File

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

View File

@ -1,4 +1,8 @@
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 { Footer } from "@components/Common/Footer/Footer";
@ -14,9 +18,38 @@ import "./trackerRegistration.scss";
export const TrackerRegistration = () => {
const [modalConfirmOpen, setModalConfirm] = useState(false);
const [inputs, setInputs] = useState({
email: ""
});
const fields = {
username: "",
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 (
<div className="tracker-registration">
@ -34,33 +67,65 @@ export const TrackerRegistration = () => {
<div className="tracker-registration__form">
<div className="tracker-registration__form__inputs">
<div className="tracker-registration__inputContainer">
<span>Ваше имя</span>
<input placeholder="Имя" />
</div>
<div className="tracker-registration__inputContainer">
<span>Ваш e-mail</span>
<h5>Ваше имя</h5>
<input
placeholder="E-mail"
onChange={(e) =>
setInputs((prevState) => ({
...prevState,
email: e.target.value
}))
}
type="email"
placeholder="Имя"
className={validationErrors.username ? "error" : ""}
onChange={handleChange}
value={formData.username}
id="username"
/>
<span>{validationErrors.username}</span>
</div>
<div className="tracker-registration__inputContainer">
<span>Придумайте пароль</span>
<input placeholder="Пароль" />
<h5>Ваш e-mail</h5>
<input
onChange={handleChange}
className={validationErrors.email ? "error" : ""}
placeholder="E-mail"
type="email"
id="email"
value={formData.email}
/>
<span>{validationErrors.email}</span>
</div>
<div className="tracker-registration__inputContainer">
<span>Повторите пароль</span>
<input placeholder="Повторите пароль" />
<h5>Придумайте пароль</h5>
<input
placeholder="Пароль"
className={validationErrors.password ? "error" : ""}
onChange={handleChange}
value={formData.password}
type="password"
id="password"
/>
<span>{validationErrors.password}</span>
</div>
<div className="tracker-registration__inputContainer">
<h5>Повторите пароль</h5>
<input
placeholder="Повторите пароль"
className={validationErrors.secondPassword ? "error" : ""}
value={formData.secondPassword}
type="password"
onChange={handleChange}
id="secondPassword"
/>
<span>{validationErrors.secondPassword}</span>
</div>
</div>
<div className="tracker-registration__form__submit">
<button onClick={() => setModalConfirm(true)}>Отправить</button>
<button
onClick={async (e) => {
e.preventDefault();
const result = await handleSubmit(e);
if (result === true) {
setModalConfirm(true);
}
}}
>
Отправить
</button>
<div className="tracker-registration__form__info">
<img src={authImg} alt="img" />
<p>
@ -80,7 +145,7 @@ export const TrackerRegistration = () => {
<ModalLayout active={modalConfirmOpen} setActive={setModalConfirm}>
<ModalTrackerRegistration
setModalReset={setModalConfirm}
email={inputs.email}
email={formData.email}
/>
</ModalLayout>
)}

View File

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

View File

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