table refactor
This commit is contained in:
+30
-29
@@ -1,34 +1,7 @@
|
||||
import React, { Fragment, ReactNode } from 'react';
|
||||
import React, { Fragment, useState } from 'react';
|
||||
import DefaultTableSkeleton from './DefaultTableSkeleton';
|
||||
import Td from './Td';
|
||||
|
||||
export type RowDataType = Record<string, unknown> & { id: string | number };
|
||||
|
||||
export interface ColumnType<T extends RowDataType = RowDataType> {
|
||||
title: string;
|
||||
key: string;
|
||||
render?: (item: T) => React.ReactNode;
|
||||
width?: string | number;
|
||||
align?: 'left' | 'center' | 'right';
|
||||
sortable?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface TableProps<T extends RowDataType = RowDataType> {
|
||||
columns: ColumnType<T>[];
|
||||
data: T[];
|
||||
isLoading?: boolean;
|
||||
onRowClick?: (id: T['id'], item: T) => void;
|
||||
className?: string;
|
||||
rowClassName?: string | ((item: T, index: number) => string);
|
||||
noDataMessage?: React.ReactNode;
|
||||
headerClassName?: string;
|
||||
emptyRowsCount?: number;
|
||||
showHeader?: boolean;
|
||||
actions?: ReactNode;
|
||||
actionsClassName?: string;
|
||||
actionsPosition?: 'top' | 'header-replace' | 'above-header';
|
||||
}
|
||||
import { TableProps, RowDataType, ColumnType } from './types/TableTypes';
|
||||
|
||||
const Table = <T extends RowDataType>({
|
||||
columns,
|
||||
@@ -43,8 +16,11 @@ const Table = <T extends RowDataType>({
|
||||
showHeader = true,
|
||||
actions = null,
|
||||
actionsPosition = 'top',
|
||||
selectable = false,
|
||||
}: TableProps<T>): React.ReactElement => {
|
||||
|
||||
const [selectedRows, setSelectedRows] = useState<T[]>([]);
|
||||
|
||||
const getRowClassName = (item: T, index: number): string => {
|
||||
if (typeof rowClassName === 'function') {
|
||||
return rowClassName(item, index);
|
||||
@@ -57,6 +33,16 @@ const Table = <T extends RowDataType>({
|
||||
return `p-3 ${alignClass} ${column.className || ''}`.trim();
|
||||
};
|
||||
|
||||
const handleRowClick = (item: T) => {
|
||||
if (selectable) {
|
||||
if (selectedRows.includes(item)) {
|
||||
setSelectedRows(selectedRows.filter((row) => row !== item));
|
||||
} else {
|
||||
setSelectedRows([...selectedRows, item]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderTableBody = () => {
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -82,6 +68,11 @@ const Table = <T extends RowDataType>({
|
||||
className={`tr border-b hover:bg-gray-50 ${onRowClick ? 'cursor-pointer' : ''} ${getRowClassName(item, rowIndex)}`}
|
||||
onClick={() => onRowClick && onRowClick(item.id, item)}
|
||||
>
|
||||
{selectable && (
|
||||
<td className="p-3 w-10 relative z-[5]">
|
||||
<input type="checkbox" checked={selectedRows.includes(item)} onChange={() => handleRowClick(item)} />
|
||||
</td>
|
||||
)}
|
||||
{columns.map((col) => (
|
||||
<td key={`${item.id}-${col.key}`} className={getCellClassName(col)} style={{ width: col.width }}>
|
||||
{col.render ? col.render(item) : item[col.key] as React.ReactNode}
|
||||
@@ -97,6 +88,16 @@ const Table = <T extends RowDataType>({
|
||||
return (
|
||||
<thead className={`thead ${headerClassName}`}>
|
||||
<tr>
|
||||
{selectable && (
|
||||
<th
|
||||
className="p-3 w-10 relative z-[5]"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<input type="checkbox" checked={false} onChange={() => { }} />
|
||||
</th>
|
||||
)}
|
||||
{columns.map((col) => (
|
||||
<th
|
||||
key={col.key}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { ReactNode } from "react";
|
||||
|
||||
export type RowDataType = Record<string, unknown> & { id: string | number };
|
||||
|
||||
export interface ColumnType<T extends RowDataType = RowDataType> {
|
||||
title: string;
|
||||
key: string;
|
||||
render?: (item: T) => React.ReactNode;
|
||||
width?: string | number;
|
||||
align?: "left" | "center" | "right";
|
||||
sortable?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface TableProps<T extends RowDataType = RowDataType> {
|
||||
columns: ColumnType<T>[];
|
||||
data: T[];
|
||||
isLoading?: boolean;
|
||||
onRowClick?: (id: T["id"], item: T) => void;
|
||||
className?: string;
|
||||
rowClassName?: string | ((item: T, index: number) => string);
|
||||
noDataMessage?: React.ReactNode;
|
||||
headerClassName?: string;
|
||||
emptyRowsCount?: number;
|
||||
showHeader?: boolean;
|
||||
actions?: ReactNode;
|
||||
actionsClassName?: string;
|
||||
actionsPosition?: "top" | "header-replace" | "above-header";
|
||||
selectable?: boolean;
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import Filters, { FilterValues } from '../../components/Filters';
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Table, { ColumnType } from '../../components/Table';
|
||||
import Table from '../../components/Table';
|
||||
import { ColumnType } from '../../components/types/TableTypes';
|
||||
import { InfoCircle, More, Refresh2 } from 'iconsax-react';
|
||||
|
||||
interface Message extends Record<string, unknown> {
|
||||
@@ -86,6 +87,7 @@ const List: FC = () => {
|
||||
<div>هیچ پیامی یافت نشد</div>
|
||||
</div>
|
||||
}
|
||||
selectable={true}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user