select all + mobile table in all pages

This commit is contained in:
hamid zarghami
2025-07-29 09:37:22 +03:30
parent 8b28a2dee0
commit ab1b509c42
9 changed files with 642 additions and 27 deletions
+3 -1
View File
@@ -58,10 +58,12 @@ const Table = <T extends RowDataType>({
};
}, []);
// خروج از حالت انتخاب اگر هیچ آیتمی انتخاب نشده
// خروج از حالت انتخاب اگر هیچ آیتمی انتخاب نشده، ورود اگر آیتمی انتخاب شده
React.useEffect(() => {
if (selectedRows.length === 0 && mobileSelectionMode) {
setMobileSelectionMode(false);
} else if (selectedRows.length > 0 && !mobileSelectionMode) {
setMobileSelectionMode(true);
}
}, [selectedRows.length, mobileSelectionMode]);
+87 -3
View File
@@ -7,12 +7,13 @@ import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useEmptyTrash, useGetTrashMessages } from './hooks/useTrashData';
import { TrashMessage } from './types/TrashTypes';
import { formatDate } from '@/config/func';
import { useEmailActions } from '@/hooks/useEmailActions';
import Button from '@/components/Button';
import ModalConfrim from '@/components/ModalConfrim';
import { ErrorType } from '@/helpers/types';
import { toast } from '@/components/Toast';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -30,8 +31,27 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<TrashMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<TrashMessage>[] = [
// تابع برای گرفتن فقط ساعت
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
// ستون‌های دسکتاپ
const desktopColumns: ColumnType<TrashMessage>[] = [
{
key: 'subject',
title: 'عنوان پیام',
@@ -54,13 +74,72 @@ const List: FC = () => {
title: 'تاریخ',
align: 'center',
render: (item) => (
<span>{formatDate(item.date)}</span>
<span>{formatTime(item.date)}</span>
)
},
];
// ستون‌های موبایل (سه خطی)
const mobileColumns: ColumnType<TrashMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.from.name || item.from.address}
</span>
<span className="text-xs text-gray-500 whitespace-nowrap">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
</div>
)
}
];
// انتخاب ستون‌ها بر اساس سایز صفحه
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = trashData?.data?.trashMails || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -91,18 +170,23 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: TrashMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = trashData?.data?.trashMails || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkDelete(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleRestoreSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkRestore(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleTrash = () => {
+87 -3
View File
@@ -7,8 +7,9 @@ import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useGetArchiveMessages } from './hooks/useArchiveData';
import { ArchiveMessage } from './types/ArchiveTypes';
import { formatDate } from '@/config/func';
import { useEmailActions } from '@/hooks/useEmailActions';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -25,8 +26,27 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<ArchiveMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<ArchiveMessage>[] = [
// تابع برای گرفتن فقط ساعت
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
// ستون‌های دسکتاپ
const desktopColumns: ColumnType<ArchiveMessage>[] = [
{
key: 'subject',
title: 'عنوان پیام',
@@ -49,13 +69,72 @@ const List: FC = () => {
title: 'تاریخ',
align: 'center',
render: (item) => (
<span>{formatDate(item.date)}</span>
<span>{formatTime(item.date)}</span>
)
},
];
// ستون‌های موبایل (سه خطی)
const mobileColumns: ColumnType<ArchiveMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.from.name || item.from.address}
</span>
<span className="text-xs text-gray-500 whitespace-nowrap">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
</div>
)
}
];
// انتخاب ستون‌ها بر اساس سایز صفحه
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = archiveData?.data?.archiveMails || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -81,18 +160,23 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: ArchiveMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = archiveData?.data?.archiveMails || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleUnarchiveSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkUnarchive(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const getRowActions = (message: ArchiveMessage): RowActionItem[] => [
+90 -3
View File
@@ -8,9 +8,10 @@ import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useGetDrafts } from './hooks/useDraftData';
import { DraftMessage } from './types/DraftTypes';
import { formatDate } from '@/config/func';
import { useEmailActions } from '@/hooks/useEmailActions';
import { useSharedStore } from '@/shared/store/sharedStore';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -29,8 +30,27 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<DraftMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<DraftMessage>[] = [
// تابع برای گرفتن فقط ساعت
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
// ستون‌های دسکتاپ
const desktopColumns: ColumnType<DraftMessage>[] = [
{
key: 'title',
title: 'title',
@@ -66,13 +86,73 @@ const List: FC = () => {
title: 'تاریخ',
align: 'center',
render: (item) => (
<span>{formatDate(item.date)}</span>
<span>{formatTime(item.date)}</span>
)
},
];
// ستون‌های موبایل (سه خطی)
const mobileColumns: ColumnType<DraftMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="text-[#0038FF] text-sm font-medium">پیش نویس</span>
<span className="text-xs text-gray-500 whitespace-nowrap ml-auto">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
گیرنده: {item.to && item.to.length > 0
? (item.to[0].name || item.to[0].address)
: 'بدون گیرنده'
}
</div>
</div>
)
}
];
// انتخاب ستون‌ها بر اساس سایز صفحه
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = draftData?.data?.draftsMail || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -114,6 +194,9 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: DraftMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = draftData?.data?.draftsMail || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
@@ -121,6 +204,7 @@ const List: FC = () => {
emailActions.deleteDraft({ messageId: message.id, mailbox: message.mailbox });
});
setSelectedMessages([]);
setSelectAll(false);
};
const handleSendSelected = () => {
@@ -128,6 +212,7 @@ const List: FC = () => {
emailActions.sendDraft({ messageId: message.id });
});
setSelectedMessages([]);
setSelectAll(false);
};
const handleEditSelected = () => {
@@ -136,6 +221,8 @@ const List: FC = () => {
} else {
console.log('ویرایش چندین پیش‌نویس انتخاب شده:', selectedMessages.map(m => m.id));
}
setSelectedMessages([]);
setSelectAll(false);
};
const handleDeleteDraft = (messageId: number) => {
+88 -3
View File
@@ -7,9 +7,10 @@ import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useGetFavoriteMessages } from './hooks/useFavoriteData';
import { FavoriteMessage } from './types/FavoriteTypes';
import { formatDate } from '@/config/func';
import { useEmailActions } from '@/hooks/useEmailActions';
import Favorite from '../received/Components/Favorite';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -26,8 +27,27 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<FavoriteMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<FavoriteMessage>[] = [
// تابع برای گرفتن فقط ساعت
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
// ستون‌های دسکتاپ
const desktopColumns: ColumnType<FavoriteMessage>[] = [
{
key: 'subject',
title: 'عنوان پیام',
@@ -50,13 +70,72 @@ const List: FC = () => {
title: 'تاریخ',
align: 'center',
render: (item) => (
<span>{formatDate(item.date)}</span>
<span>{formatTime(item.date)}</span>
)
},
];
// ستون‌های موبایل (سه خطی)
const mobileColumns: ColumnType<FavoriteMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.from.name || item.from.address}
</span>
<span className="text-xs text-gray-500 whitespace-nowrap">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
</div>
)
}
];
// انتخاب ستون‌ها بر اساس سایز صفحه
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = favoriteData?.data?.favoriteMails || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -83,24 +162,30 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: FavoriteMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = favoriteData?.data?.favoriteMails || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleArchiveSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkArchive(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleUnfavoriteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkUnfavorite(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const getInlineActions = (message: FavoriteMessage) => [
+26 -3
View File
@@ -19,6 +19,7 @@ import Button from '@/components/Button';
import ModalConfrim from '@/components/ModalConfrim';
import { ErrorType } from '@/helpers/types';
import { toast } from '@/components/Toast';
import { Checkbox } from '@/components/ui/checkbox';
const List: FC = () => {
@@ -59,6 +60,7 @@ const List: FC = () => {
const [selectedMessages, setSelectedMessages] = useState<InboxMessage[]>([]);
const [selectedMessage, setSelectedMessage] = useState<InboxMessage | null>(null);
const [selectAll, setSelectAll] = useState(false);
// ستون‌های دسکتاپ (مثل اولیه)
const desktopColumns: ColumnType<InboxMessage>[] = [
@@ -102,7 +104,6 @@ const List: FC = () => {
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
{/* سطر اول: فرستنده + ساعت */}
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.from.name || item.from.address}
@@ -112,12 +113,10 @@ const List: FC = () => {
</span>
</div>
{/* سطر دوم: موضوع */}
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
{/* سطر سوم: خلاصه */}
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
@@ -140,8 +139,25 @@ const List: FC = () => {
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = inboxData?.data?.results || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -186,30 +202,37 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: InboxMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = inboxData?.data?.results || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleArchiveSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkArchive(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleMarkAsReadSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMarkAsSeen(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleFavoriteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkFavorite(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleMarkAll = () => {
+91 -3
View File
@@ -7,8 +7,9 @@ import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useSearchMessages } from './hooks/useSearchData';
import { SearchMessage } from './types/SearchTypes';
import { formatDate } from '@/config/func';
import { useEmailActions } from '@/hooks/useEmailActions';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -25,8 +26,27 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<SearchMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<SearchMessage>[] = [
// تابع برای گرفتن فقط ساعت
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
// ستون‌های دسکتاپ
const desktopColumns: ColumnType<SearchMessage>[] = [
{
key: 'subject',
title: 'عنوان پیام',
@@ -56,13 +76,75 @@ const List: FC = () => {
title: 'تاریخ',
align: 'center',
render: (item) => (
<span>{formatDate(item.date)}</span>
<span>{formatTime(item.date)}</span>
)
},
];
// ستون‌های موبایل (سه خطی)
const mobileColumns: ColumnType<SearchMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.from.name || item.from.address}
</span>
<span className="text-xs bg-gray-100 px-1 py-0.5 rounded">
{item.mailbox}
</span>
<span className="text-xs text-gray-500 whitespace-nowrap">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
</div>
)
}
];
// انتخاب ستون‌ها بر اساس سایز صفحه
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = searchData?.data?.results || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -89,24 +171,30 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: SearchMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = searchData?.data?.results || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleArchiveSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkArchive(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleFavoriteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkFavorite(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const getRowActions = (message: SearchMessage): RowActionItem[] => [
+88 -5
View File
@@ -9,7 +9,8 @@ import { useNavigate } from 'react-router-dom';
import { Paths } from '../../utils/Paths';
import { useEmailActions } from '@/hooks/useEmailActions';
import { RowActionItem } from '../../components/RowActionsDropdown';
import { formatDate } from '@/config/func';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -26,8 +27,27 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<InboxMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<InboxMessage>[] = [
// تابع برای گرفتن فقط ساعت
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
// ستون‌های دسکتاپ
const desktopColumns: ColumnType<InboxMessage>[] = [
{
key: 'subject',
title: 'موضوع پیام',
@@ -64,15 +84,72 @@ const List: FC = () => {
title: 'تاریخ ارسال',
align: 'center',
render: (item) => (
<span className="">
{formatDate(item.date)}
</span>
<span>{formatTime(item.date)}</span>
)
},
];
// ستون‌های موبایل (سه خطی)
const mobileColumns: ColumnType<InboxMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.to.map(recipient => recipient.address).join(', ')}
</span>
<span className="text-xs text-gray-500 whitespace-nowrap">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
</div>
)
}
];
// انتخاب ستون‌ها بر اساس سایز صفحه
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = sentData?.data?.sentMails || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -103,24 +180,30 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: InboxMessage[]) => {
setSelectedMessages(selectedRows);
// تنظیم وضعیت select all بر اساس انتخاب شده‌ها
const messages = sentData?.data?.sentMails || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleArchiveSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkArchive(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleFavoriteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkFavorite(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const getRowActions = (message: InboxMessage): RowActionItem[] => [
+82 -3
View File
@@ -7,12 +7,13 @@ import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useEmptySpam, useGetSpamMessages } from './hooks/useSpamData';
import { SpamMessage } from './types/SpamTypes';
import { formatDate } from '@/config/func';
import { useEmailActions } from '@/hooks/useEmailActions';
import Button from '@/components/Button';
import ModalConfrim from '@/components/ModalConfrim';
import { ErrorType } from '@/helpers/types';
import { toast } from '@/components/Toast';
import { Checkbox } from '@/components/ui/checkbox';
import React from 'react';
const List: FC = () => {
const navigate = useNavigate();
@@ -31,8 +32,25 @@ const List: FC = () => {
});
const [selectedMessages, setSelectedMessages] = useState<SpamMessage[]>([]);
const [selectAll, setSelectAll] = useState(false);
const columns: ColumnType<SpamMessage>[] = [
const formatTime = (dateString: string) => {
try {
if (!dateString) return '--:--';
const date = new Date(dateString);
if (isNaN(date.getTime())) return '--:--';
return new Intl.DateTimeFormat("fa-IR", {
hour: "2-digit",
minute: "2-digit",
}).format(date);
} catch (error) {
console.error('خطا در فرمت زمان:', error);
return '--:--';
}
};
const desktopColumns: ColumnType<SpamMessage>[] = [
{
key: 'subject',
title: 'عنوان پیام',
@@ -54,13 +72,70 @@ const List: FC = () => {
title: 'تاریخ',
align: 'center',
render: (item) => (
<span>{formatDate(item.date)}</span>
<span>{formatTime(item.date)}</span>
)
},
];
const mobileColumns: ColumnType<SpamMessage>[] = [
{
key: 'content',
title: 'محتوا',
render: (item) => (
<div className="flex flex-col gap-1 w-full">
<div className="flex items-center gap-2 w-full">
<span className="truncate font-medium text-sm flex-1 min-w-0">
{item.from.name || item.from.address}
</span>
<span className="text-xs text-gray-500 whitespace-nowrap">
{formatTime(item.date)}
</span>
</div>
<div className="truncate w-full text-sm font-medium">
{item.subject || 'بدون موضوع'}
</div>
<div className="truncate w-full text-xs text-gray-600">
{item.intro || 'بدون متن پیش‌نمایش'}
</div>
</div>
)
}
];
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
React.useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const columns = isMobile ? mobileColumns : desktopColumns;
const handleSelectAll = (checked: boolean) => {
setSelectAll(checked);
if (checked) {
const messages = spamData?.data?.junkMails || [];
setSelectedMessages(messages);
} else {
setSelectedMessages([]);
}
};
const tableActions = (
<div className='flex items-center gap-2 md:gap-4'>
<div className="flex items-center gap-2">
<Checkbox
checked={selectAll}
onCheckedChange={handleSelectAll}
className="w-4 h-4"
/>
</div>
<Refresh2
size={18}
color='black'
@@ -91,18 +166,22 @@ const List: FC = () => {
const handleSelectionChange = (selectedRows: SpamMessage[]) => {
setSelectedMessages(selectedRows);
const messages = spamData?.data?.junkMails || [];
setSelectAll(selectedRows.length === messages.length && messages.length > 0);
};
const handleDeleteSelected = () => {
const messageIds = selectedMessages.map(message => message.id);
emailActions.bulkMoveToTrash(messageIds, selectedMessages[0].mailbox);
setSelectedMessages([]);
setSelectAll(false);
};
const handleNotSpamSelected = () => {
// TODO: پیاده‌سازی علامت‌گذاری به عنوان غیر اسپم - نیاز به API endpoint جداگانه
console.log('علامت‌گذاری به عنوان غیر اسپم:', selectedMessages.map(m => m.id));
setSelectedMessages([]);
setSelectAll(false);
};
const handleSpam = () => {