write message with ai + summerize
This commit is contained in:
@@ -7,7 +7,7 @@ VITE_SOCKET_URL = 'wss://dmail-api.danakcorp.com/email'
|
|||||||
# VITE_SOCKET_URL = 'ws://192.168.1.118:4000/email'
|
# VITE_SOCKET_URL = 'ws://192.168.1.118:4000/email'
|
||||||
|
|
||||||
VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
|
VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
|
||||||
# VITE_BASE_URL = 'http://192.168.1.118:4000'
|
# VITE_BASE_URL = 'http://192.168.1.101:4000'
|
||||||
|
|
||||||
|
|
||||||
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
|
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<script>var s = document.createElement("script"); s.src = "https://van.najva.com/static/js/main-script.js"; s.defer = !0; s.id = "najva-mini-script"; s.setAttribute("data-najva-id", "7b4774d2-ef79-4341-8632-96556f8b0db5"); document.head.appendChild(s);</script>
|
<script>var s = document.createElement("script"); s.src = "https://van.najva.com/static/js/main-script.js"; s.defer = !0; s.id = "najva-mini-script"; s.setAttribute("data-najva-id", "9c582bcc-1a29-490c-b0e8-70ab404ad258"); document.head.appendChild(s);</script>
|
||||||
|
|
||||||
<title>DMail | داناک</title>
|
<title>DMail | داناک</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import EmailAttachments from './EmailAttachments'
|
|||||||
import EmailFormActions from './EmailFormActions'
|
import EmailFormActions from './EmailFormActions'
|
||||||
import { useNewMessage } from './hooks/useNewMessage'
|
import { useNewMessage } from './hooks/useNewMessage'
|
||||||
import Intelligense from '@/assets/images/intelligense.svg'
|
import Intelligense from '@/assets/images/intelligense.svg'
|
||||||
|
import { useGenerateEmail } from '@/pages/received/hooks/useEmailData'
|
||||||
|
import { clx } from '@/helpers/utils'
|
||||||
|
|
||||||
const NewMessage: FC = () => {
|
const NewMessage: FC = () => {
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
@@ -16,6 +18,8 @@ const NewMessage: FC = () => {
|
|||||||
const [isClosing, setIsClosing] = useState(false)
|
const [isClosing, setIsClosing] = useState(false)
|
||||||
const [shouldRender, setShouldRender] = useState(false)
|
const [shouldRender, setShouldRender] = useState(false)
|
||||||
const [isOpening, setIsOpening] = useState(false)
|
const [isOpening, setIsOpening] = useState(false)
|
||||||
|
const [isIntelligenseOpen, setIsIntelligenseOpen] = useState(false)
|
||||||
|
const [prompt, setPrompt] = useState('')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
// Form state
|
// Form state
|
||||||
@@ -46,6 +50,7 @@ const NewMessage: FC = () => {
|
|||||||
handleSaveDraft,
|
handleSaveDraft,
|
||||||
resetForm
|
resetForm
|
||||||
} = useNewMessage()
|
} = useNewMessage()
|
||||||
|
const { mutate: generateEmail, isPending: isGeneratingEmail } = useGenerateEmail()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (openNewMessage) {
|
if (openNewMessage) {
|
||||||
@@ -87,6 +92,21 @@ const NewMessage: FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlePrompt = () => {
|
||||||
|
if (isIntelligenseOpen && prompt.length > 0) {
|
||||||
|
generateEmail({ prompt }, {
|
||||||
|
onSuccess: (data) => {
|
||||||
|
setContent(data?.data?.assistance?.suggestion?.content)
|
||||||
|
if (subject === '') {
|
||||||
|
setSubject(data?.data?.assistance?.suggestion?.subject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
setIsIntelligenseOpen(!isIntelligenseOpen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{shouldRender && (
|
{shouldRender && (
|
||||||
@@ -126,17 +146,36 @@ const NewMessage: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-2 items-end'>
|
<div className='flex gap-2 items-end'>
|
||||||
<Input
|
<div className='flex flex-1 items-end gap-2'>
|
||||||
label={t('new_message.subject')}
|
<Input
|
||||||
value={subject}
|
label={t('new_message.subject')}
|
||||||
onChange={(e) => setSubject(e.target.value)}
|
value={subject}
|
||||||
/>
|
onChange={(e) => setSubject(e.target.value)}
|
||||||
|
className='w-full'
|
||||||
|
/>
|
||||||
|
|
||||||
<div className='border border-border rounded-xl h-10 px-2 flex items-center justify-center'>
|
{
|
||||||
<img src={Intelligense} alt='intelligense' className='w-6' />
|
isIntelligenseOpen && (
|
||||||
|
<Input
|
||||||
|
placeholder={t('new_message.prompt')}
|
||||||
|
value={prompt}
|
||||||
|
onChange={(e) => setPrompt(e.target.value)}
|
||||||
|
className='w-full'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div onClick={isGeneratingEmail ? undefined : handlePrompt} className='border border-border rounded-xl h-10 px-2 flex items-center justify-center'>
|
||||||
|
<img src={Intelligense} alt='intelligense' className={clx(
|
||||||
|
'w-6',
|
||||||
|
isGeneratingEmail && 'animate-spin spin-in'
|
||||||
|
)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<EmailEditor
|
<EmailEditor
|
||||||
value={content}
|
value={content}
|
||||||
|
|||||||
+2
-1
@@ -159,7 +159,8 @@
|
|||||||
"recipients_placeholder": "نام گیرنده",
|
"recipients_placeholder": "نام گیرنده",
|
||||||
"subject_placeholder": "موضوع پیام",
|
"subject_placeholder": "موضوع پیام",
|
||||||
"message_placeholder": "متن پیام",
|
"message_placeholder": "متن پیام",
|
||||||
"select_priority": "انتخاب اولویت"
|
"select_priority": "انتخاب اولویت",
|
||||||
|
"prompt": "پرامپت"
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"download": "دانلود",
|
"download": "دانلود",
|
||||||
|
|||||||
@@ -4,25 +4,26 @@ import DefaulModal from '@/components/DefaulModal';
|
|||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import { InboxMessage } from '@/pages/draft/types/DraftTypes';
|
import { InboxMessage } from '@/pages/draft/types/DraftTypes';
|
||||||
import Intelligense from '@/assets/images/intelligense.svg'
|
import Intelligense from '@/assets/images/intelligense.svg'
|
||||||
|
import Skeleton from 'react-loading-skeleton'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
const Summerize: FC<{ id: string, mailbox: string, item: InboxMessage }> = ({ id, mailbox, item }) => {
|
const Summerize: FC<{ id: string, mailbox: string, item: InboxMessage }> = ({ id, mailbox, item }) => {
|
||||||
|
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { mutate: summarizeEmail } = useSummarizeEmail();
|
const { mutate: summarizeEmail, isPending } = useSummarizeEmail();
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const [data, setData] = useState<any>()
|
const [data, setData] = useState<any>()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const handleSummarizeEmail = () => {
|
const handleSummarizeEmail = () => {
|
||||||
|
setOpen(true)
|
||||||
summarizeEmail({ messageId: Number(id), mailbox }, {
|
summarizeEmail({ messageId: Number(id), mailbox }, {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
setData(data)
|
setData(data)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setOpen(true)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('data', data);
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -38,21 +39,43 @@ const Summerize: FC<{ id: string, mailbox: string, item: InboxMessage }> = ({ id
|
|||||||
title_header='پیش نمایش ایمیل'
|
title_header='پیش نمایش ایمیل'
|
||||||
>
|
>
|
||||||
<div className='mt-5'>
|
<div className='mt-5'>
|
||||||
<div className='text-xs'>
|
{isPending ? (
|
||||||
موضوع:
|
<div>
|
||||||
</div>
|
<div className='text-xs'>
|
||||||
<div className='mt-1.5 text-xs'>
|
موضوع:
|
||||||
{item.subject}
|
</div>
|
||||||
</div>
|
<div className='mt-1.5'>
|
||||||
|
<Skeleton height={16} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='mt-7'>
|
<div className='mt-7'>
|
||||||
<div className='text-xs'>
|
<div className='text-xs'>
|
||||||
خلاصه متن:
|
خلاصه متن:
|
||||||
|
</div>
|
||||||
|
<div className='mt-3'>
|
||||||
|
<Skeleton height={16} count={4} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-3 leading-5 text-xs text-description'>
|
) : (
|
||||||
{data?.data?.summary}
|
<div>
|
||||||
|
<div className='text-xs'>
|
||||||
|
موضوع:
|
||||||
|
</div>
|
||||||
|
<div className='mt-1.5 text-xs'>
|
||||||
|
{item.subject}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-7'>
|
||||||
|
<div className='text-xs'>
|
||||||
|
خلاصه متن:
|
||||||
|
</div>
|
||||||
|
<div className='mt-3 leading-5 text-xs text-description'>
|
||||||
|
{data?.data?.summary}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<div className='mt-14 flex justify-end'>
|
<div className='mt-14 flex justify-end'>
|
||||||
<div className='flex gap-3'>
|
<div className='flex gap-3'>
|
||||||
@@ -65,9 +88,7 @@ const Summerize: FC<{ id: string, mailbox: string, item: InboxMessage }> = ({ id
|
|||||||
<Button
|
<Button
|
||||||
label='مشاهده'
|
label='مشاهده'
|
||||||
className='w-fit !px-10'
|
className='w-fit !px-10'
|
||||||
onClick={() => {
|
onClick={() => navigate(`/mail/${id}/${mailbox}`)}
|
||||||
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import * as api from '../service/EmailService';
|
import * as api from '../service/EmailService';
|
||||||
import { SendEmailDto, MessageListQueryDto, SingleActionRequest, SummarizeEmailRequest } from '../types/Types';
|
import { SendEmailDto, MessageListQueryDto, SingleActionRequest, SummarizeEmailRequest, GenerateEmailRequest } from '../types/Types';
|
||||||
|
|
||||||
export const useSendEmail = () => {
|
export const useSendEmail = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -124,4 +124,10 @@ export const useSummarizeEmail = () => {
|
|||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (params: SummarizeEmailRequest) => api.summarizeEmail(params),
|
mutationFn: (params: SummarizeEmailRequest) => api.summarizeEmail(params),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGenerateEmail = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (params: GenerateEmailRequest) => api.generateEmail(params),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
MessageDetailResponse,
|
MessageDetailResponse,
|
||||||
MessageDetail,
|
MessageDetail,
|
||||||
SummarizeEmailRequest,
|
SummarizeEmailRequest,
|
||||||
|
GenerateEmailRequest,
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
export const sendEmail = async (params: SendEmailDto) => {
|
export const sendEmail = async (params: SendEmailDto) => {
|
||||||
@@ -14,6 +15,11 @@ export const sendEmail = async (params: SendEmailDto) => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const generateEmail = async (params: GenerateEmailRequest) => {
|
||||||
|
const { data } = await axios.post(`/ai-assistant/write-email`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const saveDraft = async (params: SendEmailDto) => {
|
export const saveDraft = async (params: SendEmailDto) => {
|
||||||
const { data } = await axios.post(`/email/messages/drafts`, params);
|
const { data } = await axios.post(`/email/messages/drafts`, params);
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
@@ -321,3 +321,7 @@ export interface SummarizeEmailRequest {
|
|||||||
length?: "medium" | "short" | "long";
|
length?: "medium" | "short" | "long";
|
||||||
tone?: "professional" | "casual" | "formal";
|
tone?: "professional" | "casual" | "formal";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GenerateEmailRequest {
|
||||||
|
prompt: string;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user