Merge branch 'main' of https://github.com/apuc/outstaffing-react into fix-tracker-and-statistics

This commit is contained in:
MaxOvs19 2023-10-11 12:22:00 +03:00
commit b226ee88bd
9 changed files with 149 additions and 114 deletions

View File

@ -243,6 +243,26 @@
} }
} }
.selectDays {
border-style: dashed !important;
&:hover {
background-color: #edf1ff !important;
}
}
.selectedDay {
background-color: #edf1ff !important;
&:hover {
background-color: #edf1ff !important;
}
}
.disable {
pointer-events: none;
}
.before { .before {
background-color: #e5f9b6 !important; background-color: #e5f9b6 !important;
} }
@ -272,66 +292,6 @@
font-weight: 500; font-weight: 500;
position: relative; position: relative;
.react-datepicker-wrapper {
display: none;
}
.react-datepicker__tab-loop {
position: absolute;
top: 50px;
}
.react-datepicker-popper {
transform: none !important;
}
.datePicker {
visibility: hidden;
height: 0;
padding: 0;
width: 0;
position: absolute;
}
.react-datepicker {
border: 1px solid #398208;
}
.react-datepicker-popper {
top: -15px !important;
}
.react-datepicker__current-month {
font-size: 14px;
font-family: "LabGrotesque", sans-serif;
text-transform: capitalize;
}
.react-datepicker__header {
padding: 5px 0 10px;
border-bottom: 1px solid #398208;
}
.react-datepicker__day {
font-size: 14px;
width: 35px;
font-family: "LabGrotesque", sans-serif;
}
.react-datepicker__day-name {
font-size: 14px;
width: 35px;
font-family: "LabGrotesque", sans-serif;
}
.react-datepicker__triangle {
transform: translate(140px, 0px) !important;
&:before {
border-bottom-color: #398208 !important;
}
}
.select { .select {
border-radius: 5px; border-radius: 5px;
border: 1px solid #c4c4c4; border: 1px solid #c4c4c4;
@ -341,4 +301,11 @@
text-align: center; text-align: center;
min-width: 350px; min-width: 350px;
} }
.close {
cursor: pointer;
margin-left: 8px;
width: 14px;
height: 14px;
}
} }

View File

@ -536,9 +536,6 @@ export const TicketFullScreen = () => {
></TrackerModal> ></TrackerModal>
<div className="tasks__head__persons"> <div className="tasks__head__persons">
{projectInfo.projectUsers?.length > 3 && (
<span className="countPersons">+1...</span>
)}
<div className="projectPersons"> <div className="projectPersons">
{projectInfo.projectUsers?.length && {projectInfo.projectUsers?.length &&
projectInfo.projectUsers.slice(0, 3).map((person) => { projectInfo.projectUsers.slice(0, 3).map((person) => {
@ -555,6 +552,9 @@ export const TicketFullScreen = () => {
); );
})} })}
</div> </div>
{projectInfo.projectUsers?.length > 3 && (
<span className="countPersons">+1</span>
)}
<span <span
className="addPerson" className="addPerson"
onClick={() => { onClick={() => {

View File

@ -541,7 +541,7 @@
.exit { .exit {
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
top: 15px; top: 36px;
right: 20px; right: 20px;
width: 13px; width: 13px;
height: 13px; height: 13px;

View File

@ -36,11 +36,16 @@ export const ProfileCalendar = () => {
const [reports, setReports] = useState([]); const [reports, setReports] = useState([]);
const [totalHours, setTotalHours] = useState(0); const [totalHours, setTotalHours] = useState(0);
const [loader, setLoader] = useState(true); const [loader, setLoader] = useState(true);
const [startRangeDays, setStartRangeDays] = useState(false);
function setValueHandler(value) { function setValueHandler(value) {
setValue(value); setValue(value);
} }
function toggleStartRangeDays() {
setStartRangeDays(!startRangeDays);
}
useEffect(() => { useEffect(() => {
dispatch(setRequestDate(getReports(moment()))); dispatch(setRequestDate(getReports(moment())));
}, []); }, []);
@ -115,6 +120,8 @@ export const ProfileCalendar = () => {
value={value} value={value}
reports={reports} reports={reports}
totalHours={totalHours} totalHours={totalHours}
startRangeDays={startRangeDays}
toggleRangeDays={toggleStartRangeDays}
/> />
</div> </div>
</div> </div>

View File

@ -1,9 +1,6 @@
import ru from "date-fns/locale/ru";
import moment from "moment"; import moment from "moment";
import "moment/locale/ru"; import "moment/locale/ru";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import DatePicker, { registerLocale } from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@ -29,26 +26,38 @@ import ShortReport from "@components/ShortReport/ShortReport";
import arrow from "assets/icons/arrows/arrowCalendar.png"; import arrow from "assets/icons/arrows/arrowCalendar.png";
import calendarIcon from "assets/icons/calendar.svg"; import calendarIcon from "assets/icons/calendar.svg";
import close from "assets/icons/closeProjectPersons.svg";
import rectangle from "assets/images/rectangle__calendar.png"; import rectangle from "assets/images/rectangle__calendar.png";
registerLocale("ru", ru);
// eslint-disable-next-line react/display-name // eslint-disable-next-line react/display-name
export const ProfileCalendarComponent = React.memo( export const ProfileCalendarComponent = React.memo(
({ value, setValueHandler, reports, totalHours }) => { ({
value,
setValueHandler,
reports,
totalHours,
startRangeDays,
toggleRangeDays,
}) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [currentDay] = useState(moment()); const [currentDay] = useState(moment());
const [calendar, setCalendar] = useState([]); const [calendar, setCalendar] = useState([]);
const [month, setMonth] = useState(""); const [month, setMonth] = useState("");
const [shortReport, setShortReport] = useState(false); const [shortReport, setShortReport] = useState(false);
const [startDate, setStartDate] = useState(new Date()); const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null); const [endDate, setEndDate] = useState(null);
const [datePickerOpen, setDatePickerOpen] = useState(false);
const [totalRangeHours, setTotalRangeHours] = useState(0); const [totalRangeHours, setTotalRangeHours] = useState(0);
const [selectedRangeDays, setSelectedRangeDays] = useState({});
useEffect(() => { useEffect(() => {
setCalendar(calendarHelper(value)); setCalendar(calendarHelper(value));
calendarHelper(value).map((array) => {
setSelectedRangeDays((prevState) => ({
...prevState,
[array[0]]: false,
}));
});
}, [value]); }, [value]);
useEffect(() => { useEffect(() => {
@ -103,10 +112,10 @@ export const ProfileCalendarComponent = React.memo(
return value.clone().add(1, "month"); return value.clone().add(1, "month");
} }
function reportsByDate(start, end) { function reportsByDate(endDay) {
const requestDates = `fromDate=${getCorrectYYMMDD( const requestDates = `fromDate=${getCorrectYYMMDD(
start startDate._d
)}&toDate=${getCorrectYYMMDD(end)}`; )}&toDate=${getCorrectYYMMDD(endDay._d)}`;
apiRequest( apiRequest(
`/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem( `/reports/reports-by-date?${requestDates}&user_card_id=${localStorage.getItem(
"cardId" "cardId"
@ -124,6 +133,43 @@ export const ProfileCalendarComponent = React.memo(
}); });
} }
function rangeDays(day) {
if (!startDate) {
setStartDate(day);
} else {
setEndDate(day);
reportsByDate(day);
}
}
function onMouseRangeDays(day) {
let selectRange = {};
for (let curDay in selectedRangeDays) {
if (
day > startDate &&
new Date(curDay) > startDate &&
new Date(curDay) < day
) {
selectRange[curDay] = true;
} else {
selectRange[curDay] = false;
}
}
setSelectedRangeDays(selectRange);
}
function resetRangeDays() {
setStartDate(null);
setEndDate(null);
setTotalRangeHours(0);
calendarHelper(value).map((array) => {
setSelectedRangeDays((prevState) => ({
...prevState,
[array[0]]: false,
}));
});
}
return ( return (
<div className="calendar-component"> <div className="calendar-component">
<div className="calendar-component__header"> <div className="calendar-component__header">
@ -183,16 +229,35 @@ export const ProfileCalendarComponent = React.memo(
week.map((day) => ( week.map((day) => (
<button <button
onClick={() => { onClick={() => {
dispatch(setReportDate(day)); if (startRangeDays) {
setShortReport(true); rangeDays(day);
dispatch(setSendRequest(true)); } else {
dispatch(setReportDate(day));
setShortReport(true);
dispatch(setSendRequest(true));
}
}}
onMouseEnter={() => {
if (startRangeDays && startDate && !endDate) {
onMouseRangeDays(day);
}
}} }}
key={day} key={day}
className={dayStyles(day)} className={
startRangeDays
? `selectDays ${
startDate === day || endDate === day
? "selectedDay"
: ""
} ${endDate ? "disable" : ""} ${
selectedRangeDays[day] ? "selectedDay" : ""
}`
: dayStyles(day)
}
name={day.format("dddd")} name={day.format("dddd")}
id="btn" id="btn"
> >
<Link to={correctRoute(day)}> <Link to={startRangeDays ? "#" : correctRoute(day)}>
<img <img
className={"calendar__icon"} className={"calendar__icon"}
src={calendarIcon} src={calendarIcon}
@ -209,35 +274,29 @@ export const ProfileCalendarComponent = React.memo(
<span <span
className="select" className="select"
onClick={() => { onClick={() => {
setDatePickerOpen(!datePickerOpen); if (startRangeDays) resetRangeDays();
toggleRangeDays();
}} }}
> >
{endDate {endDate
? `${getCorrectDate(startDate)} - ${getCorrectDate(endDate)}` ? `${getCorrectDate(startDate)} - ${getCorrectDate(endDate)}`
: "Выбрать диапазон"} : "Выбрать диапазон"}
</span> </span>
<DatePicker
selected={startDate}
open={datePickerOpen}
locale="ru"
startDate={startDate}
endDate={endDate}
onChange={(dates) => {
const [start, end] = dates;
setStartDate(start);
setEndDate(end);
if (end) {
setDatePickerOpen(false);
reportsByDate(start, end);
}
}}
selectsRange
/>
<span> <span>
{totalRangeHours {totalRangeHours
? `${totalRangeHours} ${hourOfNum(totalRangeHours)}` ? `${totalRangeHours} ${hourOfNum(totalRangeHours)}`
: "0 часов"} : "0 часов"}
</span> </span>
{endDate && (
<img
className="close"
src={close}
alt="close"
onClick={() => {
resetRangeDays();
}}
/>
)}
</div> </div>
{shortReport && <ShortReport />} {shortReport && <ShortReport />}
</div> </div>

View File

@ -368,9 +368,6 @@ export const ProjectTracker = () => {
: "tasks__head__persons noProjectUsers" : "tasks__head__persons noProjectUsers"
} }
> >
{projectBoard.projectUsers?.length > 3 && (
<span className="countPersons">+1...</span>
)}
{Boolean(projectBoard.projectUsers?.length) && ( {Boolean(projectBoard.projectUsers?.length) && (
<div className="projectPersons"> <div className="projectPersons">
{projectBoard.projectUsers.slice(0, 3).map((person) => { {projectBoard.projectUsers.slice(0, 3).map((person) => {
@ -388,6 +385,9 @@ export const ProjectTracker = () => {
})} })}
</div> </div>
)} )}
{projectBoard.projectUsers?.length > 3 && (
<span className="countPersons">+1</span>
)}
<span <span
className="addPerson" className="addPerson"
onClick={() => { onClick={() => {

View File

@ -71,8 +71,8 @@ export const Tracker = () => {
apiRequest( apiRequest(
`/task/get-user-tasks?user_id=${localStorage.getItem("id")}` `/task/get-user-tasks?user_id=${localStorage.getItem("id")}`
).then((el) => { ).then((el) => {
const allTasks = el.filter((item) => item.status !== 0); const allTasks = el ? el.filter((item) => item.status !== 0) : [];
const completedTasks = el.filter((item) => item.status === 0); const completedTasks = el ? el.filter((item) => item.status === 0) : [];
setAllTasks(allTasks); setAllTasks(allTasks);
setFilteredAllTasks(allTasks); setFilteredAllTasks(allTasks);
setAllCompletedTasks(completedTasks); setAllCompletedTasks(completedTasks);
@ -179,7 +179,8 @@ export const Tracker = () => {
{loader && <Loader style="green" />} {loader && <Loader style="green" />}
{Boolean(projects.length) && {projects &&
Boolean(projects.length) &&
!loader && !loader &&
projects.map((project, index) => { projects.map((project, index) => {
return project.status !== 10 ? ( return project.status !== 10 ? (
@ -188,10 +189,11 @@ export const Tracker = () => {
"" ""
); );
})} })}
{(!Boolean(projects.length) || {typeof projects === "object" &&
!Boolean( (!Boolean(projects.length) ||
projects.filter((project) => project.status !== 10).length !Boolean(
)) && projects.filter((project) => project.status !== 10).length
)) &&
!loader && ( !loader && (
<div className="no-projects"> <div className="no-projects">
<div className="no-projects__createNew"> <div className="no-projects__createNew">
@ -216,7 +218,7 @@ export const Tracker = () => {
</div> </div>
</div> </div>
)} )}
{Boolean(projects.length) && !loader && ( {projects && Boolean(projects.length) && !loader && (
<> <>
<BaseButton <BaseButton
styles="createProjectBtn" styles="createProjectBtn"

View File

@ -321,7 +321,7 @@
.projectPersons { .projectPersons {
display: flex; display: flex;
position: relative; position: relative;
left: -10px; left: 5px;
img { img {
position: relative; position: relative;
display: flex; display: flex;
@ -358,7 +358,7 @@
color: #252c32; color: #252c32;
border: 1px solid #dde2e4; border: 1px solid #dde2e4;
background: white; background: white;
left: -6px; left: -20px;
} }
.addPerson { .addPerson {

View File

@ -65,9 +65,9 @@ export function getCorrectRequestDate(date) {
} }
export function getCorrectYYMMDD(date) { export function getCorrectYYMMDD(date) {
const yyyy = String(date.getUTCFullYear()); const yyyy = String(date.getFullYear());
const mm = String(date.getUTCMonth() + 1).padStart(2, "0"); const mm = String(date.getMonth() + 1).padStart(2, "0");
const dd = String(date.getUTCDate()).padStart(2, "0"); const dd = String(date.getDate()).padStart(2, "0");
return `${yyyy}-${mm}-${dd}`; return `${yyyy}-${mm}-${dd}`;
} }