table-pagination #29

Merged
nik.polishuk merged 2 commits from table-pagination into main 2024-03-31 20:40:00 +03:00
2 changed files with 281 additions and 45 deletions
Showing only changes of commit caaee74810 - Show all commits

View File

@ -1,5 +1,11 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; 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 { import {
getProjects, getProjects,
@ -9,7 +15,7 @@ import {
setToggleTab setToggleTab
} from "@redux/projectsTrackerSlice"; } from "@redux/projectsTrackerSlice";
import { caseOfNum } from "@utils/helper"; import { caseOfNum, urlForLocal } from "@utils/helper";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
@ -28,7 +34,7 @@ import addProjectImg from "assets/icons/addProjectImg.svg";
import archiveTrackerProjects from "assets/icons/archiveTrackerProjects.svg"; import archiveTrackerProjects from "assets/icons/archiveTrackerProjects.svg";
import arrowViewReport from "assets/icons/arrows/arrowViewReport.svg"; import arrowViewReport from "assets/icons/arrows/arrowViewReport.svg";
import filterIcon from "assets/icons/filterIcon.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 project from "assets/icons/trackerProject.svg";
import tasks from "assets/icons/trackerTasks.svg"; import tasks from "assets/icons/trackerTasks.svg";
import archive from "assets/images/archiveIcon.png"; 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 statusTimeTask from "assets/images/statusTimeTask.svg";
import "./tracker.scss"; import "./tracker.scss";
import { Link } from "react-router-dom";
import rightArrow from "assets/icons/arrows/arrowRight.svg";
export const Tracker = () => { export const Tracker = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const projects = useSelector(getProjects); const projects = useSelector(getProjects);
const tab = useSelector(getToggleTab); const tab = useSelector(getToggleTab);
const theme = useTheme(getTheme());
const [nodes, setNodes] = useState([]);
const [initialNodes, setInitialNodes] = useState([]);
const [allTasks, setAllTasks] = useState([]); const [allTasks, setAllTasks] = useState([]);
const [filteredAllTasks, setFilteredAllTasks] = useState([]); const [filteredAllTasks, setFilteredAllTasks] = useState([]);
const [loader, setLoader] = useState(false); const [loader, setLoader] = useState(false);
const [filterCompleteTasks, setFilterCompleteTasks] = useState([]); const [filterCompleteTasks, setFilterCompleteTasks] = useState([]);
const [allCompletedTasks, setAllCompletedTasks] = useState([]); const [allCompletedTasks, setAllCompletedTasks] = useState([]);
const [search, setSearch] = useState("");
const [modalCreateProject, setModalCreateProject] = useState(false); 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(() => { useEffect(() => {
setLoader(true); setLoader(true);
apiRequest( apiRequest(
@ -84,6 +169,8 @@ export const Tracker = () => {
: []; : [];
setAllTasks(allTasks); setAllTasks(allTasks);
setFilteredAllTasks(allTasks); setFilteredAllTasks(allTasks);
setNodes(allTasks)
setInitialNodes(allTasks)
setAllCompletedTasks(completedTasks); setAllCompletedTasks(completedTasks);
setFilterCompleteTasks(completedTasks); setFilterCompleteTasks(completedTasks);
}) })
@ -238,53 +325,106 @@ export const Tracker = () => {
: "tracker__tabs__content__projects" : "tracker__tabs__content__projects"
} }
> >
<div className="task-list__head"> {/*<div className="task-list__head">*/}
<div className="task-list__tasks-period"> {/* <div className="task-list__tasks-period">*/}
<div className="month-period"> {/* <div className="month-period">*/}
<p> {/* <p>*/}
{25} - {35} {/* {25} - {35}*/}
</p> {/* </p>*/}
<h3>Сентября,</h3> {/* <h3>Сентября,</h3>*/}
<h3>2023</h3> {/* <h3>2023</h3>*/}
</div> {/* </div>*/}
<div className="buttons-month"> {/* <div className="buttons-month">*/}
<button> {/* <button>*/}
<img src={arrowViewReport} alt="<"></img> {/* <img src={arrowViewReport} alt="<"></img>*/}
</button> {/* </button>*/}
<button> {/* <button>*/}
<img src={arrowViewReport} alt=">"></img> {/* <img src={arrowViewReport} alt=">"></img>*/}
</button> {/* </button>*/}
</div> {/* </div>*/}
</div> {/* </div>*/}
<div className="task-list__head__search"> {/* <div className="task-list__head__search">*/}
<img src={search} alt="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 <input
type="text" type="text"
placeholder="Найти задачу" placeholder="Поиск по задачам"
onChange={(event) => filterAllTask(event)} value={search}
onChange={handleSearch}
/> />
</div> </div>
<CompactTable
<div className="task-list__filters"> columns={COLUMNS}
<BaseButton styles={"task-list__filters-filter"}> data={data}
<img src={filterIcon} alt="#" /> theme={theme}
<p>Фильтр</p> sort={sort}
</BaseButton> pagination={pagination}
<BaseButton styles={"task-list__filters-clear"}>
<p> Очистить фильтр</p>
</BaseButton>
</div>
</div>
{loader && <Loader style="green" />}
<AllTaskTableTracker
loader={loader}
filteredAllTasks={filteredAllTasks}
projects={projects}
/> />
<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">
<div className="task-list__time-compited"> <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;
}
}
}
} }