Compare commits

...

2 Commits

Author SHA1 Message Date
Mikola
35f76abe60 all tasks table 2024-03-31 20:38:16 +03:00
Mikola
caaee74810 all tasks table 2024-03-31 20:38:01 +03:00
2 changed files with 315 additions and 45 deletions

View File

@ -1,5 +1,11 @@
import { getTheme } from "@table-library/react-table-library/baseline";
import { CompactTable } from "@table-library/react-table-library/compact";
import { usePagination } from "@table-library/react-table-library/pagination";
import { useSort } from "@table-library/react-table-library/sort";
import { useTheme } from "@table-library/react-table-library/theme";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import {
getProjects,
@ -9,7 +15,8 @@ import {
setToggleTab
} from "@redux/projectsTrackerSlice";
import { caseOfNum } from "@utils/helper";
import { getCorrectDate } from "@utils/calendarHelper";
import { caseOfNum, urlForLocal } from "@utils/helper";
import { apiRequest } from "@api/request";
@ -26,9 +33,10 @@ import ProjectTicket from "@components/ProjectTicket/ProjectTicket";
import addProjectImg from "assets/icons/addProjectImg.svg";
import archiveTrackerProjects from "assets/icons/archiveTrackerProjects.svg";
import rightArrow from "assets/icons/arrows/arrowRight.svg";
import arrowViewReport from "assets/icons/arrows/arrowViewReport.svg";
import filterIcon from "assets/icons/filterIcon.svg";
import search from "assets/icons/serchIcon.png";
import searchImg from "assets/icons/serchIcon.png";
import project from "assets/icons/trackerProject.svg";
import tasks from "assets/icons/trackerTasks.svg";
import archive from "assets/images/archiveIcon.png";
@ -43,15 +51,110 @@ export const Tracker = () => {
const dispatch = useDispatch();
const projects = useSelector(getProjects);
const tab = useSelector(getToggleTab);
const theme = useTheme(getTheme());
const [nodes, setNodes] = useState([]);
const [initialNodes, setInitialNodes] = useState([]);
const [allTasks, setAllTasks] = useState([]);
const [filteredAllTasks, setFilteredAllTasks] = useState([]);
const [loader, setLoader] = useState(false);
const [filterCompleteTasks, setFilterCompleteTasks] = useState([]);
const [allCompletedTasks, setAllCompletedTasks] = useState([]);
const [search, setSearch] = useState("");
const [modalCreateProject, setModalCreateProject] = useState(false);
const COLUMNS = [
{
label: "Задача",
renderCell: (item) => (
<p dangerouslySetInnerHTML={{ __html: item.title }}></p>
),
sort: { sortKey: "NAME" }
},
{
label: "Создано",
renderCell: (item) => <span>{getCorrectDate(item.created_at)}</span>,
sort: { sortKey: "CREATE" }
},
{
label: "Дедлайн",
renderCell: (item) => (
<span>
{item.dead_line ? getCorrectDate(item.dead_line) : "Без дедлайна"}
</span>
),
sort: { sortKey: "DEADLINE" }
},
{
label: "Потраченное время",
renderCell: (item) => (
<span>
{item.timers.length
? getSpendTime(item.timers)
: "Трекер не был включен"}
</span>
),
sort: { sortKey: "SPEND" }
}
];
let data = { nodes };
const sort = useSort(
data,
{
onChange: onSortChange
},
{
sortFns: {
NAME: (array) => array.sort((a, b) => a.title.localeCompare(b.title)),
CREATE: (array) =>
array.sort((a, b) => new Date(a.created_at) - new Date(b.created_at)),
DEADLINE: (array) =>
array.sort((a, b) => new Date(a.dead_line) - new Date(b.dead_line)),
SPEND: (array) =>
array.sort(
(a, b) =>
getSpendTime(a.timers, true) - getSpendTime(b.timers, true)
)
}
}
);
const pagination = usePagination(data, {
state: {
page: 0,
size: 11
}
});
function getSpendTime(times, seconds) {
let timerSeconds = 0;
times.forEach((time) => {
timerSeconds += time.deltaSeconds;
});
if (seconds) {
return timerSeconds;
}
return `${Math.floor(timerSeconds / 60 / 60)}:${Math.floor(
(timerSeconds / 60) % 60
)}:${timerSeconds % 60}`;
}
function onSortChange(action, state) {
console.log(action, state);
}
const handleSearch = (event) => {
setSearch(event.target.value);
setNodes(
initialNodes.filter((item) =>
item.title.toLowerCase().includes(event.target.value.toLowerCase())
)
);
};
useEffect(() => {
setLoader(true);
apiRequest(
@ -84,6 +187,8 @@ export const Tracker = () => {
: [];
setAllTasks(allTasks);
setFilteredAllTasks(allTasks);
setNodes(allTasks);
setInitialNodes(allTasks);
setAllCompletedTasks(completedTasks);
setFilterCompleteTasks(completedTasks);
})
@ -238,53 +343,122 @@ export const Tracker = () => {
: "tracker__tabs__content__projects"
}
>
<div className="task-list__head">
<div className="task-list__tasks-period">
<div className="month-period">
<p>
{25} - {35}
</p>
<h3>Сентября,</h3>
<h3>2023</h3>
</div>
{/*<div className="task-list__head">*/}
{/* <div className="task-list__tasks-period">*/}
{/* <div className="month-period">*/}
{/* <p>*/}
{/* {25} - {35}*/}
{/* </p>*/}
{/* <h3>Сентября,</h3>*/}
{/* <h3>2023</h3>*/}
{/* </div>*/}
<div className="buttons-month">
<button>
<img src={arrowViewReport} alt="<"></img>
</button>
<button>
<img src={arrowViewReport} alt=">"></img>
</button>
</div>
</div>
{/* <div className="buttons-month">*/}
{/* <button>*/}
{/* <img src={arrowViewReport} alt="<"></img>*/}
{/* </button>*/}
{/* <button>*/}
{/* <img src={arrowViewReport} alt=">"></img>*/}
{/* </button>*/}
{/* </div>*/}
{/* </div>*/}
<div className="task-list__head__search">
<img src={search} alt="search" />
{/* <div className="task-list__head__search">*/}
{/* <img src={search} alt="search" />*/}
{/* <input*/}
{/* type="text"*/}
{/* placeholder="Найти задачу"*/}
{/* onChange={(event) => filterAllTask(event)}*/}
{/* />*/}
{/* </div>*/}
{/* <div className="task-list__filters">*/}
{/* <BaseButton styles={"task-list__filters-filter"}>*/}
{/* <img src={filterIcon} alt="#" />*/}
{/* <p>Фильтр</p>*/}
{/* </BaseButton>*/}
{/* <BaseButton styles={"task-list__filters-clear"}>*/}
{/* <p> Очистить фильтр</p>*/}
{/* </BaseButton>*/}
{/* </div>*/}
{/*</div>*/}
{loader ? (
<Loader style="green" />
) : (
<>
<div className="table__search">
<img src={searchImg} alt="search" />
<input
type="text"
placeholder="Найти задачу"
onChange={(event) => filterAllTask(event)}
placeholder="Поиск по задачам"
value={search}
onChange={handleSearch}
/>
</div>
<div className="task-list__filters">
<BaseButton styles={"task-list__filters-filter"}>
<img src={filterIcon} alt="#" />
<p>Фильтр</p>
</BaseButton>
<BaseButton styles={"task-list__filters-clear"}>
<p> Очистить фильтр</p>
</BaseButton>
</div>
</div>
{loader && <Loader style="green" />}
<AllTaskTableTracker
loader={loader}
filteredAllTasks={filteredAllTasks}
projects={projects}
<CompactTable
columns={COLUMNS}
data={data}
theme={theme}
sort={sort}
pagination={pagination}
/>
<div className="table__pagination">
<button
className={
pagination.state.page === 0 ? "switch disable" : "switch"
}
type="button"
disabled={pagination.state.page === 0}
onClick={() =>
pagination.fns.onSetPage(pagination.state.page - 1)
}
>
{"<"}
</button>
<span className="table__pages">
{pagination.state.getPages(data.nodes).map((_, index) => (
<button
key={index}
type="button"
className={
pagination.state.page === index
? "page page--active "
: "page"
}
onClick={() => pagination.fns.onSetPage(index)}
>
{index + 1}
</button>
))}
</span>
<button
className={
pagination.state.page + 1 ===
pagination.state.getPages(data.nodes).length
? "switch disable"
: "switch"
}
type="button"
disabled={
pagination.state.page + 1 ===
pagination.state.getPages(data.nodes).length
}
onClick={() =>
pagination.fns.onSetPage(pagination.state.page + 1)
}
>
{">"}
</button>
</div>
</>
)}
{/*<AllTaskTableTracker*/}
{/* loader={loader}*/}
{/* filteredAllTasks={filteredAllTasks}*/}
{/* projects={projects}*/}
{/*/>*/}
<div className="task-list__time">
<div className="task-list__time-compited">

View File

@ -1937,4 +1937,100 @@
}
}
}
.table {
&__search {
display: flex;
background: #F0F2F5;
border-radius: 5px;
width: 100%;
padding: 14px 12px;
column-gap: 10px;
align-items: center;
margin-bottom: 20px;
img {
width: 20px;
height: 20px;
}
input {
background: none;
border: none;
outline: none;
font-size: 16px;
color: #9BABC5;
width: 100%;
&::placeholder {
color: #9BABC5;
}
}
}
&__pagination {
display: flex;
margin: 25px auto 0;
column-gap: 12px;
button {
font-size: 14px;
width: 32px;
border-radius: 5px;
height: 32px;
color: #2E3A59;
}
.switch {
border: none;
background: #F0F2F5;
font-weight: 600;
}
.disable {
opacity: 0.7;
}
}
&__pages {
display: flex;
column-gap: 4px;
color: black;
background: white;
.page {
border: 1px solid #E8ECF8;
background: none;
&--active {
border: none;
background: #9DA65D;
color: white;
}
}
}
}
table {
grid-template-columns: minmax(0px, 2fr) minmax(0px, 1fr) minmax(0px, 1fr) minmax(0px, 1fr);
th {
border-top: none;
border-bottom: 1px solid #F5F6F8;
color: #2E3A59;
padding: 0 7.5px 15px;
}
td {
padding: 22px 7.5px;
color: #2E3A59;
border-top: none;
p {
max-width: 430px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
}