reponsive and selective actions and row actioin + pagination

This commit is contained in:
hamid zarghami
2025-06-17 20:52:40 +03:30
parent 71fd53c810
commit 4c869c42c6
24 changed files with 869 additions and 287 deletions
+78 -29
View File
@@ -1,26 +1,28 @@
import Filters, { FilterValues } from '../../components/Filters';
import { FC, ReactNode, useState } from 'react'
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 } from 'iconsax-react';
import { InfoCircle, More, Refresh2, Trash, RecoveryConvert } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
interface Message extends Record<string, unknown> {
id: string;
title: string | ReactNode;
title: string;
sender: string;
date: string;
read: boolean;
}
const TrashList: FC = () => {
const List: FC = () => {
const { t } = useTranslation();
const [isLoading] = useState(false);
const [selectedMessages, setSelectedMessages] = useState<Message[]>([]);
const messageData: Message[] = [
{ id: '1', title: <div className='text-blue-500'>پیش نویس</div>, sender: 'علی محمدی', date: '1402/05/12', read: true },
{ id: '2', title: <div className='text-blue-500'>ارسالی</div>, sender: 'زهرا احمدی', date: '1402/05/13', read: true },
{ id: '3', title: <div className='text-blue-500'>دریافت شده</div>, sender: 'مدیریت', date: '1402/05/14', read: true },
{ id: '1', title: 'اولین پیام', sender: 'علی محمدی', date: '1402/05/12', read: true },
{ id: '2', title: 'دومین پیام', sender: 'زهرا احمدی', date: '1402/05/13', read: true },
{ id: '3', title: 'جلسه هفتگی', sender: 'مدیریت', date: '1402/05/14', read: true },
];
const columns: ColumnType<Message>[] = [
@@ -29,49 +31,94 @@ const TrashList: FC = () => {
title: 'عنوان پیام',
render: (item) => (
<div className="flex items-center">
{!item.read && <div className="w-2 h-2 rounded-full bg-blue-500 mr-2" />}
<span>{item.title}</span>
{!item.read && <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.title}</span>
</div>
)
},
{ key: 'status', title: 'وضعیت' },
{ key: 'sender', title: 'فرستنده' },
{ key: 'date', title: 'تاریخ', align: 'center' },
{
key: 'sender',
title: 'فرستنده',
render: (item) => (
<span className="truncate">{item.sender}</span>
)
},
{
key: 'date',
title: 'تاریخ',
align: 'center',
render: (item) => (
<span className="text-xs md:text-sm">{item.date}</span>
)
},
];
const tableActions = (
<div className='flex items-center gap-4'>
<Refresh2 size={20} color='black' />
<More size={20} color='black' className='rotate-90' />
<div className='flex items-center gap-2 md:gap-4'>
<Refresh2 size={18} color='black' className="cursor-pointer" />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div>
);
const selectedActions = (
<>
<RecoveryConvert size={18} color='black' onClick={() => handleRestoreSelected()} className="cursor-pointer" />
<Trash size={18} color='red' onClick={() => handleDeleteSelected()} className="cursor-pointer" />
</>
);
const handleFilterChange = (newFilters: FilterValues) => {
console.log('Applied filters:', newFilters);
};
const handleSelectionChange = (selectedRows: Message[]) => {
setSelectedMessages(selectedRows);
};
const handleDeleteSelected = () => {
console.log('حذف دائم پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق حذف دائم را پیاده‌سازی کنید
};
const handleRestoreSelected = () => {
console.log('بازگردانی پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق بازگردانی را پیاده‌سازی کنید
};
const getRowActions = (message: Message): RowActionItem[] => [
{
label: 'بازگردانی',
icon: <RecoveryConvert size={16} color="black" />,
onClick: () => console.log('بازگردانی پیام', message.id),
},
{
label: 'حذف دائم',
icon: <Trash size={16} color="red" />,
onClick: () => console.log('حذف دائم پیام', message.id),
},
];
return (
<div className='mt-4'>
<h1>{t('draft.title')}</h1>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg md:text-xl xl:text-2xl font-bold mb-4 md:mb-0">{t('trash.title')}</h1>
<Filters
fields={[
{ type: 'date', name: 'from_date', placeholder: t('received.from_date') },
{ type: 'date', name: 'to_date', placeholder: t('received.to_date') },
{ type: 'date', name: 'from_date', placeholder: t('trash.from_date') },
{ type: 'date', name: 'to_date', placeholder: t('trash.to_date') },
{
type: 'select',
name: 'status',
placeholder: t('received.all'),
placeholder: t('trash.all'),
options: [
{ value: 'all', label: t('received.all') },
{ value: 'read', label: t('received.read') },
{ value: 'unread', label: t('received.unread') }
{ value: 'all', label: t('trash.all') },
{ value: 'read', label: t('trash.read') },
{ value: 'unread', label: t('trash.unread') }
]
},
{ type: 'input', name: 'search', placeholder: t('received.search') }
{ type: 'input', name: 'search', placeholder: t('trash.search') }
]}
onChange={handleFilterChange}
className="mt-8 flex justify-between items-center"
searchField="search"
/>
@@ -81,18 +128,20 @@ const TrashList: FC = () => {
isLoading={isLoading}
showHeader={false}
actions={tableActions}
selectedActions={selectedActions}
onSelectionChange={handleSelectionChange}
onRowClick={(id) => console.log(`کلیک روی پیام با شناسه ${id}`)}
noDataMessage={
<div className="flex flex-col items-center py-6">
<InfoCircle size={40} className="text-gray-300 mb-2" />
<div>هیچ پیامی یافت نشد</div>
<InfoCircle size={32} className="text-gray-300 mb-2" />
<div className="text-sm">سطل آشغال خالی است</div>
</div>
}
selectable={true}
rowActions={getRowActions}
/>
</div>
)
}
export default TrashList
export default List
+78 -30
View File
@@ -1,27 +1,28 @@
import Filters, { FilterValues } from '../../components/Filters';
import { FC, ReactNode, useState } from 'react'
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 } from 'iconsax-react';
import { InfoCircle, More, Refresh2, Trash, ArchiveSlash } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
interface Message extends Record<string, unknown> {
id: string;
title: string | ReactNode;
status: ReactNode;
title: string;
sender: string;
date: string;
read: boolean;
}
const ArchiveList: FC = () => {
const List: FC = () => {
const { t } = useTranslation();
const [isLoading] = useState(false);
const [selectedMessages, setSelectedMessages] = useState<Message[]>([]);
const messageData: Message[] = [
{ id: '1', title: <div className='text-blue-500'>پیش نویس</div>, status: <div className='text-yellow-500'>آرشیو شده</div>, sender: 'علی محمدی', date: '1402/05/12', read: true },
{ id: '2', title: <div className='text-blue-500'>ارسالی</div>, status: <div className='text-yellow-500'>آرشیو شده</div>, sender: 'زهرا احمدی', date: '1402/05/13', read: true },
{ id: '3', title: <div className='text-blue-500'>دریافت شده</div>, status: <div className='text-yellow-500'>آرشیو شده</div>, sender: 'مدیریت', date: '1402/05/14', read: true },
{ id: '1', title: 'اولین پیام', sender: 'علی محمدی', date: '1402/05/12', read: true },
{ id: '2', title: 'دومین پیام', sender: 'زهرا احمدی', date: '1402/05/13', read: true },
{ id: '3', title: 'جلسه هفتگی', sender: 'مدیریت', date: '1402/05/14', read: true },
];
const columns: ColumnType<Message>[] = [
@@ -30,49 +31,94 @@ const ArchiveList: FC = () => {
title: 'عنوان پیام',
render: (item) => (
<div className="flex items-center">
{!item.read && <div className="w-2 h-2 rounded-full bg-blue-500 mr-2" />}
<span>{item.title}</span>
{!item.read && <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.title}</span>
</div>
)
},
{ key: 'status', title: 'وضعیت' },
{ key: 'sender', title: 'فرستنده' },
{ key: 'date', title: 'تاریخ', align: 'center' },
{
key: 'sender',
title: 'فرستنده',
render: (item) => (
<span className="truncate">{item.sender}</span>
)
},
{
key: 'date',
title: 'تاریخ',
align: 'center',
render: (item) => (
<span className="text-xs md:text-sm">{item.date}</span>
)
},
];
const tableActions = (
<div className='flex items-center gap-4'>
<Refresh2 size={20} color='black' />
<More size={20} color='black' className='rotate-90' />
<div className='flex items-center gap-2 md:gap-4'>
<Refresh2 size={18} color='black' className="cursor-pointer" />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div>
);
const selectedActions = (
<>
<ArchiveSlash size={18} color='black' onClick={() => handleUnarchiveSelected()} className="cursor-pointer" />
<Trash size={18} color='black' onClick={() => handleDeleteSelected()} className="cursor-pointer" />
</>
);
const handleFilterChange = (newFilters: FilterValues) => {
console.log('Applied filters:', newFilters);
};
const handleSelectionChange = (selectedRows: Message[]) => {
setSelectedMessages(selectedRows);
};
const handleDeleteSelected = () => {
console.log('حذف پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق حذف را پیاده‌سازی کنید
};
const handleUnarchiveSelected = () => {
console.log('خروج از آرشیو پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق خروج از آرشیو را پیاده‌سازی کنید
};
const getRowActions = (message: Message): RowActionItem[] => [
{
label: 'خروج از آرشیو',
icon: <ArchiveSlash size={16} color="black" />,
onClick: () => console.log('خروج از آرشیو', message.id),
},
{
label: 'حذف',
icon: <Trash size={16} color="red" />,
onClick: () => console.log('حذف پیام', message.id),
},
];
return (
<div className='mt-4'>
<h1>{t('draft.title')}</h1>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg md:text-xl xl:text-2xl font-bold mb-4 md:mb-0">{t('archive.title')}</h1>
<Filters
fields={[
{ type: 'date', name: 'from_date', placeholder: t('received.from_date') },
{ type: 'date', name: 'to_date', placeholder: t('received.to_date') },
{ type: 'date', name: 'from_date', placeholder: t('archive.from_date') },
{ type: 'date', name: 'to_date', placeholder: t('archive.to_date') },
{
type: 'select',
name: 'status',
placeholder: t('received.all'),
placeholder: t('archive.all'),
options: [
{ value: 'all', label: t('received.all') },
{ value: 'read', label: t('received.read') },
{ value: 'unread', label: t('received.unread') }
{ value: 'all', label: t('archive.all') },
{ value: 'read', label: t('archive.read') },
{ value: 'unread', label: t('archive.unread') }
]
},
{ type: 'input', name: 'search', placeholder: t('received.search') }
{ type: 'input', name: 'search', placeholder: t('archive.search') }
]}
onChange={handleFilterChange}
className="mt-8 flex justify-between items-center"
searchField="search"
/>
@@ -82,18 +128,20 @@ const ArchiveList: FC = () => {
isLoading={isLoading}
showHeader={false}
actions={tableActions}
selectedActions={selectedActions}
onSelectionChange={handleSelectionChange}
onRowClick={(id) => console.log(`کلیک روی پیام با شناسه ${id}`)}
noDataMessage={
<div className="flex flex-col items-center py-6">
<InfoCircle size={40} className="text-gray-300 mb-2" />
<div>هیچ پیامی یافت نشد</div>
<InfoCircle size={32} className="text-gray-300 mb-2" />
<div className="text-sm">هیچ پیام آرشیو شدهای یافت نشد</div>
</div>
}
selectable={true}
rowActions={getRowActions}
/>
</div>
)
}
export default ArchiveList
export default List
+72 -32
View File
@@ -1,13 +1,14 @@
import Filters, { FilterValues } from '../../components/Filters';
import { FC, ReactNode, useState } from 'react'
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 } from 'iconsax-react';
import { InfoCircle, More, Refresh2, Trash, Edit } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
interface Message extends Record<string, unknown> {
id: string;
title: string | ReactNode;
title: string;
sender: string;
date: string;
read: boolean;
@@ -16,11 +17,12 @@ interface Message extends Record<string, unknown> {
const List: FC = () => {
const { t } = useTranslation();
const [isLoading] = useState(false);
const [selectedMessages, setSelectedMessages] = useState<Message[]>([]);
const messageData: Message[] = [
{ id: '1', title: <div className='text-blue-500'>پیش نویس</div>, sender: 'علی محمدی', date: '1402/05/12', read: true },
{ id: '2', title: <div className='text-blue-500'>پیش نویس</div>, sender: 'زهرا احمدی', date: '1402/05/13', read: true },
{ id: '3', title: <div className='text-blue-500'>پیش نویس</div>, sender: 'مدیریت', date: '1402/05/14', read: true },
{ id: '1', title: 'اولین پیام', sender: 'علی محمدی', date: '1402/05/12', read: true },
{ id: '2', title: 'دومین پیام', sender: 'زهرا احمدی', date: '1402/05/13', read: true },
{ id: '3', title: 'جلسه هفتگی', sender: 'مدیریت', date: '1402/05/14', read: true },
];
const columns: ColumnType<Message>[] = [
@@ -29,48 +31,84 @@ const List: FC = () => {
title: 'عنوان پیام',
render: (item) => (
<div className="flex items-center">
{!item.read && <div className="w-2 h-2 rounded-full bg-blue-500 mr-2" />}
<span>{item.title}</span>
{!item.read && <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.title}</span>
</div>
)
},
{ key: 'sender', title: 'فرستنده' },
{ key: 'date', title: 'تاریخ', align: 'center' },
{
key: 'sender',
title: 'فرستنده',
render: (item) => (
<span className="truncate">{item.sender}</span>
)
},
{
key: 'date',
title: 'تاریخ',
align: 'center',
render: (item) => (
<span className="text-xs md:text-sm">{item.date}</span>
)
},
];
const tableActions = (
<div className='flex items-center gap-4'>
<Refresh2 size={20} color='black' />
<More size={20} color='black' className='rotate-90' />
<div className='flex items-center gap-2 md:gap-4'>
<Refresh2 size={18} color='black' className="cursor-pointer" />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div>
);
const selectedActions = (
<>
<Trash size={18} color='black' onClick={() => handleDeleteSelected()} className="cursor-pointer" />
<Edit size={18} color='black' onClick={() => handleEditSelected()} className="cursor-pointer" />
</>
);
const handleFilterChange = (newFilters: FilterValues) => {
console.log('Applied filters:', newFilters);
};
const handleSelectionChange = (selectedRows: Message[]) => {
setSelectedMessages(selectedRows);
};
const handleDeleteSelected = () => {
console.log('حذف پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق حذف را پیاده‌سازی کنید
};
const handleEditSelected = () => {
console.log('ویرایش پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق ویرایش را پیاده‌سازی کنید
};
const getRowActions = (message: Message): RowActionItem[] => [
{
label: 'ویرایش',
icon: <Edit size={16} color="black" />,
onClick: () => console.log('ویرایش پیام', message.id),
},
{
label: 'حذف',
icon: <Trash size={16} color="red" />,
onClick: () => console.log('حذف پیام', message.id),
},
];
return (
<div className='mt-4'>
<h1>{t('draft.title')}</h1>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg md:text-xl xl:text-2xl font-bold mb-4 md:mb-0">{t('draft.title')}</h1>
<Filters
fields={[
{ type: 'date', name: 'from_date', placeholder: t('received.from_date') },
{ type: 'date', name: 'to_date', placeholder: t('received.to_date') },
{
type: 'select',
name: 'status',
placeholder: t('received.all'),
options: [
{ value: 'all', label: t('received.all') },
{ value: 'read', label: t('received.read') },
{ value: 'unread', label: t('received.unread') }
]
},
{ type: 'input', name: 'search', placeholder: t('received.search') }
{ type: 'date', name: 'from_date', placeholder: t('draft.from_date') },
{ type: 'date', name: 'to_date', placeholder: t('draft.to_date') },
{ type: 'input', name: 'search', placeholder: t('draft.search') }
]}
onChange={handleFilterChange}
className="mt-8 flex justify-between items-center"
searchField="search"
/>
@@ -80,16 +118,18 @@ const List: FC = () => {
isLoading={isLoading}
showHeader={false}
actions={tableActions}
selectedActions={selectedActions}
onSelectionChange={handleSelectionChange}
onRowClick={(id) => console.log(`کلیک روی پیام با شناسه ${id}`)}
noDataMessage={
<div className="flex flex-col items-center py-6">
<InfoCircle size={40} className="text-gray-300 mb-2" />
<div>هیچ پیامی یافت نشد</div>
<InfoCircle size={32} className="text-gray-300 mb-2" />
<div className="text-sm">هیچ پیشنویسی یافت نشد</div>
</div>
}
selectable={true}
rowActions={getRowActions}
/>
</div>
)
}
+28 -1
View File
@@ -2,7 +2,34 @@ import { FC } from 'react'
const Home: FC = () => {
return (
<div>home page</div>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<div className="text-center py-12 md:py-20">
<h1 className="text-2xl md:text-3xl xl:text-4xl font-bold text-gray-800 mb-4">
خوش آمدید به سیستم مدیریت ایمیل
</h1>
<p className="text-sm md:text-base text-gray-600 mb-8 max-w-2xl mx-auto">
از منوی کناری میتوانید به بخشهای مختلف سیستم دسترسی داشته باشید
</p>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4 md:gap-6 mt-8 md:mt-12">
<div className="bg-white p-4 md:p-6 rounded-xl md:rounded-2xl shadow-sm border">
<h3 className="text-lg md:text-xl font-semibold mb-2">پیامهای دریافتی</h3>
<p className="text-xs md:text-sm text-gray-600">مدیریت ایمیلهای واردشده</p>
</div>
<div className="bg-white p-4 md:p-6 rounded-xl md:rounded-2xl shadow-sm border">
<h3 className="text-lg md:text-xl font-semibold mb-2">پیامهای ارسالی</h3>
<p className="text-xs md:text-sm text-gray-600">مشاهده ایمیلهای ارسال شده</p>
</div>
<div className="bg-white p-4 md:p-6 rounded-xl md:rounded-2xl shadow-sm border">
<h3 className="text-lg md:text-xl font-semibold mb-2">پیشنویسها</h3>
<p className="text-xs md:text-sm text-gray-600">ادامه نوشتن ایمیلهای ناتمام</p>
</div>
<div className="bg-white p-4 md:p-6 rounded-xl md:rounded-2xl shadow-sm border">
<h3 className="text-lg md:text-xl font-semibold mb-2">تنظیمات</h3>
<p className="text-xs md:text-sm text-gray-600">پیکربندی سیستم و حساب کاربری</p>
</div>
</div>
</div>
</div>
)
}
+80 -13
View File
@@ -3,7 +3,8 @@ 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 } from 'iconsax-react';
import { InfoCircle, More, Refresh2, Trash, Edit, Archive, ArchiveSlash } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
interface Message extends Record<string, unknown> {
id: string;
@@ -16,6 +17,7 @@ interface Message extends Record<string, unknown> {
const List: FC = () => {
const { t } = useTranslation();
const [isLoading] = useState(false);
const [selectedMessages, setSelectedMessages] = useState<Message[]>([]);
const messageData: Message[] = [
{ id: '1', title: 'اولین پیام', sender: 'علی محمدی', date: '1402/05/12', read: true },
@@ -29,29 +31,87 @@ const List: FC = () => {
title: 'عنوان پیام',
render: (item) => (
<div className="flex items-center">
{!item.read && <div className="w-2 h-2 rounded-full bg-blue-500 mr-2" />}
<span>{item.title}</span>
{!item.read && <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.title}</span>
</div>
)
},
{ key: 'sender', title: 'فرستنده' },
{ key: 'date', title: 'تاریخ', align: 'center' },
{
key: 'sender',
title: 'فرستنده',
render: (item) => (
<span className="truncate">{item.sender}</span>
)
},
{
key: 'date',
title: 'تاریخ',
align: 'center',
render: (item) => (
<span className="text-xs md:text-sm">{item.date}</span>
)
},
];
const tableActions = (
<div className='flex items-center gap-4'>
<Refresh2 size={20} color='black' />
<More size={20} color='black' className='rotate-90' />
<div className='flex items-center gap-2 md:gap-4'>
<Refresh2 size={18} color='black' className="cursor-pointer" />
<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" />
</>
);
const handleFilterChange = (newFilters: FilterValues) => {
console.log('Applied filters:', newFilters);
};
const handleSelectionChange = (selectedRows: Message[]) => {
setSelectedMessages(selectedRows);
};
const handleDeleteSelected = () => {
console.log('حذف پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق حذف را پیاده‌سازی کنید
};
const handleArchiveSelected = () => {
console.log('بایگانی پیام‌های انتخاب شده:', selectedMessages.map(m => m.id));
// اینجا منطق بایگانی را پیاده‌سازی کنید
};
const handleMarkAsReadSelected = () => {
console.log('علامت‌گذاری به عنوان خوانده شده:', selectedMessages.map(m => m.id));
// اینجا منطق علامت‌گذاری را پیاده‌سازی کنید
};
const getRowActions = (message: Message): RowActionItem[] => [
{
label: 'خروج از آرشیو',
icon: <ArchiveSlash size={16} color="black" />,
onClick: () => console.log('خروج از آرشیو', message.id),
},
{
label: 'خوانده شده',
icon: <Edit size={16} color="black" />,
onClick: () => console.log('علامت‌گذاری به عنوان خوانده شده', message.id),
},
{
label: 'حذف',
icon: <Trash size={16} color="red" />,
onClick: () => console.log('حذف پیام', message.id),
},
];
return (
<div className='mt-4'>
<h1>{t('received.title')}</h1>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg md:text-xl xl:text-2xl font-bold mb-4 md:mb-0">{t('received.title')}</h1>
<Filters
fields={[
@@ -70,7 +130,6 @@ const List: FC = () => {
{ type: 'input', name: 'search', placeholder: t('received.search') }
]}
onChange={handleFilterChange}
className="mt-8 flex justify-between items-center"
searchField="search"
/>
@@ -80,14 +139,22 @@ const List: FC = () => {
isLoading={isLoading}
showHeader={false}
actions={tableActions}
selectedActions={selectedActions}
onSelectionChange={handleSelectionChange}
onRowClick={(id) => console.log(`کلیک روی پیام با شناسه ${id}`)}
noDataMessage={
<div className="flex flex-col items-center py-6">
<InfoCircle size={40} className="text-gray-300 mb-2" />
<div>هیچ پیامی یافت نشد</div>
<InfoCircle size={32} className="text-gray-300 mb-2" />
<div className="text-sm">هیچ پیامی یافت نشد</div>
</div>
}
selectable={true}
rowActions={getRowActions}
pagination={{
totalPages: 10,
currentPage: 1,
onPageChange: () => { }
}}
/>
</div>
+24 -12
View File
@@ -29,19 +29,32 @@ const List: FC = () => {
title: 'عنوان پیام',
render: (item) => (
<div className="flex items-center">
{!item.read && <div className="w-2 h-2 rounded-full bg-blue-500 mr-2" />}
<span>{item.title}</span>
{!item.read && <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.title}</span>
</div>
)
},
{ key: 'sender', title: 'فرستنده' },
{ key: 'date', title: 'تاریخ', align: 'center' },
{
key: 'sender',
title: 'فرستنده',
render: (item) => (
<span className="truncate">{item.sender}</span>
)
},
{
key: 'date',
title: 'تاریخ',
align: 'center',
render: (item) => (
<span className="text-xs md:text-sm">{item.date}</span>
)
},
];
const tableActions = (
<div className='flex items-center gap-4'>
<Refresh2 size={20} color='black' />
<More size={20} color='black' className='rotate-90' />
<div className='flex items-center gap-2 md:gap-4'>
<Refresh2 size={18} color='black' className="cursor-pointer" />
<More size={18} color='black' className='rotate-90 cursor-pointer' />
</div>
);
@@ -50,8 +63,8 @@ const List: FC = () => {
};
return (
<div className='mt-4'>
<h1>{t('sent.title')}</h1>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg md:text-xl xl:text-2xl font-bold mb-4 md:mb-0">{t('sent.title')}</h1>
<Filters
fields={[
@@ -70,7 +83,6 @@ const List: FC = () => {
{ type: 'input', name: 'search', placeholder: t('sent.search') }
]}
onChange={handleFilterChange}
className="mt-8 flex justify-between items-center"
searchField="search"
/>
@@ -83,8 +95,8 @@ const List: FC = () => {
onRowClick={(id) => console.log(`کلیک روی پیام با شناسه ${id}`)}
noDataMessage={
<div className="flex flex-col items-center py-6">
<InfoCircle size={40} className="text-gray-300 mb-2" />
<div>هیچ پیامی یافت نشد</div>
<InfoCircle size={32} className="text-gray-300 mb-2" />
<div className="text-sm">هیچ پیامی یافت نشد</div>
</div>
}
selectable={true}
+14 -10
View File
@@ -23,9 +23,13 @@ const Setting: FC = () => {
return <Address />;
case SettingTabEnum.SETTING_PERSONALITY:
return (
<div className='flex flex-row-reverse gap-6 mt-8'>
<PersonalitySidebar />
<Personality />
<div className='flex flex-col xl:flex-row-reverse gap-4 md:gap-6 mt-6 md:mt-8'>
<div className="xl:w-auto w-full">
<PersonalitySidebar />
</div>
<div className="flex-1">
<Personality />
</div>
</div>
);
default:
@@ -34,29 +38,29 @@ const Setting: FC = () => {
};
return (
<div className='mt-4'>
<h1 className='text-2xl font-bold text-right'>{t('setting.title')}</h1>
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className='text-lg md:text-xl xl:text-2xl font-bold text-right mb-4 md:mb-0'>{t('setting.title')}</h1>
<div className='mt-7'>
<div className='mt-4 md:mt-7'>
<Tabs
items={[
{
icon: <Setting3 size={22} color={activeTab === SettingTabEnum.SETTING_MAIL_SERVER ? 'black' : '#8C90A3'} />,
icon: <Setting3 size={20} color={activeTab === SettingTabEnum.SETTING_MAIL_SERVER ? 'black' : '#8C90A3'} />,
label: t('setting.mail_server'),
value: SettingTabEnum.SETTING_MAIL_SERVER
},
{
icon: <Global size={22} color={activeTab === SettingTabEnum.SETTING_DOMAIN ? 'black' : '#8C90A3'} />,
icon: <Global size={20} color={activeTab === SettingTabEnum.SETTING_DOMAIN ? 'black' : '#8C90A3'} />,
label: t('setting.domain'),
value: SettingTabEnum.SETTING_DOMAIN
},
{
icon: <People size={22} color={activeTab === SettingTabEnum.SETTING_ADDRESS ? 'black' : '#8C90A3'} />,
icon: <People size={20} color={activeTab === SettingTabEnum.SETTING_ADDRESS ? 'black' : '#8C90A3'} />,
label: t('setting.address'),
value: SettingTabEnum.SETTING_ADDRESS
},
{
icon: <Brush2 size={22} color={activeTab === SettingTabEnum.SETTING_PERSONALITY ? 'black' : '#8C90A3'} />,
icon: <Brush2 size={20} color={activeTab === SettingTabEnum.SETTING_PERSONALITY ? 'black' : '#8C90A3'} />,
label: t('setting.personality'),
value: SettingTabEnum.SETTING_PERSONALITY
}