320 lines
9.1 KiB
TypeScript
320 lines
9.1 KiB
TypeScript
import { useState, useEffect } from "react";
|
|
import { useSharedStore } from "@/shared/store/sharedStore";
|
|
import { useAuthStore } from "@/pages/auth/store/AuthStore";
|
|
import {
|
|
useGetMessageDetail,
|
|
useSendEmail,
|
|
} from "@/pages/received/hooks/useEmailData";
|
|
import { SendEmailDto, EmailAttachmentDto } from "@/pages/received/types/Types";
|
|
import { useUpdateDraft, useSendDraft } from "@/pages/draft/hooks/useDraftData";
|
|
import { toast } from "@/components/Toast";
|
|
import { useEmailSuggestions } from "./useEmailSuggestions";
|
|
import { detectTextDirection } from "@/helpers/utils";
|
|
|
|
export const useNewMessage = () => {
|
|
const {
|
|
draftData,
|
|
setDraftData,
|
|
editingDraftId,
|
|
setEditingDraftId,
|
|
} = useSharedStore();
|
|
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("");
|
|
const [attachments, setAttachments] = useState<EmailAttachmentDto[]>([]);
|
|
|
|
const [isSending, setIsSending] = useState(false);
|
|
const [isSavingDraft, setIsSavingDraft] = useState(false);
|
|
|
|
const sendEmailMutation = useSendEmail();
|
|
const updateDraftMutation = useUpdateDraft();
|
|
const sendDraftMutation = useSendDraft();
|
|
|
|
const {
|
|
suggestions: emailSuggestions,
|
|
searchSuggestions,
|
|
} = useEmailSuggestions();
|
|
|
|
const { data: draftDetail } = useGetMessageDetail(
|
|
draftData?.id.toString() || "",
|
|
draftData?.mailbox || ""
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (draftDetail) {
|
|
const toEmailsList =
|
|
draftDetail.to?.map(
|
|
(recipient: { address: string; name: string }) => recipient.address
|
|
) || [];
|
|
setToEmails(toEmailsList);
|
|
|
|
const ccEmailsList =
|
|
draftDetail.cc?.map(
|
|
(recipient: { address: string; name: string }) => recipient.address
|
|
) || [];
|
|
setCcEmails(ccEmailsList);
|
|
|
|
const bccEmailsList =
|
|
draftDetail.bcc?.map(
|
|
(recipient: { address: string; name: string }) => recipient.address
|
|
) || [];
|
|
setBccEmails(bccEmailsList);
|
|
|
|
setSubject(draftDetail.subject || "");
|
|
|
|
const draftWithContent = (draftDetail as unknown) as {
|
|
html?: string;
|
|
text?: string;
|
|
intro: string;
|
|
};
|
|
const draftContent = ensureString(
|
|
draftWithContent.html || draftWithContent.text || draftWithContent.intro
|
|
);
|
|
setContent(draftContent);
|
|
|
|
setDraftData(null);
|
|
}
|
|
}, [draftDetail, setDraftData]);
|
|
|
|
const ensureString = (val: unknown): string => {
|
|
if (typeof val === "string") return val;
|
|
if (val === null || val === undefined) return "";
|
|
return String(val);
|
|
};
|
|
|
|
const isValidEmail = (email: string) => {
|
|
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
return emailRegex.test(email);
|
|
};
|
|
|
|
const searchEmailSuggestions = (query: string) => {
|
|
searchSuggestions(query);
|
|
};
|
|
|
|
const addEmail = (email: string) => {
|
|
if (!isValidEmail(email)) {
|
|
return;
|
|
}
|
|
|
|
if (toEmails.includes(email)) {
|
|
toast("این ایمیل قبلاً اضافه شده است", "error");
|
|
return;
|
|
}
|
|
|
|
setToEmails([...toEmails, email]);
|
|
};
|
|
|
|
const removeEmail = (emailToRemove: string) => {
|
|
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)
|
|
.map((email) => ({ address: email }));
|
|
};
|
|
|
|
const resetForm = () => {
|
|
setToEmails([]);
|
|
setCcEmails([]);
|
|
setBccEmails([]);
|
|
setSubject("");
|
|
setContent("");
|
|
setPriority("");
|
|
setAttachments([]);
|
|
};
|
|
|
|
const handleEmailAction = async (isDraft: boolean = false) => {
|
|
const isEditingDraft = !!editingDraftId;
|
|
|
|
if (!isDraft && (toEmails.length === 0 || !subject)) {
|
|
toast("لطفا تمام فیلدهای مورد نیاز را پر کنید", "error");
|
|
return;
|
|
}
|
|
|
|
if (
|
|
isDraft &&
|
|
toEmails.length === 0 &&
|
|
!subject &&
|
|
ensureString(content).trim() === ""
|
|
) {
|
|
toast("حداقل یکی از فیلدها باید پر باشد", "error");
|
|
return;
|
|
}
|
|
|
|
if (isDraft) {
|
|
setIsSavingDraft(true);
|
|
} else {
|
|
setIsSending(true);
|
|
}
|
|
|
|
try {
|
|
let messageId = "";
|
|
if (isEditingDraft) {
|
|
const contentString = ensureString(content);
|
|
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, ""),
|
|
...(attachments.length > 0 && { attachments }),
|
|
};
|
|
|
|
if (isDraft) {
|
|
await updateDraftMutation.mutateAsync(
|
|
{
|
|
messageId: editingDraftId.toString(),
|
|
draftData: draftUpdateData,
|
|
},
|
|
{
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
onSuccess: (data: any) => {
|
|
messageId = data.data?.messageId;
|
|
},
|
|
}
|
|
);
|
|
} else {
|
|
await updateDraftMutation.mutateAsync(
|
|
{
|
|
messageId: editingDraftId.toString(),
|
|
draftData: {
|
|
...draftUpdateData,
|
|
html: `<div dir="${textDirection}" style="text-align: start; unicode-bidi: plaintext; font-family: 'Irancell', 'Vazirmatn', sans-serif;">${contentString}</div>`,
|
|
isDraft: true,
|
|
uploadOnly: true,
|
|
},
|
|
},
|
|
{
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
onSuccess: (data: any) => {
|
|
messageId = data.data?.messageId;
|
|
},
|
|
}
|
|
);
|
|
await sendDraftMutation.mutateAsync(
|
|
messageId || editingDraftId.toString()
|
|
);
|
|
toast("پیام با موفقیت ارسال شد", "success");
|
|
}
|
|
|
|
resetForm();
|
|
setEditingDraftId(null);
|
|
return true;
|
|
} else {
|
|
const contentString = ensureString(content);
|
|
const textDirection = detectTextDirection(contentString);
|
|
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, ""),
|
|
...(attachments.length > 0 && { attachments }),
|
|
...(isDraft && { isDraft: true, uploadOnly: true }),
|
|
};
|
|
|
|
await sendEmailMutation.mutateAsync(emailData, {
|
|
onSuccess: (data) => {
|
|
toast(data?.data.message, "success");
|
|
},
|
|
});
|
|
|
|
resetForm();
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
console.error("Error in email action:", error);
|
|
toast("خطا در انجام عملیات", "error");
|
|
return false;
|
|
} finally {
|
|
setIsSending(false);
|
|
setIsSavingDraft(false);
|
|
}
|
|
};
|
|
|
|
const handleSend = async () => {
|
|
const result = await handleEmailAction(false);
|
|
return result || false;
|
|
};
|
|
|
|
const handleSaveDraft = async () => {
|
|
const result = await handleEmailAction(true);
|
|
return result || false;
|
|
};
|
|
|
|
return {
|
|
toEmails,
|
|
ccEmails,
|
|
bccEmails,
|
|
subject,
|
|
content,
|
|
priority,
|
|
attachments,
|
|
emailSuggestions,
|
|
|
|
isSending,
|
|
isSavingDraft,
|
|
|
|
addEmail,
|
|
removeEmail,
|
|
addCcEmail,
|
|
removeCcEmail,
|
|
addBccEmail,
|
|
removeBccEmail,
|
|
setSubject,
|
|
setContent,
|
|
setPriority,
|
|
setAttachments,
|
|
|
|
searchEmailSuggestions,
|
|
|
|
handleSend,
|
|
handleSaveDraft,
|
|
resetForm,
|
|
};
|
|
};
|