Skip to content

Commit

Permalink
Merge pull request #43 from bleu-fi/joao/click-684-novo-layout-para-m…
Browse files Browse the repository at this point in the history
…onitoramento-tributario

Refactor swrdatatable to be a composable table
  • Loading branch information
devjoaov authored Mar 26, 2024
2 parents de24762 + e461a2a commit 7f20b20
Show file tree
Hide file tree
Showing 11 changed files with 345 additions and 200 deletions.
143 changes: 143 additions & 0 deletions src/components/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import {
getCoreRowModel,
getFacetedRowModel,
getFacetedUniqueValues,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import React, { useEffect } from "react";

import { useNavigate } from "react-router";
import { TableContext } from "./TableContext";
import { serializeQuery } from "#/lib/serializeQuery";

export function formatRequestParams(originalObj) {
return {
...originalObj,
sorting: originalObj?.sorting?.length > 0 ? originalObj.sorting[0] : null,
columnFilters: originalObj.columnFilters.reduce((acc, filter) => {
acc[filter.id] = filter.value;
return acc;
}, {}),
};
}

const defaultFilterFn = (row, id, filterValue) =>
row.getValue(id).includes(filterValue);

const buildColumns = (columnsConfig) => {
if (!columnsConfig) return [];

return columnsConfig.map((columnConfig) => ({
...columnConfig,
filterFn: columnConfig.filterable ? defaultFilterFn : null,
}));
};

export function DataTable({
children,
data,
error,
tableState,
setTableState,
buildTableColumns = buildColumns,
setQueryToParams,
setSelectedData,
}) {
const { pagination, rowSelection, columnVisibility, columnFilters, sorting } =
tableState;

const {
setPagination,
setRowSelection,
setColumnVisibility,
setColumnFilters,
setSorting,
} = setTableState;

if (error) {
return <div>Error: {error.message}</div>;
}

// @ts-ignore
const columns = buildTableColumns(data?.columns, data?.filters);
const filters = data?.filters;
const searchKey = data?.search?.key;

const hiddenColumns = columns
.filter((c) => c.hide)
.map((c) => ({ [c.accessorKey]: false }))
.reduce((acc, obj) => Object.assign(acc, obj), {});

const table = useReactTable({
data: data?.data ?? [],
pageCount: Math.ceil((data?.total ?? 0) / pagination.pageSize),
columns,
state: {
sorting,
rowSelection,
columnFilters,
pagination,
columnVisibility: {
...columnVisibility,
...hiddenColumns,
},
},
onPaginationChange: setPagination,
manualPagination: true,
enableRowSelection: true,
onRowSelectionChange: setRowSelection,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
});

React.useEffect(() => {
if (setSelectedData)
setSelectedData(
table.getSelectedRowModel().flatRows.map((row) => row.original)
);
}, [rowSelection, table, setSelectedData]);

const navigate = useNavigate();
useEffect(() => {
if (!setQueryToParams) return;

const formattedParams = formatRequestParams({
columnFilters: tableState.columnFilters,
sorting: tableState.sorting,
pageIndex: tableState.pagination.pageIndex,
pageSize: tableState.pagination.pageSize,
});

const params = serializeQuery(formattedParams);
navigate(`?${params}`, { replace: true });
}, [
tableState.pagination.pageIndex,
tableState.pagination.pageSize,
tableState.sorting,
tableState.columnFilters,
navigate,
]);

// eslint-disable-next-line react/jsx-no-constructed-context-values
const contextValue = {
data,
filters,
error,
tableState,
setTableState,
table,
searchKey,
};

return (
<TableContext.Provider value={contextValue}>
{children}
</TableContext.Provider>
);
}
6 changes: 5 additions & 1 deletion src/components/DataTable/DataTablePagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import {
} from "@radix-ui/react-icons";
import { useTranslation, Trans } from "react-i18next";
import { Button, Select } from "#/components/ui";
import { useTableContext } from "./TableContext";

export function DataTablePagination() {
// @ts-expect-error TS(2339) FIXME: Property 'table' does not exist on type '{}'.
const { table } = useTableContext();

export function DataTablePagination({ table }) {
const { t } = useTranslation();
const currentPage = Number(table.getState().pagination.pageIndex) + 1;
const pageCount = table.getPageCount() || 1;
Expand Down
15 changes: 10 additions & 5 deletions src/components/DataTable/DataTableToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ import { Button, Input } from "#/components/ui";

import { DataTableFacetedFilter } from "./DataTableFacetedFilter";
import { DataTableViewOptions } from "./DataTableViewOptions";
import { useTableContext } from "./TableContext";

export function DataTableToolbar({
table,
filters,
action,
showViewOptions = true,
searchKey = "name",
}) {
// @ts-expect-error TS(2339) FIXME: Property 'table' does not exist on type '{}'.
const { table, filters, searchKey: TableSeachKey } = useTableContext();

const search = TableSeachKey || searchKey;

if (!table || !filters) {
return null;
}
Expand Down Expand Up @@ -47,9 +52,9 @@ export function DataTableToolbar({
<div className="flex flex-1 items-start space-x-2">
<Input
placeholder={t("Search")}
value={table.getColumn(searchKey)?.getFilterValue() ?? ""}
value={table.getColumn(search)?.getFilterValue() ?? ""}
onChange={(event) =>
table.getColumn(searchKey)?.setFilterValue(event.target.value)
table.getColumn(search)?.setFilterValue(event.target.value)
}
className="h-8 w-[150px] lg:w-[250px] dark:border-2"
/>
Expand Down Expand Up @@ -79,7 +84,7 @@ export function DataTableToolbar({
</div>
<div className="flex items-center space-x-2">
{action}
<DataTableViewOptions table={table} />
{showViewOptions && <DataTableViewOptions />}
</div>
</div>
);
Expand Down
6 changes: 5 additions & 1 deletion src/components/DataTable/DataTableViewOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ import {
DropdownMenuLabel,
DropdownMenuSeparator,
} from "#/components/ui";
import { useTableContext } from "./TableContext";

export function DataTableViewOptions() {
// @ts-expect-error TS(2339) FIXME: Property 'table' does not exist on type '{}'.
const { table } = useTableContext();

export function DataTableViewOptions({ table }) {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
Expand Down
45 changes: 45 additions & 0 deletions src/components/DataTable/SWRDataTable/SWRDataTableBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* eslint-disable no-restricted-syntax */
import React from "react";
import { flexRender } from "@tanstack/react-table";

import { Trans } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { TableBody, TableCell, TableRow } from "#/components/ui";

import { useTableContext } from "../TableContext";

export function SWRDataTableBody({ hasDetails }) {
// @ts-expect-error TS(2339) FIXME: Property 'table' does not exist on type '{}'.
const { table } = useTableContext();

const navigate = useNavigate();
return (
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
onClick={() => {
if (hasDetails) {
navigate(`${row.original.id}`);
}
}}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell className="h-24 text-center">
<Trans>No results found</Trans>.
</TableCell>
</TableRow>
)}
</TableBody>
);
}
31 changes: 31 additions & 0 deletions src/components/DataTable/SWRDataTable/SWRDataTableHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* eslint-disable no-restricted-syntax */
import React from "react";
import { flexRender } from "@tanstack/react-table";

import { TableHead, TableHeader, TableRow } from "#/components/ui";

import { useTableContext } from "../TableContext";

export function SWRDataTableHeader() {
// @ts-expect-error TS(2339) FIXME: Property 'table' does not exist on type '{}'.
const { table } = useTableContext();

return (
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
);
}
Loading

0 comments on commit 7f20b20

Please sign in to comment.