cc and bcc

This commit is contained in:
hamid zarghami
2025-10-23 11:05:03 +03:30
parent a081c364fe
commit 58f054ccfa
3 changed files with 121 additions and 3 deletions
+14 -1
View File
@@ -8,6 +8,8 @@ interface EmailInputProps {
onRemoveEmail: (email: string) => void
suggestions: EmailSuggestion[]
onSearchSuggestions?: (query: string) => void
showCcBccButton?: boolean
onCcBccClick?: () => void
}
const EmailInput: FC<EmailInputProps> = ({
@@ -15,7 +17,9 @@ const EmailInput: FC<EmailInputProps> = ({
onAddEmail,
onRemoveEmail,
suggestions,
onSearchSuggestions
onSearchSuggestions,
showCcBccButton = false,
onCcBccClick
}) => {
const [to, setTo] = useState('')
const [filteredSuggestions, setFilteredSuggestions] = useState<EmailSuggestion[]>([])
@@ -195,6 +199,15 @@ const EmailInput: FC<EmailInputProps> = ({
placeholder={toEmails.length === 0 ? "ایمیل را وارد کرده و Enter بزنید" : ""}
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>
{showSuggestions && filteredSuggestions.length > 0 && (
+50 -2
View File
@@ -21,10 +21,13 @@ const NewMessage: FC = () => {
const [isOpening, setIsOpening] = useState(false)
const [isIntelligenseOpen, setIsIntelligenseOpen] = useState(false)
const [prompt, setPrompt] = useState('')
const [showCcBcc, setShowCcBcc] = useState(false)
const {
// Form state
toEmails,
ccEmails,
bccEmails,
subject,
content,
priority,
@@ -38,6 +41,10 @@ const NewMessage: FC = () => {
// Form handlers
addEmail,
removeEmail,
addCcEmail,
removeCcEmail,
addBccEmail,
removeBccEmail,
setSubject,
setContent,
setPriority,
@@ -76,6 +83,7 @@ const NewMessage: FC = () => {
setTimeout(() => {
setOpenNewMessage(false)
resetForm()
setShowCcBcc(false)
}, 300)
}
@@ -132,20 +140,60 @@ const NewMessage: FC = () => {
{/* Content */}
<div className='space-y-6 md:space-y-8'>
<div>
<label className='text-sm'>
<label className='text-sm mb-1 block'>
{t('new_message.to')}
</label>
<div className='mt-1'>
<div>
<EmailInput
toEmails={toEmails}
onAddEmail={addEmail}
onRemoveEmail={removeEmail}
suggestions={emailSuggestions}
onSearchSuggestions={searchEmailSuggestions}
showCcBccButton={true}
onCcBccClick={() => setShowCcBcc(!showCcBcc)}
/>
</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 lg:flex-row flex-col flex-1 items-end gap-2'>
<Input
@@ -21,6 +21,8 @@ export const useNewMessage = () => {
const { email: userEmail } = useAuthStore();
const [toEmails, setToEmails] = useState<string[]>([]);
const [ccEmails, setCcEmails] = useState<string[]>([]);
const [bccEmails, setBccEmails] = useState<string[]>([]);
const [subject, setSubject] = useState("");
const [content, setContent] = useState("");
const [priority, setPriority] = useState("");
@@ -48,6 +50,15 @@ export const useNewMessage = () => {
const toEmailsList =
draftDetail.to?.map((recipient) => recipient.address) || [];
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 || "");
const draftWithContent = (draftDetail as unknown) as {
@@ -96,6 +107,40 @@ export const useNewMessage = () => {
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[]) => {
return emails
.filter((email) => email.length > 0)
@@ -104,6 +149,8 @@ export const useNewMessage = () => {
const resetForm = () => {
setToEmails([]);
setCcEmails([]);
setBccEmails([]);
setSubject("");
setContent("");
setPriority("");
@@ -141,6 +188,8 @@ export const useNewMessage = () => {
const textDirection = detectTextDirection(contentString);
const draftUpdateData = {
to: parseEmailAddresses(toEmails),
...(ccEmails.length > 0 && { cc: parseEmailAddresses(ccEmails) }),
...(bccEmails.length > 0 && { bcc: parseEmailAddresses(bccEmails) }),
subject,
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
text: contentString.replace(/<[^>]*>/g, ""),
@@ -193,6 +242,8 @@ export const useNewMessage = () => {
const emailData: SendEmailDto = {
from: { address: userEmail || "sender@example.com" },
to: parseEmailAddresses(toEmails),
...(ccEmails.length > 0 && { cc: parseEmailAddresses(ccEmails) }),
...(bccEmails.length > 0 && { bcc: parseEmailAddresses(bccEmails) }),
subject,
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
text: contentString.replace(/<[^>]*>/g, ""),
@@ -231,6 +282,8 @@ export const useNewMessage = () => {
return {
toEmails,
ccEmails,
bccEmails,
subject,
content,
priority,
@@ -242,6 +295,10 @@ export const useNewMessage = () => {
addEmail,
removeEmail,
addCcEmail,
removeCcEmail,
addBccEmail,
removeBccEmail,
setSubject,
setContent,
setPriority,