table-pagination #29
@ -1,5 +1,11 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
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 { getCorrectDate } from "@utils/calendarHelper";
|
||||
|
||||
import {
|
||||
getProjects,
|
||||
@ -9,7 +15,7 @@ import {
|
||||
setToggleTab
|
||||
} from "@redux/projectsTrackerSlice";
|
||||
|
||||
import { caseOfNum } from "@utils/helper";
|
||||
import { caseOfNum, urlForLocal } from "@utils/helper";
|
||||
|
||||
import { apiRequest } from "@api/request";
|
||||
|
||||
@ -28,7 +34,7 @@ import addProjectImg from "assets/icons/addProjectImg.svg";
|
||||
import archiveTrackerProjects from "assets/icons/archiveTrackerProjects.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";
|
||||
@ -38,20 +44,99 @@ import noProjects from "assets/images/noProjects.png";
|
||||
import statusTimeTask from "assets/images/statusTimeTask.svg";
|
||||
|
||||
import "./tracker.scss";
|
||||
import { Link } from "react-router-dom";
|
||||
import rightArrow from "assets/icons/arrows/arrowRight.svg";
|
||||
|
||||
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 +169,8 @@ export const Tracker = () => {
|
||||
: [];
|
||||
setAllTasks(allTasks);
|
||||
setFilteredAllTasks(allTasks);
|
||||
setNodes(allTasks)
|
||||
setInitialNodes(allTasks)
|
||||
setAllCompletedTasks(completedTasks);
|
||||
setFilterCompleteTasks(completedTasks);
|
||||
})
|
||||
@ -238,53 +325,106 @@ 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" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Найти задачу"
|
||||
onChange={(event) => filterAllTask(event)}
|
||||
{/* <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="Поиск по задачам"
|
||||
value={search}
|
||||
onChange={handleSearch}
|
||||
/>
|
||||
</div>
|
||||
<CompactTable
|
||||
columns={COLUMNS}
|
||||
data={data}
|
||||
theme={theme}
|
||||
sort={sort}
|
||||
pagination={pagination}
|
||||
/>
|
||||
</div>
|
||||
<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>
|
||||
</>
|
||||
}
|
||||
|
||||
<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}
|
||||
/>
|
||||
{/*<AllTaskTableTracker*/}
|
||||
{/* loader={loader}*/}
|
||||
{/* filteredAllTasks={filteredAllTasks}*/}
|
||||
{/* projects={projects}*/}
|
||||
{/*/>*/}
|
||||
|
||||
<div className="task-list__time">
|
||||
<div className="task-list__time-compited">
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user