send , receive , detail email
This commit is contained in:
@@ -2,21 +2,37 @@ import { FC, useState, useEffect } from 'react'
|
||||
import { CloseCircle } from 'iconsax-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSharedStore } from '@/shared/store/sharedStore'
|
||||
import { useAuthStore } from '../../pages/auth/store/AuthStore'
|
||||
import { useSendEmail, useSaveDraft } from '../../pages/received/hooks/useEmailData'
|
||||
import { SendEmailDto } from '../../pages/received/types/Types'
|
||||
import Input from '../Input'
|
||||
import ReactQuill from 'react-quill-new';
|
||||
import Button from '../Button'
|
||||
import Select from '../Select'
|
||||
import UploadButton from '../UploadButton'
|
||||
import { toast } from '../Toast'
|
||||
|
||||
|
||||
const NewMessage: FC = () => {
|
||||
const { t } = useTranslation('global')
|
||||
const [value, setValue] = useState('');
|
||||
const { setOpenNewMessage, openNewMessage } = useSharedStore()
|
||||
const { email: userEmail } = useAuthStore()
|
||||
const [isClosing, setIsClosing] = useState(false)
|
||||
const [shouldRender, setShouldRender] = useState(false)
|
||||
const [isOpening, setIsOpening] = useState(false)
|
||||
|
||||
// Form state
|
||||
const [to, setTo] = useState('')
|
||||
const [toEmails, setToEmails] = useState<string[]>([])
|
||||
const [subject, setSubject] = useState('')
|
||||
const [priority, setPriority] = useState('')
|
||||
|
||||
|
||||
// API hooks
|
||||
const sendEmailMutation = useSendEmail()
|
||||
const saveDraftMutation = useSaveDraft()
|
||||
|
||||
useEffect(() => {
|
||||
if (openNewMessage) {
|
||||
setShouldRender(true)
|
||||
@@ -42,6 +58,108 @@ const NewMessage: FC = () => {
|
||||
setOpenNewMessage(false)
|
||||
}, 300)
|
||||
}
|
||||
|
||||
const parseEmailAddresses = (emails: string[]) => {
|
||||
return emails
|
||||
.filter(email => email.length > 0)
|
||||
.map(email => ({ address: email }))
|
||||
}
|
||||
|
||||
const isValidEmail = (email: string) => {
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
||||
return emailRegex.test(email)
|
||||
}
|
||||
|
||||
const handleToKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter' && to.trim()) {
|
||||
e.preventDefault()
|
||||
const email = to.trim()
|
||||
|
||||
if (!isValidEmail(email)) {
|
||||
toast('لطفا یک ایمیل معتبر وارد کنید', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
if (toEmails.includes(email)) {
|
||||
toast('این ایمیل قبلاً اضافه شده است', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
setToEmails([...toEmails, email])
|
||||
setTo('')
|
||||
}
|
||||
}
|
||||
|
||||
const removeEmail = (emailToRemove: string) => {
|
||||
setToEmails(toEmails.filter(email => email !== emailToRemove))
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleSend = async () => {
|
||||
if (toEmails.length === 0 || !subject) {
|
||||
toast('لطفا تمام فیلدهای مورد نیاز را پر کنید', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
const emailData: SendEmailDto = {
|
||||
from: { address: userEmail || 'sender@example.com' },
|
||||
to: parseEmailAddresses(toEmails),
|
||||
subject,
|
||||
html: value,
|
||||
text: value.replace(/<[^>]*>/g, ''), // Strip HTML for text version
|
||||
}
|
||||
|
||||
try {
|
||||
await sendEmailMutation.mutateAsync(emailData)
|
||||
toast('ایمیل با موفقیت ارسال شد', 'success')
|
||||
handleClose()
|
||||
// Reset form
|
||||
setTo('')
|
||||
setToEmails([])
|
||||
setSubject('')
|
||||
setValue('')
|
||||
setPriority('')
|
||||
} catch {
|
||||
toast('خطا در ارسال ایمیل', 'error')
|
||||
}
|
||||
}
|
||||
|
||||
const handleSaveDraft = async () => {
|
||||
if (toEmails.length === 0 && !subject && !value) {
|
||||
toast('حداقل یکی از فیلدها باید پر باشد', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
const emailData: SendEmailDto = {
|
||||
from: { address: userEmail || 'sender@example.com' },
|
||||
to: parseEmailAddresses(toEmails),
|
||||
subject,
|
||||
html: value,
|
||||
text: value.replace(/<[^>]*>/g, ''),
|
||||
isDraft: true,
|
||||
}
|
||||
|
||||
try {
|
||||
await saveDraftMutation.mutateAsync(emailData)
|
||||
toast('پیشنویس ذخیره شد', 'success')
|
||||
handleClose()
|
||||
// Reset form
|
||||
setTo('')
|
||||
setToEmails([])
|
||||
setSubject('')
|
||||
setValue('')
|
||||
setPriority('')
|
||||
} catch {
|
||||
toast('خطا در ذخیره پیشنویس', 'error')
|
||||
}
|
||||
}
|
||||
|
||||
const priorityOptions = [
|
||||
{ value: 'high', label: 'بالا' },
|
||||
{ value: 'medium', label: 'متوسط' },
|
||||
{ value: 'low', label: 'پایین' },
|
||||
]
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -66,12 +184,44 @@ const NewMessage: FC = () => {
|
||||
|
||||
{/* Content */}
|
||||
<div className='space-y-6 md:space-y-8'>
|
||||
<Input
|
||||
label={t('new_message.to')}
|
||||
/>
|
||||
<div>
|
||||
<label className='text-sm'>
|
||||
{t('new_message.to')}
|
||||
</label>
|
||||
<div className='w-full relative mt-1'>
|
||||
<div className="w-full bg-white min-h-10 text-black flex flex-wrap items-center gap-1 px-4 py-2 text-xs rounded-xl border border-border">
|
||||
{/* Email Tags */}
|
||||
{toEmails.map((email, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center gap-1 bg-[#EBEDF5] text-xs h-7 rounded-full px-3"
|
||||
>
|
||||
<span>{email}</span>
|
||||
<CloseCircle
|
||||
size={16}
|
||||
color='#D52903'
|
||||
className='cursor-pointer'
|
||||
onClick={() => removeEmail(email)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Input Field */}
|
||||
<input
|
||||
value={to}
|
||||
onChange={(e) => setTo(e.target.value)}
|
||||
onKeyDown={handleToKeyDown}
|
||||
placeholder={toEmails.length === 0 ? "ایمیل را وارد کرده و Enter بزنید" : ""}
|
||||
className="flex-1 min-w-32 bg-transparent outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
label={t('new_message.subject')}
|
||||
value={subject}
|
||||
onChange={(e) => setSubject(e.target.value)}
|
||||
/>
|
||||
|
||||
<div>
|
||||
@@ -101,19 +251,25 @@ const NewMessage: FC = () => {
|
||||
<div className='flex flex-col gap-4 sm:flex-row pt-4'>
|
||||
<div>
|
||||
<Select
|
||||
items={[]}
|
||||
items={priorityOptions}
|
||||
placeholder={t('new_message.select_priority')}
|
||||
className='xl:w-[190px] min-w-[130px]'
|
||||
value={priority}
|
||||
onChange={(e) => setPriority(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex-1 justify-end flex gap-3'>
|
||||
<Button
|
||||
className='!w-full sm:!w-fit px-6 md:px-10 bg-white text-black border border-primary order-2 sm:order-1'
|
||||
label={t('new_message.draft')}
|
||||
onClick={handleSaveDraft}
|
||||
loading={saveDraftMutation.isPending}
|
||||
/>
|
||||
<Button
|
||||
className='w-full sm:w-fit px-6 md:px-10 order-1 sm:order-2'
|
||||
label={t('new_message.send')}
|
||||
onClick={handleSend}
|
||||
loading={sendEmailMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -121,6 +277,8 @@ const NewMessage: FC = () => {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user