all filters + and add star inside checkbox

This commit is contained in:
hamid zarghami
2025-07-23 15:44:46 +03:30
parent 0778ecae76
commit 1f3dcac623
27 changed files with 262 additions and 128 deletions
+4 -14
View File
@@ -116,23 +116,13 @@ const List: FC = () => {
return (
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg mb-4 md:mb-0">سطل آشغال</h1>
<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: 'جستجو...' }
{ type: 'date', name: 'datestart', placeholder: 'از تاریخ' },
{ type: 'date', name: 'dateend', placeholder: 'تا تاریخ' },
{ type: 'input', name: 'search', placeholder: 'جستجو' }
]}
onChange={handleFilterChange}
searchField="search"
+17 -1
View File
@@ -1,10 +1,26 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import { MessageListQueryDto, TrashResponse } from "../types/TrashTypes";
export const getTrashMessages = async (
query: MessageListQueryDto
): Promise<TrashResponse> => {
const { data } = await axios.get(`/email/messages/trash`, { params: query });
console.log("query", query);
const isSearch =
!!query.search || !!query.datestart || query.dateend || query.from;
const url = isSearch ? "search" : "messages/trash";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("Trash");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: queryWithMailbox,
});
return data;
};
+7 -4
View File
@@ -37,11 +37,14 @@ export interface TrashMessage extends Record<string, unknown> {
export interface MessageListQueryDto {
page?: number;
limit?: number;
order?: "asc" | "desc";
search?: string;
dateFrom?: string;
dateTo?: string;
isRead?: string;
from?: string;
subject?: string;
datestart?: string;
dateend?: string;
attachments?: boolean;
flagged?: boolean;
order?: "asc" | "desc";
}
export interface TrashResponse {
+4 -14
View File
@@ -114,23 +114,13 @@ const List: FC = () => {
return (
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg mb-4 md:mb-0">آرشیو</h1>
<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: 'جستجو...' }
{ type: 'date', name: 'datestart', placeholder: 'از تاریخ' },
{ type: 'date', name: 'dateend', placeholder: 'تا تاریخ' },
{ type: 'input', name: 'search', placeholder: 'جستجو' }
]}
onChange={handleFilterChange}
searchField="search"
+16 -2
View File
@@ -1,11 +1,25 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import { MessageListQueryDto, ArchiveResponse } from "../types/ArchiveTypes";
export const getArchiveMessages = async (
query: MessageListQueryDto
): Promise<ArchiveResponse> => {
const { data } = await axios.get(`/email/messages/archive`, {
params: query,
console.log("query", query);
const isSearch =
!!query.search || !!query.datestart || query.dateend || query.from;
const url = isSearch ? "search" : "messages/archive";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("Archive");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: queryWithMailbox,
});
return data;
};
+7 -4
View File
@@ -37,11 +37,14 @@ export interface ArchiveMessage extends Record<string, unknown> {
export interface MessageListQueryDto {
page?: number;
limit?: number;
order?: "asc" | "desc";
search?: string;
dateFrom?: string;
dateTo?: string;
isRead?: string;
from?: string;
subject?: string;
datestart?: string;
dateend?: string;
attachments?: boolean;
flagged?: boolean;
order?: "asc" | "desc";
}
export interface ArchiveResponse {
+2 -2
View File
@@ -184,8 +184,8 @@ const List: FC = () => {
<Filters
fields={[
{ type: 'date', name: 'dateFrom', placeholder: t('draft.from_date') },
{ type: 'date', name: 'dateTo', placeholder: t('draft.to_date') },
{ type: 'date', name: 'datestart', placeholder: t('draft.from_date') },
{ type: 'date', name: 'dateend', placeholder: t('draft.to_date') },
{ type: 'input', name: 'search', placeholder: t('draft.search') }
]}
onChange={handleFilterChange}
+17 -1
View File
@@ -1,4 +1,5 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import {
MessageListQueryDto,
InboxResponse,
@@ -9,7 +10,22 @@ import {
export const getDrafts = async (
query: MessageListQueryDto
): Promise<InboxResponse> => {
const { data } = await axios.get(`/email/messages/drafts`, { params: query });
console.log("query", query);
const isSearch =
!!query.search || !!query.datestart || query.dateend || query.from;
const url = isSearch ? "search" : "messages/drafts";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("Drafts");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: queryWithMailbox,
});
return data;
};
+5 -6
View File
@@ -21,15 +21,14 @@ export interface EmailAttachmentDto {
export interface MessageListQueryDto {
page?: number;
limit?: number;
order?: string;
search?: string;
from?: string;
subject?: string;
dateFrom?: string;
dateTo?: string;
hasAttachment?: boolean;
isRead?: boolean;
isFlagged?: boolean;
datestart?: string;
dateend?: string;
attachments?: boolean;
flagged?: boolean;
order?: "asc" | "desc";
}
export interface DraftMessage extends Record<string, unknown> {
+7 -17
View File
@@ -2,7 +2,7 @@ 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, Star, Archive } from 'iconsax-react';
import { InfoCircle, More, Refresh2, Trash, Archive, Star1 } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate } from 'react-router-dom';
import { useGetFavoriteMessages } from './hooks/useFavoriteData';
@@ -66,7 +66,7 @@ const List: FC = () => {
const selectedActions = (
<>
<Star size={18} color='black' onClick={() => handleUnfavoriteSelected()} className="cursor-pointer" />
<Star1 variant='Bold' size={18} color="#FFC107" onClick={() => handleUnfavoriteSelected()} className="cursor-pointer" />
<Archive size={18} color='black' onClick={() => handleArchiveSelected()} className="cursor-pointer" />
<Trash size={18} color='black' onClick={() => handleDeleteSelected()} className="cursor-pointer" />
</>
@@ -102,7 +102,7 @@ const List: FC = () => {
const getRowActions = (message: FavoriteMessage): RowActionItem[] => [
{
label: 'حذف از علاقه‌مندی‌ها',
icon: <Star size={16} color="black" />,
icon: <Star1 variant='Bold' size={16} color="#FFC107" />,
onClick: () => emailActions.unfavorite({ messageId: message.id, mailbox: message.mailbox }),
},
{
@@ -126,23 +126,13 @@ const List: FC = () => {
return (
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg mb-4 md:mb-0">علاقهمندیها</h1>
<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: 'جستجو...' }
{ type: 'date', name: 'datestart', placeholder: 'از تاریخ' },
{ type: 'date', name: 'dateend', placeholder: 'تا تاریخ' },
{ type: 'input', name: 'search', placeholder: 'جستجو' }
]}
onChange={handleFilterChange}
searchField="search"
+16 -2
View File
@@ -1,11 +1,25 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import { MessageListQueryDto, FavoriteResponse } from "../types/FavoriteTypes";
export const getFavoriteMessages = async (
query: MessageListQueryDto
): Promise<FavoriteResponse> => {
const { data } = await axios.get(`/email/messages/favorite`, {
params: query,
console.log("query", query);
const isSearch =
!!query.search || !!query.datestart || query.dateend || query.from;
const url = isSearch ? "search" : "messages/favorite";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("FAVORITE");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: queryWithMailbox,
});
return data;
};
+7 -4
View File
@@ -37,11 +37,14 @@ export interface FavoriteMessage extends Record<string, unknown> {
export interface MessageListQueryDto {
page?: number;
limit?: number;
order?: "asc" | "desc";
search?: string;
dateFrom?: string;
dateTo?: string;
isRead?: string;
from?: string;
subject?: string;
datestart?: string;
dateend?: string;
attachments?: boolean;
flagged?: boolean;
order?: "asc" | "desc";
}
export interface FavoriteResponse {
@@ -0,0 +1,36 @@
import { FC, useState } from 'react'
import { Star1 } from 'iconsax-react'
import { useMoveToFavorite, useUnFavoriteMessage } from '../hooks/useEmailData';
const Favorite: FC<{ flagged: boolean, id: string, mailbox: string }> = ({ flagged, id, mailbox }) => {
const [isFavorite, setIsFavorite] = useState<boolean>(flagged)
const { mutate: moveToFavorite } = useMoveToFavorite()
const { mutate: unFavoriteMessage } = useUnFavoriteMessage()
const handleFavoriteClick = (e: React.MouseEvent) => {
e.preventDefault()
e.stopPropagation()
console.log('Favorite clicked!', { isFavorite, id, mailbox })
if (isFavorite) {
unFavoriteMessage({ messageId: id || '', mailbox: mailbox || '' })
} else {
moveToFavorite({ messageId: id || '', mailbox: mailbox || '' })
}
setIsFavorite(!isFavorite)
}
return (
<div className="inline-block mt-[3px] relative -right-6" onClick={handleFavoriteClick}>
<Star1
variant={isFavorite ? 'Bold' : 'Outline'}
size={18}
color={isFavorite ? '#FFC107' : '#8C90A3'}
className='cursor-pointer select-none'
/>
</div>
)
};
export default Favorite;
+2 -2
View File
@@ -10,7 +10,7 @@ import { MailboxEnum } from '../enum/Enum'
import MessageFavorite from './MessageFavorite'
import MessageTrash from './MessageTrash'
const Header: FC<{ mailBoxName: MailboxEnum }> = ({ mailBoxName }) => {
const Header: FC<{ mailBoxName: MailboxEnum, flagged: boolean }> = ({ mailBoxName, flagged }) => {
const navigate = useNavigate()
const { t } = useTranslation()
@@ -22,7 +22,7 @@ const Header: FC<{ mailBoxName: MailboxEnum }> = ({ mailBoxName }) => {
<MessageUnread />
<MessageSpam isActiveSpam={mailBoxName === MailboxEnum.Junk} />
<MessageArchive isActiveArchive={mailBoxName === MailboxEnum.ARCHIVE} />
<MessageFavorite isActiveFavorite={mailBoxName === MailboxEnum.FAVORITE} />
<MessageFavorite flagged={flagged} />
{/* <VolumeMute size={18} color='black' className='xl:block hidden' /> */}
<MessageTrash isActiveTrash={mailBoxName === MailboxEnum.TRASH} />
{/* <More size={18} color='black' className='rotate-90' /> */}
@@ -3,8 +3,8 @@ import { FC, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { useMoveToFavorite, useUnFavoriteMessage } from '../hooks/useEmailData'
const MessageFavorite: FC<{ isActiveFavorite: boolean }> = ({ isActiveFavorite }) => {
const [isFavorite, setIsFavorite] = useState<boolean>(isActiveFavorite)
const MessageFavorite: FC<{ flagged: boolean }> = ({ flagged }) => {
const [isFavorite, setIsFavorite] = useState<boolean>(flagged)
const { id, mailbox } = useParams<{ id: string, mailbox: string }>()
const { mutate: moveToFavorite } = useMoveToFavorite()
const { mutate: unFavoriteMessage } = useUnFavoriteMessage()
+1 -1
View File
@@ -141,7 +141,7 @@ const DetailEmail: FC = () => {
return (
<div className='bg-white rounded-4xl p-8'>
<Header mailBoxName={messageDetail?.mailboxName as MailboxEnum} />
<Header flagged={messageDetail?.flagged || false} mailBoxName={messageDetail?.mailboxName as MailboxEnum} />
<div className='mt-6 flex xl:flex-row flex-col justify-between xl:items-center'>
<div className='flex xl:flex-row flex-col-reverse gap-4 xl:items-center'>
+10 -13
View File
@@ -1,22 +1,20 @@
import Filters, { FilterValues } from '../../components/Filters';
import { FC, useState, useEffect } 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, Trash, Edit, Archive, ArchiveTick, Star1 } from 'iconsax-react';
import { RowActionItem } from '../../components/RowActionsDropdown';
import { useNavigate, useLocation } from 'react-router-dom';
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';
import { useQueryClient } from '@tanstack/react-query';
import Favorite from './Components/Favorite';
const List: FC = () => {
const queryClient = useQueryClient();
const navigate = useNavigate();
const location = useLocation();
const { t } = useTranslation();
const [currentPage, setCurrentPage] = useState(1);
const [filters, setFilters] = useState<FilterValues>({});
@@ -28,18 +26,17 @@ const List: FC = () => {
...filters
});
// Force refresh when component mounts or location changes
useEffect(() => {
// Refetch when coming back to inbox from other pages
if (location.pathname === '/') {
refetch();
queryClient.invalidateQueries({ queryKey: ['mailbox-count'] });
}
}, [location.pathname, refetch]);
const [selectedMessages, setSelectedMessages] = useState<InboxMessage[]>([]);
const columns: ColumnType<InboxMessage>[] = [
{
key: 'flagged',
title: 'علامت گذاری',
render: (item) => (
<Favorite flagged={item.flagged} id={item.id.toString()} mailbox={item.mailbox} />
)
},
{
key: 'subject',
title: 'عنوان پیام',
+9 -1
View File
@@ -1,4 +1,5 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import {
SendEmailDto,
MessageListQueryDto,
@@ -37,8 +38,15 @@ export const getInbox = async (
query.from;
const url = isSearch ? "search" : "messages/inbox";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("INBOX");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: query,
params: queryWithMailbox,
});
return data;
};
+4 -14
View File
@@ -147,23 +147,13 @@ const List: FC = () => {
return (
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg mb-4 md:mb-0">ارسال شده</h1>
<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: 'جستجو...' }
{ type: 'date', name: 'datestart', placeholder: 'از تاریخ' },
{ type: 'date', name: 'dateend', placeholder: 'تا تاریخ' },
{ type: 'input', name: 'search', placeholder: 'جستجو' }
]}
onChange={handleFilterChange}
searchField="search"
+17 -1
View File
@@ -1,4 +1,5 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import {
MessageListQueryDto,
InboxResponse,
@@ -9,7 +10,22 @@ import {
export const getSentMessages = async (
query: MessageListQueryDto
): Promise<InboxResponse> => {
const { data } = await axios.get(`/email/messages/sent`, { params: query });
console.log("query", query);
const isSearch =
!!query.search || !!query.datestart || query.dateend || query.from;
const url = isSearch ? "search" : "messages/sent";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("Sent Mail");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: queryWithMailbox,
});
return data;
};
+7 -3
View File
@@ -2,9 +2,13 @@ export interface MessageListQueryDto {
page?: number;
limit?: number;
search?: string;
from_date?: string;
to_date?: string;
status?: "all" | "read" | "unread";
from?: string;
subject?: string;
datestart?: string;
dateend?: string;
attachments?: boolean;
flagged?: boolean;
order?: "asc" | "desc";
}
export interface EmailAddress {
+4 -14
View File
@@ -113,23 +113,13 @@ const List: FC = () => {
return (
<div className='mt-2 md:mt-4 px-2 md:px-0'>
<h1 className="text-lg mb-4 md:mb-0">پیامهای اسپم</h1>
<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: 'جستجو...' }
{ type: 'date', name: 'datestart', placeholder: 'از تاریخ' },
{ type: 'date', name: 'dateend', placeholder: 'تا تاریخ' },
{ type: 'input', name: 'search', placeholder: 'جستجو' }
]}
onChange={handleFilterChange}
searchField="search"
+17 -1
View File
@@ -1,9 +1,25 @@
import axios from "../../../config/axios";
import { getMailboxId } from "../../../config/func";
import { MessageListQueryDto, SpamResponse } from "../types/SpamTypes";
export const getSpamMessages = async (
query: MessageListQueryDto
): Promise<SpamResponse> => {
const { data } = await axios.get(`/email/messages/junk`, { params: query });
console.log("query", query);
const isSearch =
!!query.search || !!query.datestart || query.dateend || query.from;
const url = isSearch ? "search" : "messages/junk";
// اضافه کردن mailbox id از localStorage
const mailboxId = getMailboxId("Junk");
const queryWithMailbox = {
...query,
mailbox: mailboxId,
};
const { data } = await axios.get(`/email/${url}`, {
params: queryWithMailbox,
});
return data;
};
+7 -4
View File
@@ -37,11 +37,14 @@ export interface SpamMessage extends Record<string, unknown> {
export interface MessageListQueryDto {
page?: number;
limit?: number;
order?: "asc" | "desc";
search?: string;
dateFrom?: string;
dateTo?: string;
isRead?: string;
from?: string;
subject?: string;
datestart?: string;
dateend?: string;
attachments?: boolean;
flagged?: boolean;
order?: "asc" | "desc";
}
export interface SpamResponse {