email actions + sent list + action list + archive list + trash list
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import Filters, { FilterValues } from '../../components/Filters';
|
||||
import { FC, useState } from 'react'
|
||||
import Table from '../../components/Table';
|
||||
import { ColumnType } from '../../components/types/TableTypes';
|
||||
import { InfoCircle, More, Refresh2, Trash, RecoveryConvert } from 'iconsax-react';
|
||||
import { RowActionItem } from '../../components/RowActionsDropdown';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useGetSpamMessages } from './hooks/useSpamData';
|
||||
import { SpamMessage } from './types/SpamTypes';
|
||||
import { formatDate } from '@/config/func';
|
||||
import { useEmailActions } from '@/hooks/useEmailActions';
|
||||
|
||||
const List: FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [filters, setFilters] = useState<FilterValues>({});
|
||||
const emailActions = useEmailActions();
|
||||
|
||||
const { data: spamData, isLoading, refetch, isFetching } = useGetSpamMessages({
|
||||
page: currentPage,
|
||||
limit: 10,
|
||||
...filters
|
||||
});
|
||||
|
||||
const [selectedMessages, setSelectedMessages] = useState<SpamMessage[]>([]);
|
||||
|
||||
const columns: ColumnType<SpamMessage>[] = [
|
||||
{
|
||||
key: 'subject',
|
||||
title: 'عنوان پیام',
|
||||
render: (item) => (
|
||||
<span className="truncate">{item.subject || 'بدون موضوع'}</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'from',
|
||||
title: 'فرستنده',
|
||||
render: (item) => (
|
||||
<div className="flex items-center">
|
||||
{!item.seen && <div className="w-1.5 h-1.5 md:w-2 md:h-2 rounded-full bg-blue-500 ml-2" />}
|
||||
<span className="truncate">{item.from.name || item.from.address}</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'date',
|
||||
title: 'تاریخ',
|
||||
align: 'center',
|
||||
render: (item) => (
|
||||
<span>{formatDate(item.date)}</span>
|
||||
)
|
||||
},
|
||||
];
|
||||
|
||||
const tableActions = (
|
||||
<div className='flex items-center gap-2 md:gap-4'>
|
||||
<Refresh2
|
||||
size={18}
|
||||
color='black'
|
||||
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
|
||||
onClick={() => refetch()}
|
||||
/>
|
||||
<More size={18} color='black' className='rotate-90 cursor-pointer' />
|
||||
</div>
|
||||
);
|
||||
|
||||
const selectedActions = (
|
||||
<>
|
||||
<RecoveryConvert size={18} color='black' onClick={() => handleNotSpamSelected()} className="cursor-pointer" />
|
||||
<Trash size={18} color='black' onClick={() => handleDeleteSelected()} className="cursor-pointer" />
|
||||
</>
|
||||
);
|
||||
|
||||
const handleFilterChange = (newFilters: FilterValues) => {
|
||||
setFilters(newFilters);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleSelectionChange = (selectedRows: SpamMessage[]) => {
|
||||
setSelectedMessages(selectedRows);
|
||||
};
|
||||
|
||||
const handleDeleteSelected = () => {
|
||||
const messageIds = selectedMessages.map(message => message.id);
|
||||
emailActions.bulkMoveToTrash(messageIds);
|
||||
setSelectedMessages([]);
|
||||
};
|
||||
|
||||
const handleNotSpamSelected = () => {
|
||||
// TODO: پیادهسازی علامتگذاری به عنوان غیر اسپم - نیاز به API endpoint جداگانه
|
||||
console.log('علامتگذاری به عنوان غیر اسپم:', selectedMessages.map(m => m.id));
|
||||
setSelectedMessages([]);
|
||||
};
|
||||
|
||||
const getRowActions = (message: SpamMessage): RowActionItem[] => [
|
||||
{
|
||||
label: 'غیر اسپم',
|
||||
icon: <RecoveryConvert size={16} color="black" />,
|
||||
onClick: () => console.log('علامتگذاری به عنوان غیر اسپم', message.id),
|
||||
},
|
||||
{
|
||||
label: 'حذف',
|
||||
icon: <Trash size={16} color="red" />,
|
||||
onClick: () => emailActions.moveToTrash(message.id),
|
||||
},
|
||||
];
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
const messages = spamData?.data?.results || [];
|
||||
const pager = spamData?.data?.pager;
|
||||
|
||||
return (
|
||||
<div className='mt-2 md:mt-4 px-2 md:px-0'>
|
||||
<h1 className="text-lg mb-4 md:mb-0">پیامهای اسپم</h1>
|
||||
|
||||
<Filters
|
||||
fields={[
|
||||
{ type: 'date', name: 'dateFrom', placeholder: 'از تاریخ' },
|
||||
{ type: 'date', name: 'dateTo', placeholder: 'تا تاریخ' },
|
||||
{
|
||||
type: 'select',
|
||||
name: 'isRead',
|
||||
placeholder: 'همه',
|
||||
options: [
|
||||
{ value: '', label: 'همه' },
|
||||
{ value: 'true', label: 'خوانده شده' },
|
||||
{ value: 'false', label: 'خوانده نشده' }
|
||||
]
|
||||
},
|
||||
{ type: 'input', name: 'search', placeholder: 'جستجو...' }
|
||||
]}
|
||||
onChange={handleFilterChange}
|
||||
searchField="search"
|
||||
/>
|
||||
|
||||
<Table<SpamMessage>
|
||||
columns={columns}
|
||||
data={messages}
|
||||
isLoading={isLoading || emailActions.isLoading}
|
||||
showHeader={false}
|
||||
actions={tableActions}
|
||||
selectedActions={selectedActions}
|
||||
onSelectionChange={handleSelectionChange}
|
||||
selectedRows={selectedMessages}
|
||||
onRowClick={(id) => navigate(`/mail/${id}`)}
|
||||
noDataMessage={
|
||||
<div className="flex flex-col items-center">
|
||||
<InfoCircle size={32} className="text-gray-300 mb-2" />
|
||||
<div className="text-sm">هیچ پیامی یافت نشد</div>
|
||||
</div>
|
||||
}
|
||||
selectable={true}
|
||||
rowActions={getRowActions}
|
||||
pagination={pager ? {
|
||||
totalPages: pager.totalPages,
|
||||
currentPage: pager.page,
|
||||
onPageChange: handlePageChange
|
||||
} : undefined}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default List
|
||||
Reference in New Issue
Block a user