2023-05-31 08:36:15 +03:00
|
|
|
|
import ru from "date-fns/locale/ru";
|
|
|
|
|
import React, { useEffect, useState } from "react";
|
|
|
|
|
import DatePicker, { registerLocale } from "react-datepicker";
|
|
|
|
|
import "react-datepicker/dist/react-datepicker.css";
|
2023-05-24 15:34:43 +03:00
|
|
|
|
import { useSelector } from "react-redux";
|
|
|
|
|
import { Link, Navigate, useNavigate } from "react-router-dom";
|
2023-01-16 20:42:27 +03:00
|
|
|
|
|
2023-05-31 08:36:15 +03:00
|
|
|
|
import { getReportDate } from "@redux/reportSlice";
|
2023-01-16 20:42:27 +03:00
|
|
|
|
|
2023-05-30 10:10:34 +03:00
|
|
|
|
import { apiRequest } from "@api/request";
|
2023-05-31 08:36:15 +03:00
|
|
|
|
|
|
|
|
|
import { Footer } from "@components/Common/Footer/Footer";
|
|
|
|
|
import { Loader } from "@components/Common/Loader/Loader";
|
2023-05-30 10:10:34 +03:00
|
|
|
|
import { Navigation } from "@components/Navigation/Navigation";
|
2023-05-31 08:36:15 +03:00
|
|
|
|
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
|
|
|
|
|
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
|
2023-01-16 20:42:27 +03:00
|
|
|
|
|
2023-05-31 08:36:15 +03:00
|
|
|
|
import arrow from "assets/icons/arrows/left-arrow.png";
|
2023-05-30 10:10:34 +03:00
|
|
|
|
import calendarIcon from "assets/icons/calendar.svg";
|
|
|
|
|
import ellipse from "assets/icons/ellipse.png";
|
|
|
|
|
import remove from "assets/icons/remove.svg";
|
2023-01-16 20:42:27 +03:00
|
|
|
|
|
2023-05-31 08:36:15 +03:00
|
|
|
|
import {
|
|
|
|
|
getCorrectDate,
|
|
|
|
|
getCreatedDate,
|
|
|
|
|
hourOfNum,
|
|
|
|
|
} from "../Calendar/calendarHelper";
|
2023-05-24 15:34:43 +03:00
|
|
|
|
import "./reportForm.scss";
|
2023-05-31 08:36:15 +03:00
|
|
|
|
|
|
|
|
|
registerLocale("ru", ru);
|
2021-06-21 17:41:26 +03:00
|
|
|
|
|
|
|
|
|
const ReportForm = () => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
if (localStorage.getItem("role_status") === "18") {
|
|
|
|
|
return <Navigate to="/profile" replace />;
|
2023-02-27 16:50:32 +03:00
|
|
|
|
}
|
2023-05-24 15:34:43 +03:00
|
|
|
|
const navigate = useNavigate();
|
2023-01-09 20:53:23 +03:00
|
|
|
|
const reportDate = useSelector(getReportDate);
|
2022-10-19 15:41:11 +03:00
|
|
|
|
|
2023-02-07 15:11:11 +03:00
|
|
|
|
useEffect(() => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
initListeners();
|
|
|
|
|
}, []);
|
2023-02-07 15:11:11 +03:00
|
|
|
|
|
2023-01-09 20:53:23 +03:00
|
|
|
|
const [isFetching, setIsFetching] = useState(false);
|
2023-05-24 15:34:43 +03:00
|
|
|
|
const [reportSuccess, setReportSuccess] = useState("");
|
|
|
|
|
const [startDate, setStartDate] = useState(
|
2023-12-04 21:08:15 +03:00
|
|
|
|
reportDate ? new Date(reportDate._d) : new Date()
|
2023-05-24 15:34:43 +03:00
|
|
|
|
);
|
2023-02-07 15:11:11 +03:00
|
|
|
|
const [datePickerOpen, setDatePickerOpen] = useState(false);
|
2021-06-22 18:00:52 +03:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
const [inputs, setInputs] = useState([
|
|
|
|
|
{ task: "", hours_spent: "", minutes_spent: 0 },
|
|
|
|
|
]);
|
|
|
|
|
const [troublesInputValue, setTroublesInputValue] = useState("");
|
|
|
|
|
const [scheduledInputValue, setScheduledInputValue] = useState("");
|
2021-06-22 18:00:52 +03:00
|
|
|
|
|
2021-11-30 16:00:58 +02:00
|
|
|
|
const addInput = () => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
setInputs((prev) => [
|
|
|
|
|
...prev,
|
|
|
|
|
{ task: "", hours_spent: "", minutes_spent: 0 },
|
|
|
|
|
]);
|
2023-01-09 20:53:23 +03:00
|
|
|
|
};
|
2021-06-22 18:00:52 +03:00
|
|
|
|
|
2023-02-07 15:11:11 +03:00
|
|
|
|
const initListeners = () => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
document.addEventListener("click", closeByClickingOut);
|
|
|
|
|
};
|
2023-02-07 15:11:11 +03:00
|
|
|
|
|
|
|
|
|
const closeByClickingOut = (event) => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
const path = event.path || (event.composedPath && event.composedPath());
|
2023-02-07 15:11:11 +03:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
if (
|
|
|
|
|
event &&
|
|
|
|
|
!path.find(
|
|
|
|
|
(div) =>
|
|
|
|
|
div.classList &&
|
|
|
|
|
(div.classList.contains("report-form__block-img") ||
|
2023-12-04 21:08:15 +03:00
|
|
|
|
div.classList.contains("react-datepicker-popper"))
|
2023-05-24 15:34:43 +03:00
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
setDatePickerOpen(false);
|
2023-02-07 15:11:11 +03:00
|
|
|
|
}
|
2023-05-24 15:34:43 +03:00
|
|
|
|
};
|
2023-02-07 15:11:11 +03:00
|
|
|
|
|
2023-01-09 20:53:23 +03:00
|
|
|
|
const totalHours = inputs.reduce((a, b) => a + b.hours_spent, 0);
|
2022-10-19 15:41:11 +03:00
|
|
|
|
|
2021-11-30 16:00:58 +02:00
|
|
|
|
const deleteInput = (indexRemove) => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
setInputs((prev) => prev.filter((el, index) => index !== indexRemove));
|
2023-01-09 20:53:23 +03:00
|
|
|
|
};
|
2021-06-22 18:00:52 +03:00
|
|
|
|
|
2023-01-16 19:12:44 +03:00
|
|
|
|
const handler = () => {
|
2023-03-01 00:28:58 +03:00
|
|
|
|
for (let input of inputs) {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
if (!input.task || !input.hours_spent) {
|
|
|
|
|
setReportSuccess("Заполните задачи");
|
|
|
|
|
setTimeout(() => setReportSuccess(""), 2000);
|
|
|
|
|
return;
|
2023-03-01 00:28:58 +03:00
|
|
|
|
}
|
2023-01-24 19:11:24 +03:00
|
|
|
|
}
|
2023-05-24 15:34:43 +03:00
|
|
|
|
apiRequest("/reports/create", {
|
|
|
|
|
method: "POST",
|
2023-01-17 22:14:05 +03:00
|
|
|
|
data: {
|
2023-01-16 19:12:44 +03:00
|
|
|
|
tasks: inputs,
|
|
|
|
|
difficulties: troublesInputValue,
|
|
|
|
|
tomorrow: scheduledInputValue,
|
2023-02-07 15:11:11 +03:00
|
|
|
|
created_at: getCreatedDate(startDate),
|
2023-01-16 19:12:44 +03:00
|
|
|
|
status: 1,
|
|
|
|
|
},
|
2023-05-31 11:24:46 +03:00
|
|
|
|
}).then(() => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
setReportSuccess("Отчет отправлен");
|
2023-01-24 19:11:24 +03:00
|
|
|
|
setTimeout(() => {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
setReportSuccess("");
|
|
|
|
|
navigate("/profile/calendar");
|
|
|
|
|
}, 1000);
|
2023-01-16 19:12:44 +03:00
|
|
|
|
setInputs(() => []);
|
2023-05-24 15:34:43 +03:00
|
|
|
|
setTroublesInputValue("");
|
|
|
|
|
setScheduledInputValue("");
|
2023-01-16 19:12:44 +03:00
|
|
|
|
setIsFetching(false);
|
2023-05-24 15:34:43 +03:00
|
|
|
|
setInputs(() => [{ task: "", hours_spent: "", minutes_spent: 0 }]);
|
|
|
|
|
});
|
2023-01-16 19:12:44 +03:00
|
|
|
|
};
|
|
|
|
|
|
2021-06-21 17:41:26 +03:00
|
|
|
|
return (
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<section className="report-form">
|
|
|
|
|
<ProfileHeader />
|
|
|
|
|
<Navigation />
|
|
|
|
|
<div className="container">
|
|
|
|
|
<ProfileBreadcrumbs
|
|
|
|
|
links={[
|
|
|
|
|
{ name: "Главная", link: "/profile" },
|
|
|
|
|
{ name: "Ваша отчетность", link: "/profile/calendar" },
|
|
|
|
|
{ name: "Страница добавления нового отчета", link: "/report" },
|
|
|
|
|
]}
|
|
|
|
|
/>
|
|
|
|
|
<h2 className="summary__title">
|
|
|
|
|
Ваши отчеты - <span>добавить отчет</span>
|
|
|
|
|
</h2>
|
|
|
|
|
<div>
|
|
|
|
|
<div className="report__head">
|
|
|
|
|
<Link className="calendar__back" to={`/profile/calendar`}>
|
|
|
|
|
<img src={arrow} alt="" />
|
|
|
|
|
<p>Вернуться</p>
|
|
|
|
|
</Link>
|
2023-01-13 15:53:07 +03:00
|
|
|
|
</div>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
</div>
|
2023-01-13 15:53:07 +03:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<div className="report-form__content">
|
|
|
|
|
<div className="report-form__block">
|
|
|
|
|
<div className="report-form__block-title">
|
|
|
|
|
<h2>Добавление отчета за день</h2>
|
|
|
|
|
<h3>Дата заполнения отчета:</h3>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
className="report-form__block-img"
|
|
|
|
|
onClick={() => setDatePickerOpen(true)}
|
|
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
className="report-form__calendar-icon"
|
|
|
|
|
src={calendarIcon}
|
|
|
|
|
alt=""
|
2023-02-07 15:11:11 +03:00
|
|
|
|
/>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
{getCorrectDate(startDate)}
|
|
|
|
|
</div>
|
|
|
|
|
<DatePicker
|
|
|
|
|
className="datePicker"
|
|
|
|
|
open={datePickerOpen}
|
|
|
|
|
locale="ru"
|
|
|
|
|
selected={startDate}
|
|
|
|
|
onChange={(date) => {
|
|
|
|
|
setDatePickerOpen(false);
|
|
|
|
|
setStartDate(date);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<div className="report-form__task-list">
|
|
|
|
|
<img src={ellipse} alt="" />
|
|
|
|
|
<span>Какие задачи были выполнены?</span>
|
2021-06-21 17:41:26 +03:00
|
|
|
|
</div>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
</div>
|
2021-06-22 18:00:52 +03:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<div className="row">
|
|
|
|
|
<div className="col-8">
|
|
|
|
|
<div className="report-form__task-header">
|
|
|
|
|
<p className="report-form__task-title--description">
|
|
|
|
|
Краткое описание задачи
|
|
|
|
|
</p>
|
2023-12-04 21:08:15 +03:00
|
|
|
|
<p className="report-form__task-title--hours">Кол-во часов</p>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
</div>
|
2021-11-30 16:00:58 +02:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
{inputs.map((input, index) => {
|
|
|
|
|
return (
|
|
|
|
|
<form
|
|
|
|
|
id={"input"}
|
|
|
|
|
key={`input__${index}`}
|
|
|
|
|
className="report-form__task-form"
|
|
|
|
|
>
|
|
|
|
|
<div className="report-form__task-number">{index + 1}.</div>
|
|
|
|
|
<div className="report-form__task-input report-form__task-input--description">
|
|
|
|
|
<input
|
|
|
|
|
value={inputs[index].task}
|
|
|
|
|
className={
|
|
|
|
|
!input.task && reportSuccess === "Заполните задачи"
|
|
|
|
|
? "checkTask"
|
|
|
|
|
: ""
|
|
|
|
|
}
|
|
|
|
|
name="text"
|
|
|
|
|
type="text"
|
|
|
|
|
onChange={(e) =>
|
|
|
|
|
setInputs(
|
|
|
|
|
inputs.map((input, inputIndex) => {
|
|
|
|
|
return index === inputIndex
|
|
|
|
|
? {
|
|
|
|
|
...input,
|
|
|
|
|
task: e.target.value,
|
|
|
|
|
}
|
|
|
|
|
: input;
|
2023-12-04 21:08:15 +03:00
|
|
|
|
})
|
2023-05-24 15:34:43 +03:00
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="report-form__task-input report-form__task-input--hours">
|
|
|
|
|
<input
|
|
|
|
|
value={inputs[index].hours_spent}
|
|
|
|
|
className={
|
|
|
|
|
!input.hours_spent &&
|
|
|
|
|
reportSuccess === "Заполните задачи"
|
|
|
|
|
? "checkTask"
|
|
|
|
|
: ""
|
|
|
|
|
}
|
|
|
|
|
name="number"
|
|
|
|
|
type="number"
|
|
|
|
|
min="1"
|
|
|
|
|
onChange={(e) =>
|
|
|
|
|
setInputs(
|
|
|
|
|
inputs.map((input, inputIndex) => {
|
|
|
|
|
return index === inputIndex
|
2023-01-13 15:53:07 +03:00
|
|
|
|
? {
|
2023-05-24 15:34:43 +03:00
|
|
|
|
...input,
|
|
|
|
|
hours_spent: Number(e.target.value),
|
|
|
|
|
}
|
|
|
|
|
: input;
|
2023-12-04 21:08:15 +03:00
|
|
|
|
})
|
2023-05-24 15:34:43 +03:00
|
|
|
|
)
|
2023-02-17 15:19:49 +03:00
|
|
|
|
}
|
2023-05-24 15:34:43 +03:00
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
{index > 0 && (
|
|
|
|
|
<div className="report-form__task-remove">
|
|
|
|
|
<img
|
|
|
|
|
onClick={() => deleteInput(index)}
|
|
|
|
|
src={remove}
|
|
|
|
|
alt=""
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</form>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2021-11-30 16:00:58 +02:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<div className="report-form__form-add">
|
|
|
|
|
<p className="addMore" onClick={addInput}>
|
|
|
|
|
+
|
|
|
|
|
</p>
|
2023-12-04 18:00:12 +03:00
|
|
|
|
<span>Добавить ещё</span>
|
2023-01-13 15:53:07 +03:00
|
|
|
|
</div>
|
2023-01-09 20:53:23 +03:00
|
|
|
|
</div>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
</div>
|
2021-06-22 18:00:52 +03:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<div className="row">
|
|
|
|
|
<div className="col-12">
|
|
|
|
|
<div className="report-form__input-box">
|
|
|
|
|
<div className="report-form__troubles">
|
|
|
|
|
<img src={ellipse} alt="" />
|
|
|
|
|
<span>Какие сложности возникли?</span>
|
|
|
|
|
</div>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
value={troublesInputValue}
|
|
|
|
|
onChange={(e) => setTroublesInputValue(e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
<div className="report-form__scheduled">
|
|
|
|
|
<img src={ellipse} alt="" />
|
|
|
|
|
<span>Что планируется сделать завтра?</span>
|
|
|
|
|
</div>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
value={scheduledInputValue}
|
|
|
|
|
onChange={(e) => setScheduledInputValue(e.target.value)}
|
|
|
|
|
/>
|
2023-01-09 20:53:23 +03:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2021-06-22 18:00:52 +03:00
|
|
|
|
</div>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<div className="row">
|
|
|
|
|
<div className="col-12">
|
|
|
|
|
<div className="report-form__footer">
|
|
|
|
|
<button
|
|
|
|
|
className="report-form__footer-btn"
|
|
|
|
|
onClick={() => handler()}
|
|
|
|
|
>
|
|
|
|
|
{isFetching ? <Loader /> : "Отправить"}
|
|
|
|
|
</button>
|
|
|
|
|
<p className="report-form__footer-text">
|
2023-12-04 21:08:15 +03:00
|
|
|
|
Всего за день:{" "}
|
2023-05-24 15:34:43 +03:00
|
|
|
|
<span>
|
|
|
|
|
{totalHours} {hourOfNum(totalHours)}
|
|
|
|
|
</span>
|
|
|
|
|
</p>
|
|
|
|
|
{reportSuccess && (
|
|
|
|
|
<p
|
|
|
|
|
className={`report-form__footer-done ${
|
|
|
|
|
reportSuccess === "Заполните задачи" ? "errorText" : ""
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
{reportSuccess}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2023-01-09 20:53:23 +03:00
|
|
|
|
</div>
|
2021-06-22 18:00:52 +03:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-05-24 15:34:43 +03:00
|
|
|
|
</div>
|
|
|
|
|
<Footer />
|
|
|
|
|
</section>
|
|
|
|
|
);
|
2023-01-09 20:53:23 +03:00
|
|
|
|
};
|
2021-06-21 17:41:26 +03:00
|
|
|
|
|
2023-05-24 15:34:43 +03:00
|
|
|
|
export default ReportForm;
|