complete ModalTicketToReport

This commit is contained in:
Никита Губарь 2024-07-07 16:25:07 +03:00
parent 4c7e21b430
commit 83b6d155f8
6 changed files with 147 additions and 37 deletions

View File

@ -88,20 +88,19 @@ export const ModalTiсket = ({
minute: 0, minute: 0,
seconds: 0 seconds: 0
}); });
const additionalData = { const additionalData = {
difficulties: "", user_id: task.executor_id,
project_id: task.project_id, project_id: task.project_id,
status: task.status, company_id: null,
tasks: [ task: {
{ hours_spent: currentTimerCount.hours,
hours_spent: currentTimerCount.hours, minutes_spent: currentTimerCount.minute,
minutes_spent: currentTimerCount.minute, id: task.id,
task: task.title description: task.description
} }
],
tomorrow: "",
user_id: task.executor_id
}; };
const [timerId, setTimerId] = useState(null); const [timerId, setTimerId] = useState(null);
const [taskFiles, setTaskFiles] = useState([]); const [taskFiles, setTaskFiles] = useState([]);
const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers); const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers);
@ -128,7 +127,6 @@ export const ModalTiсket = ({
const currentUrl = window.location.pathname; const currentUrl = window.location.pathname;
const newUrl = currentUrl.replace(/\/task\/\d+$/, ""); const newUrl = currentUrl.replace(/\/task\/\d+$/, "");
window.history.replaceState({}, "", newUrl); window.history.replaceState({}, "", newUrl);
// Восстанавливаем скролл при закрытии модального окна
document.body.style.overflow = "auto"; document.body.style.overflow = "auto";
console.log(task); console.log(task);
}; };

View File

@ -1,33 +1,92 @@
import axios from "axios";
import { format } from "date-fns"; import { format } from "date-fns";
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import DatePicker from "react-datepicker"; import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"; import "react-datepicker/dist/react-datepicker.css";
import { useNavigate } from "react-router";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import { useNotification } from "@hooks/useNotification";
import BaseButton from "@components/Common/BaseButton/BaseButton"; import BaseButton from "@components/Common/BaseButton/BaseButton";
import "./modalTicketToReport.scss"; import "./modalTicketToReport.scss";
const ModalTicketToReport = ({ show, onClose, additionalData }) => { const ModalTicketToReport = ({ show, onClose, additionalData }) => {
const [date, setDate] = useState(new Date()); const [date, setDate] = useState(new Date());
const [inputValue, setInputValue] = useState(0);
const [taskDescription, setTaskDescription] = useState("");
const navigate = useNavigate();
const { showNotification } = useNotification();
useEffect(() => {
if (additionalData.task.description) {
const parser = new DOMParser();
const doc = parser.parseFromString(
additionalData.task.description,
"text/html"
);
setTaskDescription(doc.body.textContent || "");
}
}, [additionalData.task.description]);
useEffect(() => {
const hoursSpent = additionalData.task.hours_spent;
setInputValue(hoursSpent);
}, [additionalData.task.hours_spent]);
const handleSubmit = async () => { const handleSubmit = async () => {
const formattedDate = format(date, "yyyy-MM-dd"); const formattedDate = format(date, "yyyy-MM-dd");
const data = {
created_at: formattedDate,
...additionalData
};
console.log(data);
try { apiRequest("https://back.itguild.info/api/reports/find-or-create", {
await apiRequest("https://back.itguild.info/api/reports/create", { method: "GET",
method: "POST", params: {
data: data user_id: additionalData.user_id,
created_at: formattedDate,
project_id: additionalData.project_id,
company_id: additionalData.company_id
}
})
.then((res) => {
apiRequest("https://back.itguild.info/api/reports/add-task-to-report", {
method: "POST",
data: {
report_id: res[0].id,
tasks: taskDescription,
hours_spent: inputValue,
minutes_spent: additionalData.task.minutes_spent
}
})
.then(() => {
showNotification({
show: true,
text: "Отчет успешно создан",
type: "true"
});
})
.catch((error) => {
console.error("Error:", error);
});
})
.catch((error) => {
console.error("Error:", error);
}); });
} catch (error) { };
console.error("Error:", error);
const toTheReport = async () => {
const success = await handleSubmit();
if (success) {
navigate(
`/profile/calendar/view/${additionalData.created_at}/${additionalData.user_id}`
);
}
};
const handleInputChange = (e) => {
const value = Number(e.target.value);
if (value !== 0) {
setInputValue(value);
} }
}; };
@ -43,7 +102,9 @@ const ModalTicketToReport = ({ show, onClose, additionalData }) => {
<div className="modal-report-close" onClick={onClose}></div> <div className="modal-report-close" onClick={onClose}></div>
<h2>Выгрузка в отчет</h2> <h2>Выгрузка в отчет</h2>
<div className="modal-report-date-picker"> <div className="modal-report-date-picker">
<label htmlFor="date-picker">Дата отчета:</label>
<DatePicker <DatePicker
id="date-picker"
className="datePicker" className="datePicker"
locale="ru" locale="ru"
selected={date} selected={date}
@ -51,6 +112,14 @@ const ModalTicketToReport = ({ show, onClose, additionalData }) => {
dateFormat="dd/MM/yyyy" dateFormat="dd/MM/yyyy"
/> />
</div> </div>
<label className="modal-report-input-time">
Время выполнения:
<input
type="number"
value={inputValue}
onChange={handleInputChange}
/>
</label>
<div className="modal-report__buttons"> <div className="modal-report__buttons">
<BaseButton <BaseButton
@ -61,7 +130,7 @@ const ModalTicketToReport = ({ show, onClose, additionalData }) => {
</BaseButton> </BaseButton>
<BaseButton <BaseButton
styles={`button-add add-person-btn ${show ? "" : "disable"}`} styles={`button-add add-person-btn ${show ? "" : "disable"}`}
onClick={handleSubmit} onClick={toTheReport}
> >
Выгрузить и перейти в отчет Выгрузить и перейти в отчет
</BaseButton> </BaseButton>

View File

@ -22,7 +22,7 @@
padding: 20px; padding: 20px;
border-radius: 5px; border-radius: 5px;
position: relative; position: relative;
max-width: 500px; max-width: 600px;
height: 500px; height: 500px;
width: 100%; width: 100%;
display: flex; display: flex;
@ -78,8 +78,8 @@
} }
.react-datepicker-popper { .react-datepicker-popper {
top: -150px !important; top: -90px !important;
left: 180px !important; left: 250px !important;
z-index: 10; z-index: 10;
@media (max-width: 880px) { @media (max-width: 880px) {
@ -152,14 +152,20 @@
} }
} }
&-input-time {
display: flex;
flex-direction: column;
width: 30%;
}
&__buttons { &__buttons {
display: flex; display: flex;
justify-content: center; justify-content: center;
column-gap: 100px; column-gap: 60px;
margin: 30px 0; margin: 30px 0;
.button { .button {
height: 47px; width: 220px;
font-size: 15px; font-size: 15px;
line-height: 16px; line-height: 16px;
} }

View File

@ -49,6 +49,7 @@ import watch from "assets/icons/watch.svg";
import archive from "assets/images/archiveIcon.webp"; import archive from "assets/images/archiveIcon.webp";
import avatarMok from "assets/images/avatarMok.webp"; import avatarMok from "assets/images/avatarMok.webp";
import ModalTicketToReport from "../ModalTicketToReport/ModalTicketToReport";
import "./ticketFullScreen.scss"; import "./ticketFullScreen.scss";
registerLocale("ru", ru); registerLocale("ru", ru);
@ -71,6 +72,18 @@ export const TicketFullScreen = () => {
minute: 0, minute: 0,
seconds: 0 seconds: 0
}); });
const additionalData = {
user_id: taskInfo.executor_id,
project_id: taskInfo.project_id,
company_id: null,
task: {
hours_spent: currentTimerCount.hours,
minutes_spent: currentTimerCount.minute,
id: taskInfo.id,
description: taskInfo.description
}
};
const profileInfo = useSelector(getProfileInfo); const profileInfo = useSelector(getProfileInfo);
const [timerId, setTimerId] = useState(null); const [timerId, setTimerId] = useState(null);
const [dropListOpen, setDropListOpen] = useState(false); const [dropListOpen, setDropListOpen] = useState(false);
@ -90,6 +103,15 @@ export const TicketFullScreen = () => {
const [correctProjectTags, setCorrectProjectTags] = useState([]); const [correctProjectTags, setCorrectProjectTags] = useState([]);
const { showNotification } = useNotification(); const { showNotification } = useNotification();
const [commentSendDisable, setCommentSendDisable] = useState(false); const [commentSendDisable, setCommentSendDisable] = useState(false);
const [showModalToReport, setShowModalToReport] = useState(false);
const openModalToReport = () => {
setShowModalToReport(!showModalToReport);
};
const closeModalToReport = () => {
setShowModalToReport(!showModalToReport);
};
const priority = { const priority = {
2: "Высокий", 2: "Высокий",
@ -1096,7 +1118,7 @@ export const TicketFullScreen = () => {
</div> </div>
<div className="workers_box-bottom"> <div className="workers_box-bottom">
<div <div
className={editOpen ? "edit" : ""} className={`bottom-button ${editOpen ? "edit" : ""}`}
onClick={() => { onClick={() => {
if (editOpen) { if (editOpen) {
editTask(); editTask();
@ -1108,30 +1130,39 @@ export const TicketFullScreen = () => {
<img src={edit} alt="edit"></img> <img src={edit} alt="edit"></img>
<p>{editOpen ? "сохранить" : "редактировать"}</p> <p>{editOpen ? "сохранить" : "редактировать"}</p>
</div> </div>
<div> <div className="bottom-button">
<img src={link} alt="link"></img> <img src={link} alt="link"></img>
<p onClick={copyTicketLink}>ссылка на задачу</p> <p onClick={copyTicketLink}>ссылка на задачу</p>
</div> </div>
<div className="bottom-button">
<img src={link}></img>
<p onClick={openModalToReport}>выгрузка в отчет</p>
<ModalTicketToReport
show={showModalToReport}
onClose={closeModalToReport}
additionalData={additionalData}
></ModalTicketToReport>
</div>
<div <div
onClick={archiveTask} onClick={archiveTask}
className={ className={`bottom-button ${
profileInfo.id_user === projectInfo.owner_id || profileInfo.id_user === projectInfo.owner_id ||
profileInfo.id_user === taskInfo.user_id profileInfo.id_user === taskInfo.user_id
? "" ? ""
: "disable" : "disable"
} }`}
> >
<img src={archive} alt="arch"></img> <img src={archive} alt="arch"></img>
<p>в архив</p> <p>в архив</p>
</div> </div>
<div <div
onClick={deleteTask} onClick={deleteTask}
className={ className={`bottom-button ${
profileInfo.id_user === projectInfo.owner_id || profileInfo.id_user === projectInfo.owner_id ||
profileInfo.id_user === taskInfo.user_id profileInfo.id_user === taskInfo.user_id
? "" ? ""
: "disable" : "disable"
} }`}
> >
<img src={del} alt="delete"></img> <img src={del} alt="delete"></img>
<p>удалить</p> <p>удалить</p>

View File

@ -18,6 +18,10 @@
.ticket { .ticket {
border: none; border: none;
justify-content: center; justify-content: center;
margin: 20px auto;
padding: 30px;
max-height: none;
max-width: 1200px;
&-whith { &-whith {
width: 850px !important; width: 850px !important;

View File

@ -15,12 +15,14 @@ import { Summary } from "@pages/Summary/Summary";
import { Tracker } from "@pages/Tracker/Tracker"; import { Tracker } from "@pages/Tracker/Tracker";
import { ViewReport } from "@pages/ViewReport/ViewReport"; import { ViewReport } from "@pages/ViewReport/ViewReport";
import TicketFullScreen from "@components/Modal/Tracker/TicketFullScreen/TicketFullScreen";
import { ProfileCalendar } from "@components/ProfileCalendar/ProfileCalendar"; import { ProfileCalendar } from "@components/ProfileCalendar/ProfileCalendar";
import { ReportForm } from "@components/ReportForm/ReportForm"; import { ReportForm } from "@components/ReportForm/ReportForm";
export const DeveloperPage = () => { export const DeveloperPage = () => {
return ( return (
<Routes> <Routes>
<Route exact path="/tracker/task/:id" element={<TicketFullScreen />} />
<Route <Route
exact exact
path="/tracker/project/:id/task/:taskId" path="/tracker/project/:id/task/:taskId"