Skip to content
Snippets Groups Projects

Draft: Feature/project info publications modal + table

Closed Tadeusz Miesiąc requested to merge feature/project-info-publications-modal into development
25 files
+ 436
6
Compare changes
  • Side-by-side
  • Inline
Files
25
import { ONE, ZERO } from '@/constants/common';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import {
totalSizeSelector,
paginationSelector,
isLoadingSelector,
sortColumnSelector,
sortOrderSelector,
} from '@/redux/publications/publications.selectors';
import { getPublications } from '@/redux/publications/publications.thunks';
import { Button } from '@/shared/Button';
import {
PaginationState,
createColumnHelper,
flexRender,
getCoreRowModel,
useReactTable,
OnChangeFn,
} from '@tanstack/react-table';
import { useState } from 'react';
import { SortByHeader } from './SortByHeader';
import { DEFAULT_PAGE_SIZE } from './PublicationsTable.constants';
export type PublicationsTableData = {
pubmedId: string;
title: string;
authors: string[];
journal: string;
year: number;
elementsOnMap: string;
submaps: string;
};
const columnHelper = createColumnHelper<PublicationsTableData>();
const columns = [
columnHelper.accessor(row => row.pubmedId, {
id: 'pubmedId',
header: () => <SortByHeader columnName="pubmedId">Pubmed ID</SortByHeader>,
size: 128,
}),
columnHelper.accessor(row => row.title, {
id: 'title',
header: () => <SortByHeader columnName="title">Title</SortByHeader>,
size: 288,
}),
columnHelper.accessor(row => row.authors, {
id: 'authors',
header: () => <SortByHeader columnName="authors">Authors</SortByHeader>,
size: 200,
}),
columnHelper.accessor(row => row.journal, {
id: 'journal',
header: () => <SortByHeader columnName="journal">Journal</SortByHeader>,
size: 168,
}),
columnHelper.accessor(row => row.year, {
id: 'year',
header: () => <SortByHeader columnName="year">Year</SortByHeader>,
size: 80,
}),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
columnHelper.accessor(row => row.elementsOnMap, { header: 'Elements on map', size: 176 }),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
columnHelper.accessor(row => row.submaps, { header: 'Submaps', size: 144 }),
];
type PublicationsTableProps = {
data: PublicationsTableData[];
};
export const PublicationsTable = ({ data }: PublicationsTableProps): JSX.Element => {
const dispatch = useAppDispatch();
const pagesCount = useAppSelector(totalSizeSelector);
const isPublicationsLoading = useAppSelector(isLoadingSelector);
const sortColumn = useAppSelector(sortColumnSelector);
const sortOrder = useAppSelector(sortOrderSelector);
const reduxPagination = useAppSelector(paginationSelector);
const [pagination, setPagination] = useState(reduxPagination);
// useEffect(() => {
// dispatch(getPublications({ page: pagination.pageIndex, length: DEFAULT_PAGE_SIZE }));
// }, [pagination, dispatch]);
const onPaginationChange: OnChangeFn<PaginationState> = updater => {
/** updating state this way is forced by table library */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const nextState = updater(pagination);
dispatch(
getPublications({
page: nextState.pageIndex,
length: DEFAULT_PAGE_SIZE,
sortColumn,
sortOrder,
// TODO
// search: get search from redux
}),
);
setPagination(nextState);
};
const table = useReactTable({
state: {
pagination,
},
columns,
data,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
pageCount: pagesCount,
// onPaginationChange: setPagination,
onPaginationChange,
});
return (
<div className="flex max-h-full w-full flex-col items-center justify-center bg-white p-6">
<div className="w-full overflow-auto">
<table className="w-full min-w-[1184px] table-auto overflow-auto text-sm">
<thead className="sticky top-0 bg-white-pearl">
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id} className="border-y ">
{headerGroup.headers.map(header => (
<th
key={header.id}
className="whitespace-nowrap py-2.5"
style={{ width: header.getSize() }}
>
{flexRender(header.column.columnDef.header, header.getContext())}
</th>
))}
</tr>
))}
</thead>
<tbody>
{data &&
table.getRowModel().rows.map(row => (
<tr key={row.id} className="even:bg-lotion">
{row.getVisibleCells().map(cell => (
<td
key={cell.id}
className="p-3"
style={{
width: cell.column.getSize(),
}}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
<div className="flex w-full flex-row justify-end border-t">
<div className="mt-6 flex flex-row items-center">
<Button
variantStyles="quiet"
className="text-primary-500"
onClick={() => table.setPageIndex(ZERO)}
disabled={isPublicationsLoading}
>
First page
</Button>
<Button
variantStyles="secondary"
onClick={() => table.previousPage()}
disabled={isPublicationsLoading}
>
Previous page
</Button>
<div className="mx-4 text-sm font-semibold">
Page {table.getState().pagination.pageIndex + ONE} out of {table.getPageCount()}
</div>
<Button
variantStyles="secondary"
onClick={() => table.nextPage()}
disabled={isPublicationsLoading}
>
Next page
</Button>
<Button
variantStyles="quiet"
className="text-primary-500"
onClick={() => table.setPageIndex(table.getPageCount() - ONE)}
disabled={isPublicationsLoading}
>
Last page
</Button>
</div>
</div>
</div>
);
};
Loading