Spaces:
Running
Running
import "./DocsList.scss"; | |
import { FC, useState } from "react"; | |
import { GoDownload, GoSearch, GoTrash, GoTriangleDown, GoTriangleUp } from "react-icons/go"; | |
import { SortDirectionsTooltipMap, StatusMap } from "@/shared/constants"; | |
import Button from "@/components/generics/button/Button"; | |
import { DocsListProps } from "./DocsList.interface"; | |
import Input from "@/components/generics/input/Input"; | |
import { Pagination } from "../../pagination/Pagination"; | |
import { SortDirections } from "@/api/documents/types"; | |
import Spinner from "@/components/generics/spinner/Spinner"; | |
import Tag from "@/components/generics/tag/Tag"; | |
import Tooltip from "@/components/generics/tooltip/Tooltip"; | |
import { downloadDocument } from "@/api/documents/documentsApi"; | |
import { useGetDataset } from "@/api/documents/hooks"; | |
export const DocsList: FC<DocsListProps> = ({ datasetId, handleDeleteFile }) => { | |
const [page, setPage] = useState<number>(0); | |
const [pageSize, setPageSize] = useState<number>(10); | |
const [searchInput, setSearchInput] = useState<string | undefined>(undefined); | |
const [search, setSearch] = useState<string | undefined>(undefined); | |
const [sort, setSort] = useState<undefined | { field: string; direction: SortDirections }[]>(undefined); | |
const { data: datasetData, isFetching } = useGetDataset(datasetId ?? -1, { page, page_size: pageSize, search, sort }); | |
const toggleSort = (field: string) => { | |
setSort((prevSort) => { | |
if (prevSort?.length && prevSort?.length > 0) { | |
const newSort = [...prevSort]; | |
const existingFieldIndex = prevSort?.findIndex((e) => e.field === field); | |
const currentDirection = prevSort[existingFieldIndex]?.direction; | |
if (existingFieldIndex != null && existingFieldIndex !== -1) { | |
const newSort = [...prevSort]; | |
if (currentDirection === SortDirections.asc) { | |
newSort[existingFieldIndex] = { field, direction: SortDirections.desc }; | |
return newSort; | |
} else if (currentDirection === SortDirections.desc) { | |
newSort.splice(existingFieldIndex, 1); | |
return newSort; | |
} | |
} else { | |
newSort.push({ field, direction: SortDirections.asc }); | |
} | |
return newSort; | |
} else { | |
return [{ field, direction: SortDirections.asc }]; | |
} | |
}); | |
}; | |
const handleEnterPress = (event: React.KeyboardEvent<HTMLInputElement>) => { | |
if (event.key === "Enter" && searchInput) { | |
setSearch(searchInput); | |
setPage(0); | |
} | |
}; | |
const sorting = (field: string) => { | |
const currentDirection = sort?.find((e) => e.field === field)?.direction; | |
return ( | |
<Tooltip text={SortDirectionsTooltipMap[currentDirection ?? "empty"]}> | |
<Button | |
onClick={() => toggleSort(field)} | |
icon={ | |
<div className="sort-btn"> | |
<GoTriangleUp viewBox="0 0 20 20" className={currentDirection === SortDirections.asc ? "active" : ""} /> | |
<GoTriangleDown | |
viewBox="0 0 20 20" | |
className={currentDirection === SortDirections.desc ? "arrow-down active" : "arrow-down"} | |
/> | |
</div> | |
} | |
buttonType="link" | |
/> | |
</Tooltip> | |
); | |
}; | |
return ( | |
<> | |
<div className="docs-search-input"> | |
<Input | |
name="" | |
placeholder="Введите название документа" | |
value={searchInput} | |
onSetValue={setSearchInput} | |
onKeyDown={handleEnterPress} | |
extra={ | |
<Tooltip text="Поиск"> | |
<Button | |
buttonType="link" | |
icon={<GoSearch style={{ width: "19px", height: "19px" }} />} | |
onClick={() => { | |
setSearch(searchInput); | |
setPage(0); | |
}} | |
/> | |
</Tooltip> | |
} | |
/> | |
</div> | |
<div className="docs-table-container" style={{ position: "relative" }}> | |
{isFetching && ( | |
<div className="loading-overlay"> | |
<Spinner /> | |
</div> | |
)} | |
<table className="docs-table"> | |
<thead> | |
<tr> | |
<th style={{ width: "50%" }}> | |
<div className="name-with-sort"> | |
<span>Название документа</span> | |
{sorting("name")} | |
</div> | |
</th> | |
<th> | |
<div className="name-with-sort"> | |
<span>Владелец</span> | |
{sorting("owner")} | |
</div> | |
</th> | |
<th> | |
<div className="name-with-sort"> | |
<span>Статус</span> | |
{sorting("status")} | |
</div> | |
</th> | |
<th></th> | |
</tr> | |
</thead> | |
<tbody> | |
{datasetData?.data.page.map((doc) => ( | |
<tr key={doc.id}> | |
<td>{doc.name}</td> | |
<td>{doc.owner}</td> | |
<td> | |
<Tag text={doc.status} type={StatusMap[doc.status]} /> | |
</td> | |
<td> | |
<div className="actions"> | |
<Button | |
onClick={() => downloadDocument(datasetData.id, doc.id.toString(), doc.name)} | |
icon={<GoDownload />} | |
buttonType="link" | |
/> | |
<Button onClick={() => handleDeleteFile(doc.id)} icon={<GoTrash />} buttonType="link" /> | |
</div> | |
</td> | |
</tr> | |
))} | |
</tbody> | |
</table> | |
</div> | |
<Pagination | |
total={datasetData?.data.total ?? 0} | |
pageNumber={datasetData?.data.pageNumber ? datasetData?.data.pageNumber : page} | |
pageSize={datasetData?.data.pageSize ?? 20} | |
setPageSize={setPageSize} | |
setPage={setPage} | |
/> | |
</> | |
); | |
}; | |