attachment + download attach + suggestion

This commit is contained in:
hamid zarghami
2025-07-21 16:31:38 +03:30
parent 60f459d33b
commit b31b64a7f9
14 changed files with 879 additions and 331 deletions
+50 -7
View File
@@ -9,7 +9,7 @@ import AnswerIcon from '@/assets/images/answer.svg'
import Header from './Components/Header'
import ReactQuill from 'react-quill-new';
import Select from '@/components/Select'
import { useGetMessageDetail, useSendEmail } from './hooks/useEmailData'
import { useGetMessageDetail, useSendEmail, useDownloadAttachment } from './hooks/useEmailData'
import { useAuthStore } from '../auth/store/AuthStore'
import { SendEmailDto } from './types/Types'
import { toast } from '@/components/Toast'
@@ -31,6 +31,7 @@ const DetailEmail: FC = () => {
// API hooks
const { data: messageDetail, isLoading, error } = useGetMessageDetail(id || '', mailbox || '')
const sendEmailMutation = useSendEmail()
const downloadAttachmentMutation = useDownloadAttachment()
// const saveDraftMutation = useSaveDraft()
const priorityOptions = [
@@ -110,6 +111,36 @@ const DetailEmail: FC = () => {
toast('قابلیت ارسال به دیگران به زودی اضافه خواهد شد', 'info')
}
const handleDownloadAttachment = async (attachmentId: string, filename: string) => {
if (!id) {
toast('شناسه پیام یافت نشد', 'error')
return
}
try {
const blob = await downloadAttachmentMutation.mutateAsync({
messageId: id,
attachmentId: attachmentId,
mailbox: mailbox || ''
})
// Create download link
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = filename || `attachment-${attachmentId}`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
toast('فایل با موفقیت دانلود شد', 'success')
} catch (error) {
console.error('Download error:', error)
toast('خطا در دانلود فایل', 'error')
}
}
// Mark message as seen when it's loaded and not already seen
useEffect(() => {
if (messageDetail && !messageDetail.seen && id) {
@@ -161,9 +192,14 @@ const DetailEmail: FC = () => {
</div>
</div>
<div className='mt-6 flex gap-4 items-center'>
<img src={AvatarImage} className='size-10' />
<div className='text-sm'>{messageDetail.from.name || messageDetail.from.address}</div>
<div>
<div className='mt-6 flex gap-4 items-center'>
<img src={AvatarImage} className='size-10' />
<div>
<div className='text-sm'>{messageDetail.from.name || messageDetail.from.address}</div>
<div className='text-xs text-description mt-0.5'>{messageDetail.from?.address}</div>
</div>
</div>
</div>
<div className='xl:mt-8 mt-3 text-[13px] leading-7 font-light'>
@@ -191,13 +227,20 @@ const DetailEmail: FC = () => {
messageDetail.attachments.map((attachment, index) => (
<div key={index} className='bg-[#EBEDF5] text-sm flex gap-2 h-10 rounded-full items-center px-4'>
<span>{attachment.filename || `attachment-${index + 1}`}</span>
<DocumentDownload size={20} color='#0038FF' className='cursor-pointer' />
<DocumentDownload
size={20}
color='#0038FF'
className='cursor-pointer hover:opacity-70 transition-opacity'
onClick={() => handleDownloadAttachment(
attachment.id || `ATT${String(index + 1).padStart(5, '0')}`,
attachment.filename || `attachment-${index + 1}`
)}
/>
</div>
))
) : (
<div className='bg-[#EBEDF5] text-sm flex gap-2 h-10 rounded-full items-center px-4'>
<span>Lorem Ipsum.pdf</span>
<DocumentDownload size={20} color='#0038FF' />
<span>فایل ضمیمهای وجود ندارد</span>
</div>
)}
</div>
@@ -111,4 +111,11 @@ export const useRestoreMessage = () => {
return useMutation({
mutationFn: ({ messageId, mailbox }: SingleActionRequest) => api.restoreMessage(messageId, mailbox),
});
};
export const useDownloadAttachment = () => {
return useMutation({
mutationFn: ({ messageId, attachmentId, mailbox }: { messageId: string; attachmentId: string; mailbox: string }) =>
api.downloadAttachment(messageId, attachmentId, mailbox),
});
};
@@ -145,3 +145,17 @@ export const markAsUnread = async (
);
return data;
};
export const downloadAttachment = async (
messageId: string,
attachmentId: string,
mailbox: string
): Promise<Blob> => {
const response = await axios.get(
`/email/messages/${messageId}/attachment?attachmentId=${attachmentId}&mailbox=${mailbox}`,
{
responseType: "blob",
}
);
return response.data;
};
+1
View File
@@ -9,6 +9,7 @@ export interface EmailHeaderDto {
}
export interface EmailAttachmentDto {
id?: string;
filename?: string;
contentType?: string;
encoding?: string;