Files
dmail-front/src/components/newMessage/hooks/useNewMessage.ts
T
hamid zarghami c76d9c788b fix build
2025-10-23 11:13:53 +03:30

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,
};
};