68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
import React from 'react';
|
|
|
|
export interface Column<T> {
|
|
key: string;
|
|
label: string;
|
|
render?: (item: T) => React.ReactNode;
|
|
width?: string;
|
|
}
|
|
|
|
export interface DataTableProps<T> {
|
|
columns: Column<T>[];
|
|
data: T[];
|
|
keyExtractor: (item: T) => string;
|
|
onRowClick?: (item: T) => void;
|
|
emptyMessage?: string;
|
|
}
|
|
|
|
export function DataTable<T>({
|
|
columns,
|
|
data,
|
|
keyExtractor,
|
|
onRowClick,
|
|
emptyMessage = 'No data available'
|
|
}: DataTableProps<T>) {
|
|
if (data.length === 0) {
|
|
return (
|
|
<div className="text-center py-12 text-gray-500">
|
|
<p>{emptyMessage}</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full">
|
|
<thead>
|
|
<tr className="border-b border-gray-200 bg-gray-50">
|
|
{columns.map((column) => (
|
|
<th
|
|
key={column.key}
|
|
className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
style={column.width ? { width: column.width } : undefined}
|
|
>
|
|
{column.label}
|
|
</th>
|
|
))}
|
|
</tr>
|
|
</thead>
|
|
<tbody className="bg-white divide-y divide-gray-200">
|
|
{data.map((item) => (
|
|
<tr
|
|
key={keyExtractor(item)}
|
|
onClick={() => onRowClick?.(item)}
|
|
className={onRowClick ? 'cursor-pointer hover:bg-gray-50 transition-colors' : ''}
|
|
>
|
|
{columns.map((column) => (
|
|
<td key={column.key} className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
|
|
{column.render ? column.render(item) : (item as any)[column.key]}
|
|
</td>
|
|
))}
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|