mark all as read + spam empty
This commit is contained in:
@@ -7,7 +7,7 @@ VITE_SOCKET_URL = 'wss://dmail-api.danakcorp.com/email'
|
|||||||
# VITE_SOCKET_URL = 'ws://192.168.1.118:4000/email'
|
# VITE_SOCKET_URL = 'ws://192.168.1.118:4000/email'
|
||||||
|
|
||||||
VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
|
VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
|
||||||
# VITE_BASE_URL = 'http://192.168.1.101:4000'
|
# VITE_BASE_URL = 'http://192.168.1.106:4000'
|
||||||
|
|
||||||
|
|
||||||
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
|
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { FC, useState } from 'react'
|
||||||
|
import DefaulModal from './DefaulModal'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Button from './Button'
|
||||||
|
import Textarea from './Textarea'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isLoading?: boolean,
|
||||||
|
close: () => void,
|
||||||
|
isOpen: boolean,
|
||||||
|
onConfrim: (text?: string) => void,
|
||||||
|
label?: string,
|
||||||
|
isHasDescription?: boolean,
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModalConfrim: FC<Props> = (props: Props) => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const [description, setDescription] = useState<string>('')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DefaulModal
|
||||||
|
open={props.isOpen}
|
||||||
|
close={props.close}
|
||||||
|
title_header={props.title ? props.title : t('confrim.subject')}
|
||||||
|
isHeader
|
||||||
|
>
|
||||||
|
<div className='mt-6'>
|
||||||
|
<div className='text-sm text-center'>
|
||||||
|
{
|
||||||
|
props.label ?
|
||||||
|
props.label
|
||||||
|
:
|
||||||
|
t('confrim.content')
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
props.isHasDescription &&
|
||||||
|
<div className='mt-4'>
|
||||||
|
<Textarea
|
||||||
|
placeholder={t('description')}
|
||||||
|
onChange={(e) => setDescription(e.target.value)}
|
||||||
|
value={description}
|
||||||
|
className='bg-transparent border border-gray-500 rounded-xl w-[300px] p-2'
|
||||||
|
label=''
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-4 justify-center mt-10'>
|
||||||
|
<Button
|
||||||
|
label={t('confrim.yes')}
|
||||||
|
onClick={() => props.onConfrim(props.isHasDescription ? description : undefined)}
|
||||||
|
loading={props.isLoading}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label={t('confrim.cancel')}
|
||||||
|
className='bg-transparent text-black border border-primary'
|
||||||
|
onClick={props.close}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DefaulModal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalConfrim
|
||||||
+8
-1
@@ -156,6 +156,12 @@
|
|||||||
"cancel": "انصراف",
|
"cancel": "انصراف",
|
||||||
"confirm_disable": "تایید غیر فعال سازی"
|
"confirm_disable": "تایید غیر فعال سازی"
|
||||||
},
|
},
|
||||||
|
"confrim": {
|
||||||
|
"subject": "حذف",
|
||||||
|
"content": "برای حذف این آیتم مطمئن هستید؟",
|
||||||
|
"yes": "بله",
|
||||||
|
"cancel": "لغو"
|
||||||
|
},
|
||||||
"success": "عملیات با موفقیت انجام شد",
|
"success": "عملیات با موفقیت انجام شد",
|
||||||
"attachment_select": "اضافه کردن فایل ضمیمه",
|
"attachment_select": "اضافه کردن فایل ضمیمه",
|
||||||
"domain": {
|
"domain": {
|
||||||
@@ -203,7 +209,8 @@
|
|||||||
"Junk": "هرزنامهها",
|
"Junk": "هرزنامهها",
|
||||||
"SENT": "ارسال شدهها",
|
"SENT": "ارسال شدهها",
|
||||||
"TRASH": "سطل زباله",
|
"TRASH": "سطل زباله",
|
||||||
"Sent Mail": "ارسال شده ها"
|
"Sent Mail": "ارسال شده ها",
|
||||||
|
"Trash": "سطل زباله"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"welcome": "خوش آمدید",
|
"welcome": "خوش آمدید",
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ import Filters, { FilterValues } from '../../components/Filters';
|
|||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import Table from '../../components/Table';
|
import Table from '../../components/Table';
|
||||||
import { ColumnType } from '../../components/types/TableTypes';
|
import { ColumnType } from '../../components/types/TableTypes';
|
||||||
import { InfoCircle, More, Refresh2, Trash, RecoveryConvert } from 'iconsax-react';
|
import { InfoCircle, Refresh2, Trash, RecoveryConvert } from 'iconsax-react';
|
||||||
import { RowActionItem } from '../../components/RowActionsDropdown';
|
import { RowActionItem } from '../../components/RowActionsDropdown';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useGetTrashMessages } from './hooks/useTrashData';
|
import { useEmptyTrash, useGetTrashMessages } from './hooks/useTrashData';
|
||||||
import { TrashMessage } from './types/TrashTypes';
|
import { TrashMessage } from './types/TrashTypes';
|
||||||
import { formatDate } from '@/config/func';
|
import { formatDate } from '@/config/func';
|
||||||
import { useEmailActions } from '@/hooks/useEmailActions';
|
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';
|
||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -16,7 +20,8 @@ const List: FC = () => {
|
|||||||
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const { mutate: emptyTrash, isPending } = useEmptyTrash();
|
||||||
const { data: trashData, isLoading, refetch, isFetching } = useGetTrashMessages({
|
const { data: trashData, isLoading, refetch, isFetching } = useGetTrashMessages({
|
||||||
next: nextCursor,
|
next: nextCursor,
|
||||||
previous: previousCursor,
|
previous: previousCursor,
|
||||||
@@ -59,10 +64,15 @@ const List: FC = () => {
|
|||||||
<Refresh2
|
<Refresh2
|
||||||
size={18}
|
size={18}
|
||||||
color='black'
|
color='black'
|
||||||
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
|
className={`cursor-pointer min-w-[18px] ${isFetching ? 'animate-spin-reverse' : ''}`}
|
||||||
onClick={() => refetch()}
|
onClick={() => refetch()}
|
||||||
/>
|
/>
|
||||||
<More size={18} color='black' className='rotate-90 cursor-pointer' />
|
<Button
|
||||||
|
label='خالی کردن سطل زباله'
|
||||||
|
className='h-8'
|
||||||
|
onClick={() => setShowModal(true)}
|
||||||
|
loading={isPending}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -95,6 +105,18 @@ const List: FC = () => {
|
|||||||
setSelectedMessages([]);
|
setSelectedMessages([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleTrash = () => {
|
||||||
|
emptyTrash(undefined, {
|
||||||
|
onSuccess: () => {
|
||||||
|
refetch();
|
||||||
|
setShowModal(false);
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast(error.response?.data?.error.message[0], 'error')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getRowActions = (message: TrashMessage): RowActionItem[] => [
|
const getRowActions = (message: TrashMessage): RowActionItem[] => [
|
||||||
{
|
{
|
||||||
label: 'بازگردانی',
|
label: 'بازگردانی',
|
||||||
@@ -108,10 +130,6 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleNext = (cursor?: string) => {
|
const handleNext = (cursor?: string) => {
|
||||||
setNextCursor(cursor);
|
setNextCursor(cursor);
|
||||||
setPreviousCursor(undefined);
|
setPreviousCursor(undefined);
|
||||||
@@ -165,6 +183,13 @@ const List: FC = () => {
|
|||||||
onPrevious: handlePrevious
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ModalConfrim
|
||||||
|
isOpen={showModal}
|
||||||
|
close={() => setShowModal(false)}
|
||||||
|
onConfrim={handleTrash}
|
||||||
|
isLoading={isPending}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { getTrashMessages } from '../service/TrashService';
|
import { emptyTrash, getTrashMessages } from '../service/TrashService';
|
||||||
import { MessageListQueryDto } from '../types/TrashTypes';
|
import { MessageListQueryDto } from '../types/TrashTypes';
|
||||||
|
|
||||||
export const useGetTrashMessages = (query: MessageListQueryDto) => {
|
export const useGetTrashMessages = (query: MessageListQueryDto) => {
|
||||||
@@ -10,4 +10,8 @@ export const useGetTrashMessages = (query: MessageListQueryDto) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: useRestoreMessage is now handled by useEmailActions hook
|
export const useEmptyTrash = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: () => emptyTrash(),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { MailboxEnum } from "@/pages/received/enum/Enum";
|
||||||
import axios from "../../../config/axios";
|
import axios from "../../../config/axios";
|
||||||
import { getMailboxId } from "../../../config/func";
|
import { getMailboxId } from "../../../config/func";
|
||||||
import { MessageListQueryDto, TrashResponse } from "../types/TrashTypes";
|
import { MessageListQueryDto, TrashResponse } from "../types/TrashTypes";
|
||||||
@@ -25,3 +26,11 @@ export const getTrashMessages = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Note: deleteMessagePermanently and restoreMessage are now handled by EmailActionsService
|
// Note: deleteMessagePermanently and restoreMessage are now handled by EmailActionsService
|
||||||
|
|
||||||
|
export const emptyTrash = async () => {
|
||||||
|
const mailboxId = getMailboxId(MailboxEnum.TRASH);
|
||||||
|
const { data } = await axios.patch(
|
||||||
|
`/email/messages/empty-trash?mailbox=${mailboxId}`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { ColumnType } from '../../components/types/TableTypes';
|
|||||||
import { InfoCircle, More, Refresh2, Trash, Edit, Archive, ArchiveTick, Star1 } from 'iconsax-react';
|
import { InfoCircle, More, Refresh2, Trash, Edit, Archive, ArchiveTick, Star1 } from 'iconsax-react';
|
||||||
import { RowActionItem } from '../../components/RowActionsDropdown';
|
import { RowActionItem } from '../../components/RowActionsDropdown';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useGetInbox, useSummarizeEmail } from './hooks/useEmailData';
|
import { useGetInbox, useMarkAllRead, useSummarizeEmail } from './hooks/useEmailData';
|
||||||
import { InboxMessage } from './types/Types';
|
import { InboxMessage } from './types/Types';
|
||||||
import { formatDate } from '@/config/func';
|
import { formatDate } from '@/config/func';
|
||||||
import MarkAsRead from '@/assets/images/mark_as_read.svg'
|
import MarkAsRead from '@/assets/images/mark_as_read.svg'
|
||||||
@@ -15,6 +15,10 @@ import Favorite from './Components/Favorite';
|
|||||||
import Summerize from './Components/Summerize';
|
import Summerize from './Components/Summerize';
|
||||||
import Intelligense from '@/assets/images/intelligense.svg'
|
import Intelligense from '@/assets/images/intelligense.svg'
|
||||||
import SummarizeModal from './Components/SummarizeModal';
|
import SummarizeModal from './Components/SummarizeModal';
|
||||||
|
import Button from '@/components/Button';
|
||||||
|
import ModalConfrim from '@/components/ModalConfrim';
|
||||||
|
import { ErrorType } from '@/helpers/types';
|
||||||
|
import { toast } from '@/components/Toast';
|
||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
|
|
||||||
@@ -25,7 +29,9 @@ const List: FC = () => {
|
|||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
const [openSummarizeModal, setOpenSummarizeModal] = useState(false);
|
const [openSummarizeModal, setOpenSummarizeModal] = useState(false);
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
const { mutate: summarizeEmail, isPending: isSummarizing, data: summarizeData } = useSummarizeEmail();
|
const { mutate: summarizeEmail, isPending: isSummarizing, data: summarizeData } = useSummarizeEmail();
|
||||||
|
const { mutate: markAllRead, isPending: isMarkingAllRead } = useMarkAllRead();
|
||||||
|
|
||||||
const { data: inboxData, isLoading, refetch, isFetching } = useGetInbox({
|
const { data: inboxData, isLoading, refetch, isFetching } = useGetInbox({
|
||||||
next: nextCursor,
|
next: nextCursor,
|
||||||
@@ -77,9 +83,15 @@ const List: FC = () => {
|
|||||||
<Refresh2
|
<Refresh2
|
||||||
size={18}
|
size={18}
|
||||||
color='black'
|
color='black'
|
||||||
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
|
className={`cursor-pointer min-w-[18px] ${isFetching ? 'animate-spin-reverse' : ''}`}
|
||||||
onClick={() => refetch()}
|
onClick={() => refetch()}
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
label='علامتگذاری همه به عنوان خوانده شده'
|
||||||
|
className='h-8'
|
||||||
|
onClick={() => setShowModal(true)}
|
||||||
|
loading={isMarkingAllRead}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -147,6 +159,18 @@ const List: FC = () => {
|
|||||||
setSelectedMessages([]);
|
setSelectedMessages([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleMarkAll = () => {
|
||||||
|
markAllRead(undefined, {
|
||||||
|
onSuccess: () => {
|
||||||
|
refetch();
|
||||||
|
setShowModal(false);
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast(error.response?.data?.error.message[0], 'error')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getInlineActions = (item: InboxMessage) => [
|
const getInlineActions = (item: InboxMessage) => [
|
||||||
{
|
{
|
||||||
icon: <Favorite flagged={item.flagged} id={item.id.toString()} mailbox={item.mailbox} />,
|
icon: <Favorite flagged={item.flagged} id={item.id.toString()} mailbox={item.mailbox} />,
|
||||||
@@ -285,6 +309,15 @@ const List: FC = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<ModalConfrim
|
||||||
|
isOpen={showModal}
|
||||||
|
close={() => setShowModal(false)}
|
||||||
|
onConfrim={handleMarkAll}
|
||||||
|
isLoading={isMarkingAllRead}
|
||||||
|
title={'خواندن همه'}
|
||||||
|
label={'آیا از خواندن همه پیام ها اطمینان دارید؟'}
|
||||||
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,3 +131,9 @@ export const useGenerateEmail = () => {
|
|||||||
mutationFn: (params: GenerateEmailRequest) => api.generateEmail(params),
|
mutationFn: (params: GenerateEmailRequest) => api.generateEmail(params),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useMarkAllRead = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: () => api.markAllRead(),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
SummarizeEmailRequest,
|
SummarizeEmailRequest,
|
||||||
GenerateEmailRequest,
|
GenerateEmailRequest,
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
import { MailboxEnum } from "../enum/Enum";
|
||||||
|
|
||||||
export const sendEmail = async (params: SendEmailDto) => {
|
export const sendEmail = async (params: SendEmailDto) => {
|
||||||
const { data } = await axios.post(`/email/send`, params);
|
const { data } = await axios.post(`/email/send`, params);
|
||||||
@@ -161,3 +162,11 @@ export const summarizeEmail = async (params: SummarizeEmailRequest) => {
|
|||||||
const { data } = await axios.post(`/ai-assistant/summarize-email`, params);
|
const { data } = await axios.post(`/ai-assistant/summarize-email`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const markAllRead = async () => {
|
||||||
|
const mailboxId = getMailboxId(MailboxEnum.INBOX);
|
||||||
|
const { data } = await axios.patch(
|
||||||
|
`/email/messages/mark-all-read?mailbox=${mailboxId}`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
+34
-4
@@ -2,13 +2,17 @@ import Filters, { FilterValues } from '../../components/Filters';
|
|||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import Table from '../../components/Table';
|
import Table from '../../components/Table';
|
||||||
import { ColumnType } from '../../components/types/TableTypes';
|
import { ColumnType } from '../../components/types/TableTypes';
|
||||||
import { InfoCircle, More, Refresh2, Trash, RecoveryConvert } from 'iconsax-react';
|
import { InfoCircle, Refresh2, Trash, RecoveryConvert } from 'iconsax-react';
|
||||||
import { RowActionItem } from '../../components/RowActionsDropdown';
|
import { RowActionItem } from '../../components/RowActionsDropdown';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useGetSpamMessages } from './hooks/useSpamData';
|
import { useEmptySpam, useGetSpamMessages } from './hooks/useSpamData';
|
||||||
import { SpamMessage } from './types/SpamTypes';
|
import { SpamMessage } from './types/SpamTypes';
|
||||||
import { formatDate } from '@/config/func';
|
import { formatDate } from '@/config/func';
|
||||||
import { useEmailActions } from '@/hooks/useEmailActions';
|
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';
|
||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -16,6 +20,8 @@ const List: FC = () => {
|
|||||||
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const { mutate: emptySpam, isPending } = useEmptySpam();
|
||||||
|
|
||||||
const { data: spamData, isLoading, refetch, isFetching } = useGetSpamMessages({
|
const { data: spamData, isLoading, refetch, isFetching } = useGetSpamMessages({
|
||||||
next: nextCursor,
|
next: nextCursor,
|
||||||
@@ -58,10 +64,15 @@ const List: FC = () => {
|
|||||||
<Refresh2
|
<Refresh2
|
||||||
size={18}
|
size={18}
|
||||||
color='black'
|
color='black'
|
||||||
className={`cursor-pointer ${isFetching ? 'animate-spin-reverse' : ''}`}
|
className={`cursor-pointer min-w-[18px] ${isFetching ? 'animate-spin-reverse' : ''}`}
|
||||||
onClick={() => refetch()}
|
onClick={() => refetch()}
|
||||||
/>
|
/>
|
||||||
<More size={18} color='black' className='rotate-90 cursor-pointer' />
|
<Button
|
||||||
|
label='خالی کردن هرزنامه'
|
||||||
|
className='h-8'
|
||||||
|
onClick={() => setShowModal(true)}
|
||||||
|
loading={isPending}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -94,6 +105,18 @@ const List: FC = () => {
|
|||||||
setSelectedMessages([]);
|
setSelectedMessages([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSpam = () => {
|
||||||
|
emptySpam(undefined, {
|
||||||
|
onSuccess: () => {
|
||||||
|
refetch();
|
||||||
|
setShowModal(false);
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast(error.response?.data?.error.message[0], 'error')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getRowActions = (message: SpamMessage): RowActionItem[] => [
|
const getRowActions = (message: SpamMessage): RowActionItem[] => [
|
||||||
{
|
{
|
||||||
label: 'غیر اسپم',
|
label: 'غیر اسپم',
|
||||||
@@ -160,6 +183,13 @@ const List: FC = () => {
|
|||||||
onPrevious: handlePrevious
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ModalConfrim
|
||||||
|
isOpen={showModal}
|
||||||
|
close={() => setShowModal(false)}
|
||||||
|
onConfrim={handleSpam}
|
||||||
|
isLoading={isPending}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { getSpamMessages } from '../service/SpamService';
|
import { emptySpam, getSpamMessages } from '../service/SpamService';
|
||||||
import { MessageListQueryDto } from '../types/SpamTypes';
|
import { MessageListQueryDto } from '../types/SpamTypes';
|
||||||
|
|
||||||
export const useGetSpamMessages = (query: MessageListQueryDto) => {
|
export const useGetSpamMessages = (query: MessageListQueryDto) => {
|
||||||
@@ -9,3 +9,9 @@ export const useGetSpamMessages = (query: MessageListQueryDto) => {
|
|||||||
staleTime: 0
|
staleTime: 0
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useEmptySpam = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: () => emptySpam(),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import axios from "../../../config/axios";
|
import axios from "../../../config/axios";
|
||||||
import { getMailboxId } from "../../../config/func";
|
import { getMailboxId } from "../../../config/func";
|
||||||
import { MessageListQueryDto, SpamResponse } from "../types/SpamTypes";
|
import { MessageListQueryDto, SpamResponse } from "../types/SpamTypes";
|
||||||
|
import { MailboxEnum } from "@/pages/received/enum/Enum";
|
||||||
|
|
||||||
export const getSpamMessages = async (
|
export const getSpamMessages = async (
|
||||||
query: MessageListQueryDto
|
query: MessageListQueryDto
|
||||||
@@ -23,3 +24,11 @@ export const getSpamMessages = async (
|
|||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const emptySpam = async () => {
|
||||||
|
const mailboxId = getMailboxId(MailboxEnum.Junk);
|
||||||
|
const { data } = await axios.patch(
|
||||||
|
`/email/messages/empty-spam?mailbox=${mailboxId}`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
+40
-40
@@ -2,7 +2,7 @@ import { defineConfig } from "vite";
|
|||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
// import { VitePWA } from "vite-plugin-pwa";
|
import { VitePWA } from "vite-plugin-pwa";
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -10,49 +10,49 @@ export default defineConfig({
|
|||||||
react(),
|
react(),
|
||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
tsconfigPaths(),
|
tsconfigPaths(),
|
||||||
// VitePWA({
|
VitePWA({
|
||||||
// registerType: "autoUpdate",
|
registerType: "autoUpdate",
|
||||||
// devOptions: {
|
devOptions: {
|
||||||
// enabled: false, // در حالت توسعه هم کار کند
|
enabled: false, // در حالت توسعه هم کار کند
|
||||||
// },
|
},
|
||||||
// manifest: {
|
manifest: {
|
||||||
// name: "Danak Mail",
|
name: "Danak Mail",
|
||||||
// short_name: "Danak Mail",
|
short_name: "Danak Mail",
|
||||||
// description: "Danak Mail",
|
description: "Danak Mail",
|
||||||
// theme_color: "#ffffff",
|
theme_color: "#ffffff",
|
||||||
// background_color: "#ffffff",
|
background_color: "#ffffff",
|
||||||
// display: "standalone",
|
display: "standalone",
|
||||||
// start_url: "/received", // صفحه اصلی PWA
|
start_url: "/received", // صفحه اصلی PWA
|
||||||
// icons: [
|
icons: [
|
||||||
|
{
|
||||||
|
src: "/icon-192x192.png",
|
||||||
|
sizes: "192x192",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/icon-512x512.png",
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// workbox: {
|
||||||
|
// maximumFileSizeToCacheInBytes: 4 * 1024 * 1024, // افزایش به 4MB
|
||||||
|
// runtimeCaching: [
|
||||||
// {
|
// {
|
||||||
// src: "/icon-192x192.png",
|
// urlPattern: /^https:\/\/admin-panel\.danakcorp\.com\//,
|
||||||
// sizes: "192x192",
|
// handler: "NetworkFirst",
|
||||||
// type: "image/png",
|
// options: {
|
||||||
|
// cacheName: "api-cache",
|
||||||
|
// expiration: {
|
||||||
|
// maxEntries: 50,
|
||||||
|
// maxAgeSeconds: 60 * 60 * 24,
|
||||||
|
// },
|
||||||
|
// networkTimeoutSeconds: 10,
|
||||||
// },
|
// },
|
||||||
// {
|
|
||||||
// src: "/icon-512x512.png",
|
|
||||||
// sizes: "512x512",
|
|
||||||
// type: "image/png",
|
|
||||||
// },
|
// },
|
||||||
// ],
|
// ],
|
||||||
// },
|
// },
|
||||||
// // workbox: {
|
}),
|
||||||
// // maximumFileSizeToCacheInBytes: 4 * 1024 * 1024, // افزایش به 4MB
|
|
||||||
// // runtimeCaching: [
|
|
||||||
// // {
|
|
||||||
// // urlPattern: /^https:\/\/admin-panel\.danakcorp\.com\//,
|
|
||||||
// // handler: "NetworkFirst",
|
|
||||||
// // options: {
|
|
||||||
// // cacheName: "api-cache",
|
|
||||||
// // expiration: {
|
|
||||||
// // maxEntries: 50,
|
|
||||||
// // maxAgeSeconds: 60 * 60 * 24,
|
|
||||||
// // },
|
|
||||||
// // networkTimeoutSeconds: 10,
|
|
||||||
// // },
|
|
||||||
// // },
|
|
||||||
// // ],
|
|
||||||
// // },
|
|
||||||
// }),
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user