cc and bcc
This commit is contained in:
@@ -8,6 +8,8 @@ interface EmailInputProps {
|
|||||||
onRemoveEmail: (email: string) => void
|
onRemoveEmail: (email: string) => void
|
||||||
suggestions: EmailSuggestion[]
|
suggestions: EmailSuggestion[]
|
||||||
onSearchSuggestions?: (query: string) => void
|
onSearchSuggestions?: (query: string) => void
|
||||||
|
showCcBccButton?: boolean
|
||||||
|
onCcBccClick?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const EmailInput: FC<EmailInputProps> = ({
|
const EmailInput: FC<EmailInputProps> = ({
|
||||||
@@ -15,7 +17,9 @@ const EmailInput: FC<EmailInputProps> = ({
|
|||||||
onAddEmail,
|
onAddEmail,
|
||||||
onRemoveEmail,
|
onRemoveEmail,
|
||||||
suggestions,
|
suggestions,
|
||||||
onSearchSuggestions
|
onSearchSuggestions,
|
||||||
|
showCcBccButton = false,
|
||||||
|
onCcBccClick
|
||||||
}) => {
|
}) => {
|
||||||
const [to, setTo] = useState('')
|
const [to, setTo] = useState('')
|
||||||
const [filteredSuggestions, setFilteredSuggestions] = useState<EmailSuggestion[]>([])
|
const [filteredSuggestions, setFilteredSuggestions] = useState<EmailSuggestion[]>([])
|
||||||
@@ -195,6 +199,15 @@ const EmailInput: FC<EmailInputProps> = ({
|
|||||||
placeholder={toEmails.length === 0 ? "ایمیل را وارد کرده و Enter بزنید" : ""}
|
placeholder={toEmails.length === 0 ? "ایمیل را وارد کرده و Enter بزنید" : ""}
|
||||||
className="flex-1 min-w-32 bg-transparent outline-none"
|
className="flex-1 min-w-32 bg-transparent outline-none"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{showCcBccButton && (
|
||||||
|
<button
|
||||||
|
onClick={onCcBccClick}
|
||||||
|
className='text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors pt-[3px] cursor-pointer '
|
||||||
|
>
|
||||||
|
CC/BCC
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showSuggestions && filteredSuggestions.length > 0 && (
|
{showSuggestions && filteredSuggestions.length > 0 && (
|
||||||
|
|||||||
@@ -21,10 +21,13 @@ const NewMessage: FC = () => {
|
|||||||
const [isOpening, setIsOpening] = useState(false)
|
const [isOpening, setIsOpening] = useState(false)
|
||||||
const [isIntelligenseOpen, setIsIntelligenseOpen] = useState(false)
|
const [isIntelligenseOpen, setIsIntelligenseOpen] = useState(false)
|
||||||
const [prompt, setPrompt] = useState('')
|
const [prompt, setPrompt] = useState('')
|
||||||
|
const [showCcBcc, setShowCcBcc] = useState(false)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
// Form state
|
// Form state
|
||||||
toEmails,
|
toEmails,
|
||||||
|
ccEmails,
|
||||||
|
bccEmails,
|
||||||
subject,
|
subject,
|
||||||
content,
|
content,
|
||||||
priority,
|
priority,
|
||||||
@@ -38,6 +41,10 @@ const NewMessage: FC = () => {
|
|||||||
// Form handlers
|
// Form handlers
|
||||||
addEmail,
|
addEmail,
|
||||||
removeEmail,
|
removeEmail,
|
||||||
|
addCcEmail,
|
||||||
|
removeCcEmail,
|
||||||
|
addBccEmail,
|
||||||
|
removeBccEmail,
|
||||||
setSubject,
|
setSubject,
|
||||||
setContent,
|
setContent,
|
||||||
setPriority,
|
setPriority,
|
||||||
@@ -76,6 +83,7 @@ const NewMessage: FC = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setOpenNewMessage(false)
|
setOpenNewMessage(false)
|
||||||
resetForm()
|
resetForm()
|
||||||
|
setShowCcBcc(false)
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,20 +140,60 @@ const NewMessage: FC = () => {
|
|||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className='space-y-6 md:space-y-8'>
|
<div className='space-y-6 md:space-y-8'>
|
||||||
<div>
|
<div>
|
||||||
<label className='text-sm'>
|
<label className='text-sm mb-1 block'>
|
||||||
{t('new_message.to')}
|
{t('new_message.to')}
|
||||||
</label>
|
</label>
|
||||||
<div className='mt-1'>
|
<div>
|
||||||
<EmailInput
|
<EmailInput
|
||||||
toEmails={toEmails}
|
toEmails={toEmails}
|
||||||
onAddEmail={addEmail}
|
onAddEmail={addEmail}
|
||||||
onRemoveEmail={removeEmail}
|
onRemoveEmail={removeEmail}
|
||||||
suggestions={emailSuggestions}
|
suggestions={emailSuggestions}
|
||||||
onSearchSuggestions={searchEmailSuggestions}
|
onSearchSuggestions={searchEmailSuggestions}
|
||||||
|
showCcBccButton={true}
|
||||||
|
onCcBccClick={() => setShowCcBcc(!showCcBcc)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* CC/BCC Accordion */}
|
||||||
|
<div
|
||||||
|
className={clx(
|
||||||
|
'overflow-hidden transition-all duration-300 ease-in-out space-y-4',
|
||||||
|
showCcBcc ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<label className='text-sm'>
|
||||||
|
CC
|
||||||
|
</label>
|
||||||
|
<div className='mt-1'>
|
||||||
|
<EmailInput
|
||||||
|
toEmails={ccEmails}
|
||||||
|
onAddEmail={addCcEmail}
|
||||||
|
onRemoveEmail={removeCcEmail}
|
||||||
|
suggestions={emailSuggestions}
|
||||||
|
onSearchSuggestions={searchEmailSuggestions}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className='text-sm'>
|
||||||
|
BCC
|
||||||
|
</label>
|
||||||
|
<div className='mt-1'>
|
||||||
|
<EmailInput
|
||||||
|
toEmails={bccEmails}
|
||||||
|
onAddEmail={addBccEmail}
|
||||||
|
onRemoveEmail={removeBccEmail}
|
||||||
|
suggestions={emailSuggestions}
|
||||||
|
onSearchSuggestions={searchEmailSuggestions}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-2 items-end'>
|
<div className='flex gap-2 items-end'>
|
||||||
<div className='flex lg:flex-row flex-col flex-1 items-end gap-2'>
|
<div className='flex lg:flex-row flex-col flex-1 items-end gap-2'>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ export const useNewMessage = () => {
|
|||||||
const { email: userEmail } = useAuthStore();
|
const { email: userEmail } = useAuthStore();
|
||||||
|
|
||||||
const [toEmails, setToEmails] = useState<string[]>([]);
|
const [toEmails, setToEmails] = useState<string[]>([]);
|
||||||
|
const [ccEmails, setCcEmails] = useState<string[]>([]);
|
||||||
|
const [bccEmails, setBccEmails] = useState<string[]>([]);
|
||||||
const [subject, setSubject] = useState("");
|
const [subject, setSubject] = useState("");
|
||||||
const [content, setContent] = useState("");
|
const [content, setContent] = useState("");
|
||||||
const [priority, setPriority] = useState("");
|
const [priority, setPriority] = useState("");
|
||||||
@@ -48,6 +50,15 @@ export const useNewMessage = () => {
|
|||||||
const toEmailsList =
|
const toEmailsList =
|
||||||
draftDetail.to?.map((recipient) => recipient.address) || [];
|
draftDetail.to?.map((recipient) => recipient.address) || [];
|
||||||
setToEmails(toEmailsList);
|
setToEmails(toEmailsList);
|
||||||
|
|
||||||
|
const ccEmailsList =
|
||||||
|
draftDetail.cc?.map((recipient) => recipient.address) || [];
|
||||||
|
setCcEmails(ccEmailsList);
|
||||||
|
|
||||||
|
const bccEmailsList =
|
||||||
|
draftDetail.bcc?.map((recipient) => recipient.address) || [];
|
||||||
|
setBccEmails(bccEmailsList);
|
||||||
|
|
||||||
setSubject(draftDetail.subject || "");
|
setSubject(draftDetail.subject || "");
|
||||||
|
|
||||||
const draftWithContent = (draftDetail as unknown) as {
|
const draftWithContent = (draftDetail as unknown) as {
|
||||||
@@ -96,6 +107,40 @@ export const useNewMessage = () => {
|
|||||||
setToEmails(toEmails.filter((email) => email !== emailToRemove));
|
setToEmails(toEmails.filter((email) => email !== emailToRemove));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addCcEmail = (email: string) => {
|
||||||
|
if (!isValidEmail(email)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ccEmails.includes(email)) {
|
||||||
|
toast("این ایمیل قبلاً اضافه شده است", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCcEmails([...ccEmails, email]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeCcEmail = (emailToRemove: string) => {
|
||||||
|
setCcEmails(ccEmails.filter((email) => email !== emailToRemove));
|
||||||
|
};
|
||||||
|
|
||||||
|
const addBccEmail = (email: string) => {
|
||||||
|
if (!isValidEmail(email)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bccEmails.includes(email)) {
|
||||||
|
toast("این ایمیل قبلاً اضافه شده است", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBccEmails([...bccEmails, email]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeBccEmail = (emailToRemove: string) => {
|
||||||
|
setBccEmails(bccEmails.filter((email) => email !== emailToRemove));
|
||||||
|
};
|
||||||
|
|
||||||
const parseEmailAddresses = (emails: string[]) => {
|
const parseEmailAddresses = (emails: string[]) => {
|
||||||
return emails
|
return emails
|
||||||
.filter((email) => email.length > 0)
|
.filter((email) => email.length > 0)
|
||||||
@@ -104,6 +149,8 @@ export const useNewMessage = () => {
|
|||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
setToEmails([]);
|
setToEmails([]);
|
||||||
|
setCcEmails([]);
|
||||||
|
setBccEmails([]);
|
||||||
setSubject("");
|
setSubject("");
|
||||||
setContent("");
|
setContent("");
|
||||||
setPriority("");
|
setPriority("");
|
||||||
@@ -141,6 +188,8 @@ export const useNewMessage = () => {
|
|||||||
const textDirection = detectTextDirection(contentString);
|
const textDirection = detectTextDirection(contentString);
|
||||||
const draftUpdateData = {
|
const draftUpdateData = {
|
||||||
to: parseEmailAddresses(toEmails),
|
to: parseEmailAddresses(toEmails),
|
||||||
|
...(ccEmails.length > 0 && { cc: parseEmailAddresses(ccEmails) }),
|
||||||
|
...(bccEmails.length > 0 && { bcc: parseEmailAddresses(bccEmails) }),
|
||||||
subject,
|
subject,
|
||||||
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
|
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
|
||||||
text: contentString.replace(/<[^>]*>/g, ""),
|
text: contentString.replace(/<[^>]*>/g, ""),
|
||||||
@@ -193,6 +242,8 @@ export const useNewMessage = () => {
|
|||||||
const emailData: SendEmailDto = {
|
const emailData: SendEmailDto = {
|
||||||
from: { address: userEmail || "sender@example.com" },
|
from: { address: userEmail || "sender@example.com" },
|
||||||
to: parseEmailAddresses(toEmails),
|
to: parseEmailAddresses(toEmails),
|
||||||
|
...(ccEmails.length > 0 && { cc: parseEmailAddresses(ccEmails) }),
|
||||||
|
...(bccEmails.length > 0 && { bcc: parseEmailAddresses(bccEmails) }),
|
||||||
subject,
|
subject,
|
||||||
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
|
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
|
||||||
text: contentString.replace(/<[^>]*>/g, ""),
|
text: contentString.replace(/<[^>]*>/g, ""),
|
||||||
@@ -231,6 +282,8 @@ export const useNewMessage = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
toEmails,
|
toEmails,
|
||||||
|
ccEmails,
|
||||||
|
bccEmails,
|
||||||
subject,
|
subject,
|
||||||
content,
|
content,
|
||||||
priority,
|
priority,
|
||||||
@@ -242,6 +295,10 @@ export const useNewMessage = () => {
|
|||||||
|
|
||||||
addEmail,
|
addEmail,
|
||||||
removeEmail,
|
removeEmail,
|
||||||
|
addCcEmail,
|
||||||
|
removeCcEmail,
|
||||||
|
addBccEmail,
|
||||||
|
removeBccEmail,
|
||||||
setSubject,
|
setSubject,
|
||||||
setContent,
|
setContent,
|
||||||
setPriority,
|
setPriority,
|
||||||
|
|||||||
Reference in New Issue
Block a user