table refactor

This commit is contained in:
hamid zarghami
2025-04-28 16:55:43 +03:30
parent d11837fd3f
commit da0e5e7b8c
3 changed files with 63 additions and 30 deletions
+30 -29
View File
@@ -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}
+30
View File
@@ -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;
}