email actions + sent list + action list + archive list + trash list

This commit is contained in:
hamid zarghami
2025-07-12 16:01:17 +03:30
parent fac9159ec0
commit 663dd1a9db
45 changed files with 1947 additions and 326 deletions
+60 -22
View File
@@ -3,18 +3,21 @@ import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Table from '../../components/Table';
import { ColumnType } from '../../components/types/TableTypes';
import { InfoCircle, More, Refresh2, Trash, Edit, Archive } from 'iconsax-react';
import { InfoCircle, More, Refresh2, Trash, Edit, Archive, ArchiveTick, Star1 } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useGetInbox } from './hooks/useEmailData';
import { InboxMessage } from './types/Types';
import { formatDate } from '@/config/func';
import MarkAsRead from '@/assets/images/mark_as_read.svg'
import { useEmailActions } from '@/hooks/useEmailActions';
const List: FC = () => {
const navigate = useNavigate();
const { t } = useTranslation();
const [currentPage, setCurrentPage] = useState(1);
const [filters, setFilters] = useState<FilterValues>({});
const emailActions = useEmailActions();
const { data: inboxData, isLoading, refetch, isFetching } = useGetInbox({
page: currentPage,
@@ -29,17 +32,16 @@ const List: FC = () => {
key: 'subject',
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 mr-2" />} */}
<span className="truncate">{item.subject || 'بدون موضوع'}</span>
</div>
<span className="truncate">{item.subject || 'بدون موضوع'}</span>
)
},
{
key: 'from',
title: 'فرستنده',
render: (item) => (
<span className="truncate">{item.from.name || item.from.address}</span>
<div className="flex items-center">
<span className="truncate">{item.from.name || item.from.address}</span>
</div>
)
},
{
@@ -60,21 +62,42 @@ const List: FC = () => {
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
onClick={() => refetch()}
/>
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div>
);
const selectedActions = (
<>
<Trash size={18} color='black' onClick={() => handleDeleteSelected()} className="cursor-pointer" />
<Archive size={18} color='black' onClick={() => handleArchiveSelected()} className="cursor-pointer" />
<Edit size={18} color='black' onClick={() => handleMarkAsReadSelected()} className="cursor-pointer" />
<img
src={MarkAsRead}
className='w-[18px] cursor-pointer'
onClick={() => handleMarkAsReadSelected()}
/>
<ArchiveTick
size={18}
color='black'
onClick={() => handleArchiveSelected()}
className="cursor-pointer"
/>
<InfoCircle size={18} color='black' className="cursor-pointer" />
<Star1
size={18}
color='black'
className="cursor-pointer"
onClick={() => handleFavoriteSelected()}
/>
<Trash
size={18}
color='#CD0000'
onClick={() => handleDeleteSelected()}
className="cursor-pointer"
/>
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</>
);
const handleFilterChange = (newFilters: FilterValues) => {
setFilters(newFilters);
setCurrentPage(1); // Reset to first page when filters change
setCurrentPage(1);
};
const handleSelectionChange = (selectedRows: InboxMessage[]) => {
@@ -82,35 +105,49 @@ const List: FC = () => {
};
const handleDeleteSelected = () => {
console.log('حذف پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق حذف را پیاده‌سازی کنید
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds);
setSelectedMessages([]);
};
const handleArchiveSelected = () => {
console.log('بایگانی پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق بایگانی را پیاده‌سازی کنید
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkArchive(messageIds);
setSelectedMessages([]);
};
const handleMarkAsReadSelected = () => {
console.log('علامت‌گذاری به عنوان خوانده شده:', selectedMessages.map(m => m.id));
// اینجا منطق علامت‌گذاری را پیاده‌سازی کنید
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMarkAsSeen(messageIds);
setSelectedMessages([]);
};
const handleFavoriteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkFavorite(messageIds);
setSelectedMessages([]);
};
const getRowActions = (message: InboxMessage): RowActionItem[] => [
{
label: message.seen ? 'علامت‌گذاری به عنوان خوانده نشده' : 'علامت‌گذاری به عنوان خوانده شده',
icon: <Edit size={16} color="black" />,
onClick: () => console.log('تغییر وضعیت خوانده شده', message.id),
onClick: () => emailActions.markAsSeen(message.id),
},
{
label: 'اضافه به علاقه‌مندی‌ها',
icon: <Star1 size={16} color="black" />,
onClick: () => emailActions.favorite(message.id),
},
{
label: 'بایگانی',
icon: <Archive size={16} color="black" />,
onClick: () => console.log('بایگانی پیام', message.id),
onClick: () => emailActions.archive(message.id),
},
{
label: 'حذف',
icon: <Trash size={16} color="red" />,
onClick: () => console.log('حذف پیام', message.id),
onClick: () => emailActions.moveToTrash(message.id),
},
];
@@ -148,14 +185,15 @@ const List: FC = () => {
<Table<InboxMessage>
columns={columns}
data={messages}
isLoading={isLoading}
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 py-6">
<div className="flex flex-col items-center">
<InfoCircle size={32} className="text-gray-300 mb-2" />
<div className="text-sm">هیچ پیامی یافت نشد</div>
</div>
+2 -2
View File
@@ -35,12 +35,12 @@ export const getMessageDetail = async (
messageId: string
): Promise<MessageDetail> => {
const { data }: { data: MessageDetailResponse } = await axios.get(
`/email/messages/inbox/${messageId}`
`/email/messages/${messageId}`
);
return data.data.message;
};
export const deleteMessage = async (messageId: string): Promise<void> => {
const { data } = await axios.delete(`/email/messages/inbox/${messageId}`);
const { data } = await axios.delete(`/email/messages/${messageId}`);
return data;
};
+18
View File
@@ -286,3 +286,21 @@ export interface MessageDetail {
};
};
}
export enum BulkActionType {
SEEN = "seen",
DELETE = "delete",
ARCHIVE = "archive",
FAVORITE = "favorite",
UNFAVORITE = "unfavorite",
UNARCHIVE = "unarchive",
RESTORE = "restore",
JUNK = "junk",
TRASH = "trash",
}
// Interface for bulk action request
export interface BulkActionRequest {
messageIds: number[];
action: BulkActionType;
}