Compare commits

..

No commits in common. "75cf13d945c5207b5be35dfcc9583a771efbde58" and "c532302f7305156678965a939b310ea4f0c0b27f" have entirely different histories.

10 changed files with 257 additions and 334 deletions

View File

@ -95,21 +95,11 @@ export const ProfileCalendar = () => {
alt="avatar" alt="avatar"
/> />
<p className="summary__name"> <p className="summary__name">
{profileInfo?.fio || profileInfo?.username}{" "} {profileInfo?.fio || profileInfo?.username},{" "}
{profileInfo.specification} {profileInfo.specification} разработчик
</p> </p>
<hr />
<div className="summary__direction">Front End</div>
<div className="summary__level">Middle+</div>
</div> </div>
<div className="summary__skill"> <Link to="/profile/calendar/report">
<p>Ключевые навыки:</p>
<div>Java</div>
<div>Java</div>
<div>Solid</div>
<div>Java</div>
</div>
{/* <Link to="/profile/calendar/report">
<button <button
className="calendar__btn" className="calendar__btn"
onClick={() => { onClick={() => {
@ -119,7 +109,7 @@ export const ProfileCalendar = () => {
> >
Заполнить отчет Заполнить отчет
</button> </button>
</Link> */} </Link>
</div> </div>
{loader ? ( {loader ? (
<div className="loader__wrapper"> <div className="loader__wrapper">

View File

@ -22,25 +22,6 @@
@media (max-width: 500px) { @media (max-width: 500px) {
padding-right: 5px; padding-right: 5px;
} }
.summary__skill {
color: #6f6f6f;
font-size: 14px;
font-weight: 300;
display: flex;
flex-direction: row;
align-items: center;
column-gap: 10px;
div {
font-size: 12px;
font-weight: 400;
border: #8dc63f 0.5px solid;
border-radius: 44px;
padding: 3px 20px;
}
}
} }
.loader__wrapper { .loader__wrapper {

View File

@ -1,113 +0,0 @@
import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { filteredExecutorTasks } from "@redux/projectsTrackerSlice";
import { removeLast, urlForLocal } from "@utils/helper";
import arrowDown from "assets/icons/arrows/selectArrow.png";
import close from "assets/icons/close.png";
import avatarMok from "assets/images/avatarMok.png";
import "./trackerSelectExecutor.scss";
const TrackerSelectExecutor = ({
selectedExecutor,
setSelectedExecutor,
deleteSelectedExecutor,
projectBoard
}) => {
const [selectExecutorOpen, setSelectedExecutorOpen] = useState(false);
const dispatch = useDispatch();
const initListeners = () => {
document.addEventListener("click", closeByClickingOut);
};
const closeByClickingOut = (event) => {
const path = event.path || (event.composedPath && event.composedPath());
if (
event &&
!path.find(
(div) =>
div.classList &&
(div.classList.contains("tasks__head__executor") ||
div.classList.contains("tasks__head__executor-dropdown"))
)
) {
setSelectedExecutorOpen(false);
}
};
function executorFilter(user) {
dispatch(filteredExecutorTasks(user.user_id));
setSelectedExecutor(user);
}
useEffect(() => {
initListeners();
}, []);
if (selectedExecutor) {
return (
<div className="tasks__head__executor-selected">
<p>{removeLast(selectedExecutor.user.fio)}</p>
<img
className="avatar"
src={
selectedExecutor.user?.avatar
? urlForLocal(selectedExecutor.user.avatar)
: avatarMok
}
alt="avatar"
/>
<img
className="delete"
src={close}
alt="delete"
onClick={deleteSelectedExecutor}
/>
</div>
);
} else {
return (
<div
className="tasks__head__executor"
onClick={() => setSelectedExecutorOpen(!selectExecutorOpen)}
>
<p>Выберите исполнителя</p>
<img
className={selectExecutorOpen ? "open" : ""}
src={arrowDown}
alt="arrow"
/>
{selectExecutorOpen && (
<div className="tasks__head__executor-dropdown">
{projectBoard.projectUsers.map((user) => {
return (
<div
className="executor-dropdown__person"
key={user.user_id}
onClick={() => executorFilter(user)}
>
<p>{removeLast(user.user?.fio)}</p>
<img
src={
user.user?.avatar
? urlForLocal(user.user.avatar)
: avatarMok
}
alt="avatar"
/>
</div>
);
})}
</div>
)}
</div>
);
}
};
export default TrackerSelectExecutor;

View File

@ -40,7 +40,6 @@ 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 TrackerSelectColumn from "@components/TrackerSelectColumn/TrackerSelectColumn"; import TrackerSelectColumn from "@components/TrackerSelectColumn/TrackerSelectColumn";
import TrackerSelectExecutor from "@components/TrackerSelectExecutor/TrackerSelectExecutor";
import arrow from "assets/icons/arrows/arrowRight.png"; import arrow from "assets/icons/arrows/arrowRight.png";
import arrowDown from "assets/icons/arrows/selectArrow.png"; import arrowDown from "assets/icons/arrows/selectArrow.png";
@ -54,6 +53,7 @@ import trackerNoTasks from "assets/icons/trackerNoTasks.svg";
import project from "assets/icons/trackerProject.svg"; import project from "assets/icons/trackerProject.svg";
import tasks from "assets/icons/trackerTasks.svg"; import tasks from "assets/icons/trackerTasks.svg";
import accept from "assets/images/accept.png"; import accept from "assets/images/accept.png";
import archive from "assets/images/archiveIcon.png";
import avatarMok from "assets/images/avatarMok.png"; import avatarMok from "assets/images/avatarMok.png";
import { getCorrectDate } from "../../utils/calendarHelper"; import { getCorrectDate } from "../../utils/calendarHelper";
@ -85,6 +85,7 @@ export const ProjectTracker = () => {
const [filteredNoTasks, setFilteredNoTasks] = useState(false); const [filteredNoTasks, setFilteredNoTasks] = useState(false);
const [checkBoxMyTasks, setCheckBoxMyTasks] = useState(false); const [checkBoxMyTasks, setCheckBoxMyTasks] = useState(false);
const [selectedExecutor, setSelectedExecutor] = useState(null); const [selectedExecutor, setSelectedExecutor] = useState(null);
const [selectExecutorOpen, setSelectedExecutorOpen] = useState(false);
const startWrapperIndexTest = useRef({}); const startWrapperIndexTest = useRef({});
const projectBoard = useSelector(getProjectBoard); const projectBoard = useSelector(getProjectBoard);
const loader = useSelector(getBoarderLoader); const loader = useSelector(getBoarderLoader);
@ -287,6 +288,11 @@ export const ProjectTracker = () => {
setCheckBoxMyTasks(!checkBoxMyTasks); setCheckBoxMyTasks(!checkBoxMyTasks);
} }
function executorFilter(user) {
dispatch(filteredExecutorTasks(user.user_id));
setSelectedExecutor(user);
}
function deleteSelectedExecutorFilter() { function deleteSelectedExecutorFilter() {
setSelectedExecutor(null); setSelectedExecutor(null);
setCheckBoxParticipateTasks(false); setCheckBoxParticipateTasks(false);
@ -388,6 +394,18 @@ export const ProjectTracker = () => {
setPersonListOpen(false); setPersonListOpen(false);
} }
if (
event &&
!path.find(
(div) =>
div.classList &&
(div.classList.contains("tasks__head__executor") ||
div.classList.contains("tasks__head__executor-dropdown"))
)
) {
setSelectedExecutorOpen(false);
}
if ( if (
event && event &&
!path.find( !path.find(
@ -559,14 +577,63 @@ export const ProjectTracker = () => {
{checkBoxMyTasks && <img src={accept} alt="accept" />} {checkBoxMyTasks && <img src={accept} alt="accept" />}
</div> </div>
</div> </div>
{selectedExecutor ? (
<TrackerSelectExecutor <div className="tasks__head__executor-selected">
deleteSelectedExecutor={deleteSelectedExecutorFilter} <p>{removeLast(selectedExecutor.user.fio)}</p>
projectBoard={projectBoard} <img
selectedExecutor={selectedExecutor} className="avatar"
setSelectedExecutor={setSelectedExecutor} src={
selectedExecutor.user?.avatar
? urlForLocal(selectedExecutor.user.avatar)
: avatarMok
}
alt="avatar"
/> />
<img
className="delete"
src={close}
alt="delete"
onClick={deleteSelectedExecutorFilter}
/>
</div>
) : (
<div
className="tasks__head__executor"
onClick={() =>
setSelectedExecutorOpen(!selectExecutorOpen)
}
>
<p>Выберите исполнителя</p>
<img
className={selectExecutorOpen ? "open" : ""}
src={arrowDown}
alt="arrow"
/>
{selectExecutorOpen && (
<div className="tasks__head__executor-dropdown">
{projectBoard.projectUsers.map((user) => {
return (
<div
className="executor-dropdown__person"
key={user.user_id}
onClick={() => executorFilter(user)}
>
<p>{removeLast(user.user?.fio)}</p>
<img
src={
user.user?.avatar
? urlForLocal(user.user.avatar)
: avatarMok
}
alt="avatar"
/>
</div>
);
})}
</div>
)}
</div>
)}
<div className="tasks__head__tags"> <div className="tasks__head__tags">
<div <div
className="tags__add" className="tags__add"

View File

@ -116,8 +116,8 @@ export const Summary = () => {
alt="avatar" alt="avatar"
/> />
<p className="summary__name"> <p className="summary__name">
{profileInfo?.fio || profileInfo?.username}{" "} {profileInfo?.fio || profileInfo?.username},{" "}
{profileInfo.specification} {profileInfo.specification} разработчик
</p> </p>
<hr /> <hr />
<div className="summary__direction">Front End</div> <div className="summary__direction">Front End</div>

View File

@ -36,7 +36,6 @@
} }
&__info { &__info {
width: 100%;
min-height: 110px; min-height: 110px;
background: white; background: white;
border-radius: 12px; border-radius: 12px;
@ -65,12 +64,6 @@
align-items: center; align-items: center;
column-gap: 20px; column-gap: 20px;
hr {
background-color: #00000081;
height: 30px;
width: 1px;
}
@media (max-width: 825px) { @media (max-width: 825px) {
column-gap: 20px; column-gap: 20px;
} }
@ -138,7 +131,6 @@
border-radius: 44px; border-radius: 44px;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
padding: 5px 17px;
} }
&__git { &__git {

View File

@ -170,10 +170,6 @@ export const ViewReport = () => {
</div> </div>
)} )}
</div> </div>
{loader && <Loader width={75} height={75} />}
{Boolean(taskText.length) && (
<div className="view-report__content">
<div className="view-report__switch-date"> <div className="view-report__switch-date">
<div onClick={() => previousDay()}> <div onClick={() => previousDay()}>
<Link <Link
@ -196,9 +192,9 @@ export const ViewReport = () => {
}`} }`}
> >
<Link <Link
to={`/profile/calendar/view/${getCreatedDate( to={`/profile/calendar/view/${getCreatedDate(nextReportDay)}/${
nextReportDay params.id
)}/${params.id}`} }`}
> >
<div className={`view-report__switch-date__next switch-date`}> <div className={`view-report__switch-date__next switch-date`}>
<img src={arrowSwitchDate} alt="arrow" /> <img src={arrowSwitchDate} alt="arrow" />
@ -206,36 +202,55 @@ export const ViewReport = () => {
</Link> </Link>
</div> </div>
</div> </div>
<div className="view-report__done"> {loader && <Loader width={75} height={75} />}
<h2>Выполненные задачи</h2> {Boolean(taskText.length) && (
<div className="view-report__content">
<div className="table__container">
<table className="view-report__done">
<thead>
<tr>
<th>
<p>Выполненные задачи</p>
</th>
<th>
<p>Время</p>
</th>
</tr>
</thead>
<tbody>
{taskText.length && {taskText.length &&
taskText.map((task, index) => { taskText.map((task, index) => {
return ( return (
<div className="view-report__done-task" key={task.id}> <tr key={task.id}>
<div> <td>
<p> <p>
{index + 1}. {task.task} {index + 1}. {task.task}
</p> </p>
</div> </td>
<td>
<div className="view-report__done__hours__item"> <div className="view-report__done__hours__item">
<span>{Math.floor(task.hours)}</span> <span>{Math.floor(task.hours)}</span>
<p className="hours"> <p className="hours">
/ {hourOfNum(Math.floor(task.hours))} {hourOfNum(Math.floor(task.hours))}
</p> </p>
</div> </div>
<div>Задача ( On Review ) - Уведомления </div> </td>
</div> </tr>
); );
})} })}
<tr>
<p className="view-report__done-total-hours"> <td></td>
Всего: {totalHours} <span>/ {hourOfNum(totalHours)}</span> <td>
</p> <span>
Всего: {totalHours} {hourOfNum(totalHours)}
</span>
</td>
</tr>
</tbody>
</table>
</div> </div>
<div className="view-report__addition">
{Boolean(difficulties.length) && ( {Boolean(difficulties.length) && (
<div className="view-report__addition-item"> <div className="view-report__item">
<h3>Возникшие сложности</h3> <h3>Возникшие сложности</h3>
{difficulties.map((item, index) => { {difficulties.map((item, index) => {
return <p key={index}>{item}</p>; return <p key={index}>{item}</p>;
@ -243,7 +258,7 @@ export const ViewReport = () => {
</div> </div>
)} )}
{Boolean(tomorrowTask.length) && ( {Boolean(tomorrowTask.length) && (
<div className="view-report__addition-item"> <div className="view-report__item">
<h3>Что планируется сделать завтра?</h3> <h3>Что планируется сделать завтра?</h3>
{tomorrowTask.map((item, index) => { {tomorrowTask.map((item, index) => {
return <p key={index}>{item}</p>; return <p key={index}>{item}</p>;
@ -251,7 +266,6 @@ export const ViewReport = () => {
</div> </div>
)} )}
</div> </div>
</div>
)} )}
{!Boolean(taskText.length) && !loader && ( {!Boolean(taskText.length) && !loader && (
<div className="view-report__no-task"> <div className="view-report__no-task">

View File

@ -16,12 +16,6 @@
} }
} }
&__content {
background-color: #ffffff;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
&__info { &__info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -66,8 +60,7 @@
display: flex; display: flex;
margin-top: 20px; margin-top: 20px;
background: #ffffff; background: #ffffff;
border-top-left-radius: 12px; border-radius: 12px;
border-top-right-radius: 12px;
padding: 20px 33px; padding: 20px 33px;
align-items: center; align-items: center;
column-gap: 20px; column-gap: 20px;
@ -128,10 +121,10 @@
&__switch-date { &__switch-date {
display: flex; display: flex;
margin: 20px 0;
justify-content: center;
column-gap: 30px; column-gap: 30px;
align-items: center; align-items: center;
padding: 20px 20px 20px 30px;
border-bottom: #eeeeee 1px solid;
@media (max-width: 500px) { @media (max-width: 500px) {
column-gap: 0; column-gap: 0;
@ -139,16 +132,17 @@
} }
p { p {
font-weight: 500; font-weight: 400;
font-size: 22px; font-size: 18px;
color: #2e3a59; line-height: 32px;
color: #000000;
} }
.switch-date { .switch-date {
width: 20px; width: 48px;
height: 47px; height: 48px;
background-color: #e5f1fb; background: #8dc63f;
border-radius: 5px; border-radius: 50px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -192,34 +186,6 @@
border-collapse: separate; border-collapse: separate;
border-spacing: 28px 0; border-spacing: 28px 0;
h2 {
color: #1458dd;
font-size: 20px;
font-weight: 500;
padding: 35px;
}
&-task {
display: grid;
grid-template-columns: 40% 15% 30%;
align-items: center;
font-size: 15px;
font-weight: 500;
color: #111112;
justify-content: space-evenly;
margin: 0 0 20px 0;
div {
background-color: #f4f7ff;
height: 61px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
padding: 10px 20px;
}
}
@media (max-width: 1205px) { @media (max-width: 1205px) {
display: grid; display: grid;
border-collapse: collapse; border-collapse: collapse;
@ -343,17 +309,57 @@
} }
&__item { &__item {
display: flex;
column-gap: 25px;
align-items: center;
min-width: 155px;
.hours {
font-size: 15px;
@media (max-width: 1170px) {
font-size: 13px;
text-align: center;
}
}
@media (max-width: 900px) {
column-gap: 0;
justify-content: space-between;
min-width: auto;
width: 100%;
}
@media (max-width: 775px) {
flex-direction: column;
justify-content: center;
row-gap: 10px;
}
span { span {
max-width: 48px;
height: 48px;
background: #8dc63f;
border-radius: 50px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700; font-weight: 700;
font-size: 20px; font-size: 22px;
line-height: 32px;
color: #000000; color: #000000;
margin: 5px; width: 100%;
@media (max-width: 900px) {
max-width: 40px;
height: 40px;
}
} }
p { p {
font-weight: 400; font-weight: 400;
font-size: 15px; font-size: 12px;
color: #6f6f6f; line-height: 32px;
} }
} }
@ -363,42 +369,25 @@
line-height: 32px; line-height: 32px;
} }
} }
&-total-hours {
color: #000000;
font-size: 20px;
font-weight: 500;
margin: 35px 0 0 30px;
span {
font-weight: 400;
font-size: 15px;
color: #6f6f6f;
}
}
} }
&__addition { &__item {
display: grid;
grid-template-columns: 55% 45%;
column-gap: 15px;
padding: 35px;
&-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
row-gap: 10px; row-gap: 10px;
background-color: #f4f7ff; background: #ffffff;
border-radius: 10px; border-radius: 12px;
margin: 20px 0;
padding: 15px; padding: 15px;
h3 { h3 {
color: #1458dd;
font-weight: 500; font-weight: 500;
font-size: 20px; font-size: 22px;
line-height: 32px;
@media (max-width: 650px) { @media (max-width: 650px) {
font-size: 16px; font-size: 16px;
line-height: 20px;
} }
} }
@ -411,6 +400,9 @@
} }
} }
} }
&__item:last-child {
margin-bottom: 0;
} }
&__no-task { &__no-task {