import React from 'react';
interface Column<T> {
key: string;
header: string;
render?: (item: T) => React.ReactNode;
width?: string;
}
interface TableProps<T> {
data: T[];
columns: Column<T>[];
onRowClick?: (item: T) => void;
emptyMessage?: string;
loading?: boolean;
}
export function Table<T extends Record<string, any>>({
data,
columns,
onRowClick,
emptyMessage = 'No data available',
loading = false,
}: TableProps<T>) {
if (loading) {
return (
<div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 dark:border-blue-400" />
</div>
);
}
if (data.length === 0) {
return (
<div className="text-center py-12 text-gray-500 dark:text-gray-400">
{emptyMessage}
</div>
);
}
return (
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead className="bg-gray-50 dark:bg-gray-900">
<tr>
{columns.map((column) => (
<th
key={column.key}
className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
style={{ width: column.width }}
>
{column.header}
</th>
))}
</tr>
</thead>
<tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
{data.map((item, index) => (
<tr
key={index}
onClick={() => onRowClick?.(item)}
className={onRowClick ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors' : ''}
>
{columns.map((column) => (
<td key={column.key} className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100">
{column.render ? column.render(item) : item[column.key]}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
}