table like gmail and openn and close new messsage with animation +...
This commit is contained in:
@@ -68,6 +68,81 @@ const Table = <T extends RowDataType>({
|
||||
return selectedRows.some((row) => row.id === item.id);
|
||||
};
|
||||
|
||||
// Gmail-style layout برای وقتی header نمایش داده نمیشود
|
||||
const renderGmailStyleRows = () => {
|
||||
const hasActions = (actionsPosition === 'top' || actionsPosition === 'above-header') && (actions || (selectable && selectedRows.length > 0 && selectedActions));
|
||||
const roundedClass = hasActions ? 'rounded-b-2xl' : 'rounded-2xl';
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className={`bg-white ${roundedClass} overflow-hidden`}>
|
||||
{Array.from({ length: emptyRowsCount }).map((_, index) => (
|
||||
<div key={index} className={`h-[48px] bg-gray-100 animate-pulse ${index !== 0 ? 'border-t border-[#EAEDF5]' : ''}`}></div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (data.length === 0) {
|
||||
return (
|
||||
<div className={`bg-white ${roundedClass} py-6 md:py-8 text-center text-gray-500`}>
|
||||
{noDataMessage}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`bg-white ${roundedClass} overflow-hidden`}>
|
||||
{data.map((item, rowIndex) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className={`w-full min-h-[48px] hover:bg-[#F4F5F9] ${onRowClick ? 'cursor-pointer' : ''} ${getRowClassName(item, rowIndex)} px-4 py-3 flex items-center gap-3 ${rowIndex !== 0 ? 'border-t border-[#EAEDF5]' : ''}`}
|
||||
onClick={() => handleRowClick(item)}
|
||||
>
|
||||
{selectable && (
|
||||
<div
|
||||
className="flex-shrink-0 relative z-[5]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Checkbox
|
||||
checked={isRowSelected(item)}
|
||||
onCheckedChange={(checked) => handleSingleRowSelect(item, !!checked)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
{/* محتوای اصلی - ستون اول */}
|
||||
<div className="flex items-center mb-0.5 text-sm font-medium">
|
||||
{columns[0]?.render ? columns[0].render(item) : (item[columns[0]?.key] as React.ReactNode)}
|
||||
</div>
|
||||
|
||||
{/* اطلاعات اضافی - سه ستون آخر در یک خط */}
|
||||
{columns.length > 1 && (
|
||||
<div className="flex items-center gap-3 text-xs text-gray-500">
|
||||
{columns.slice(1).map((col) => (
|
||||
<div key={col.key} className="truncate">
|
||||
{col.render ? col.render(item) : (item[col.key] as React.ReactNode)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{rowActions && (
|
||||
<div
|
||||
className="flex-shrink-0 relative z-[5]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<RowActionsDropdown actions={rowActions(item)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderTableBody = () => {
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -165,6 +240,53 @@ const Table = <T extends RowDataType>({
|
||||
);
|
||||
};
|
||||
|
||||
// اگر header نشان داده نمیشود، از Gmail-style layout فقط در موبایل استفاده کن
|
||||
if (!showHeader) {
|
||||
return (
|
||||
<div className={`relative mt-6 md:mt-9 w-full ${className}`}>
|
||||
{/* نسخه موبایل - Gmail style */}
|
||||
<div className={`md:hidden`}>
|
||||
{(actionsPosition === 'top' || actionsPosition === 'above-header') && (
|
||||
<div className="h-[64px] bg-white flex items-center px-4 rounded-t-2xl border-b border-[#EAEDF5]">
|
||||
<div className='flex items-center gap-2'>
|
||||
{actions}
|
||||
{selectable && selectedRows.length > 0 && selectedActions && selectedActions}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{renderGmailStyleRows()}
|
||||
</div>
|
||||
|
||||
{/* نسخه دسکتاپ - Table معمولی */}
|
||||
<div className={`hidden md:block`}>
|
||||
{(actionsPosition === 'top' || actionsPosition === 'above-header') && (
|
||||
<div className="h-[74px] bg-white flex items-center px-6 rounded-t-3xl">
|
||||
<div className='flex items-center gap-4'>
|
||||
{actions}
|
||||
{selectable && selectedRows.length > 0 && selectedActions && selectedActions}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={`overflow-x-auto overflow-hidden ${(actionsPosition === 'top' || actionsPosition === 'above-header') && (actions || (selectable && selectedRows.length > 0 && selectedActions)) ? 'rounded-b-3xl' : 'rounded-3xl'} bg-white`}>
|
||||
<table className="w-full text-sm border-collapse min-w-[600px]">
|
||||
<tbody>
|
||||
{renderTableBody()}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{pagination && (
|
||||
<Pagination
|
||||
currentPage={pagination.currentPage}
|
||||
totalPages={pagination.totalPages}
|
||||
onPageChange={pagination.onPageChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`relative mt-6 md:mt-9 w-full ${className}`}>
|
||||
{(actionsPosition === 'top' || actionsPosition === 'above-header') && renderActions()}
|
||||
|
||||
Reference in New Issue
Block a user