Files
dmail-front/src/components/newMessage/NewMessage.tsx
T
hamid zarghami 0be4a02dea fix space inputs
2025-10-25 16:00:13 +03:30

258 lines
11 KiB
TypeScript

import { FC, useState, useEffect } from 'react'
import { CloseCircle } from 'iconsax-react'
import { useTranslation } from 'react-i18next'
import { useSharedStore } from '@/shared/store/sharedStore'
import Input from '@/components/Input'
import EmailInput from './EmailInput'
import EmailEditor from './EmailEditor'
import EmailAttachments from './EmailAttachments'
import EmailFormActions from './EmailFormActions'
import { useNewMessage } from './hooks/useNewMessage'
import Intelligense from '@/assets/images/intelligense.svg'
import { useGenerateEmail } from '@/pages/received/hooks/useEmailData'
import { clx } from '@/helpers/utils'
import { getIconColor } from '@/utils/colorUtils'
const NewMessage: FC = () => {
const { t } = useTranslation('global')
const { openNewMessage, setOpenNewMessage } = useSharedStore()
const [isClosing, setIsClosing] = useState(false)
const [shouldRender, setShouldRender] = useState(false)
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,
attachments,
emailSuggestions,
// Loading states
isSending,
isSavingDraft,
// Form handlers
addEmail,
removeEmail,
addCcEmail,
removeCcEmail,
addBccEmail,
removeBccEmail,
setSubject,
setContent,
setPriority,
setAttachments,
// Search functions
searchEmailSuggestions,
// Actions
handleSend,
handleSaveDraft,
resetForm
} = useNewMessage()
const { mutate: generateEmail, isPending: isGeneratingEmail } = useGenerateEmail()
useEffect(() => {
if (openNewMessage) {
setShouldRender(true)
setIsClosing(false)
setIsOpening(true)
setTimeout(() => {
setIsOpening(false)
}, 50)
} else if (shouldRender) {
setIsClosing(true)
const timer = setTimeout(() => {
setShouldRender(false)
setIsClosing(false)
}, 300)
return () => clearTimeout(timer)
}
}, [openNewMessage, shouldRender])
const handleClose = () => {
setIsClosing(true)
setTimeout(() => {
setOpenNewMessage(false)
resetForm()
setShowCcBcc(false)
}, 300)
}
const handleSendWithClose = async () => {
const success = await handleSend()
if (success) {
handleClose()
}
}
const handleSaveDraftWithClose = async () => {
const success = await handleSaveDraft()
if (success) {
handleClose()
}
}
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 (
<>
{shouldRender && (
<>
<div
className={`fixed inset-0 xl:bg-transparent bg-black/50 z-[9998] transition-opacity duration-300 ${isClosing ? 'opacity-0' : isOpening ? 'opacity-0' : 'opacity-100'
}`}
onClick={handleClose}
/>
<div className={`fixed bottom-2 inset-x-2 md:bottom-4 md:inset-x-4 xl:left-4 xl:right-auto xl:bottom-4 bg-white dark:bg-[#252526] rounded-2xl md:rounded-3xl shadow-[0_0_20px_rgba(0,0,0,0.1)] z-[9999] p-4 md:p-6 xl:p-8 xl:w-[800px] max-h-[90vh] overflow-y-auto transition-transform duration-300 ease-out ${isClosing ? 'translate-y-[120%]' : isOpening ? 'translate-y-full' : 'translate-y-0'
}`}>
{/* Header */}
<div className='flex justify-between items-center mb-6 md:mb-8'>
<div className='text-lg'>
{t('new_message.title')}
</div>
<div onClick={handleClose} className='cursor-pointer p-1'>
<CloseCircle size={20} className='md:w-6 md:h-6' color={getIconColor('primary')} />
</div>
</div>
{/* Content */}
<div>
<div>
<label className='text-sm mb-1 block'>
{t('new_message.to')}
</label>
<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',
showCcBcc ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
)}
>
<div className='mt-4'>
<label className='text-sm mb-1 block'>
CC
</label>
<div>
<EmailInput
toEmails={ccEmails}
onAddEmail={addCcEmail}
onRemoveEmail={removeCcEmail}
suggestions={emailSuggestions}
onSearchSuggestions={searchEmailSuggestions}
/>
</div>
</div>
<div className='mt-4'>
<label className='text-sm mb-1 block'>
BCC
</label>
<div>
<EmailInput
toEmails={bccEmails}
onAddEmail={addBccEmail}
onRemoveEmail={removeBccEmail}
suggestions={emailSuggestions}
onSearchSuggestions={searchEmailSuggestions}
/>
</div>
</div>
</div>
<div className='flex gap-2 items-end mt-4'>
<div className='flex lg:flex-row flex-col flex-1 items-end gap-2'>
<Input
label={t('new_message.subject')}
value={subject}
onChange={(e) => setSubject(e.target.value)}
className='w-full'
/>
{
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 className='mt-4'>
<EmailEditor
value={content}
onChange={setContent}
/>
</div>
<div className='mt-4'>
<EmailAttachments
attachments={attachments}
onAttachmentsChange={setAttachments}
/>
</div>
<div className='mt-4'>
<EmailFormActions
priority={priority}
onPriorityChange={setPriority}
onSend={handleSendWithClose}
onSaveDraft={handleSaveDraftWithClose}
isSending={isSending}
isSavingDraft={isSavingDraft}
/>
</div>
</div>
</div>
</>
)}
</>
)
}
export default NewMessage