forward and reply

This commit is contained in:
hamid zarghami
2025-07-22 12:37:35 +03:30
parent b31b64a7f9
commit 6bb82bcbac
12 changed files with 681 additions and 196 deletions
+162
View File
@@ -0,0 +1,162 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { ArrowDown2, CloseSquare } from 'iconsax-react'
import AvatarImage from '@/assets/images/avatar.svg'
import AnswerIcon from '@/assets/images/answer.svg'
import EmailEditor from './EmailEditor'
import EmailFormActions from './EmailFormActions'
import { useReply } from './hooks/useReply'
import { MessageDetail } from '@/pages/received/types/Types'
import { toast } from '@/components/Toast'
interface ReplyProps {
originalMessage: MessageDetail
onClose?: () => void
onExpand?: () => void
className?: string
showInitialButton?: boolean
}
const Reply: FC<ReplyProps> = ({
originalMessage,
onClose,
onExpand,
className = '',
showInitialButton = true
}) => {
const { t } = useTranslation()
const {
content,
isExpanded,
isSending,
setContent,
expandReply,
collapseReply,
handleSendReply,
handleSaveDraft
} = useReply({
originalMessage,
onSuccess: () => {
onClose?.()
}
})
const handleExpand = () => {
expandReply()
onExpand?.()
}
const handleClose = async () => {
// اگر محتوایی وارد شده، پیش‌نویس ذخیره کن
if (content.trim()) {
await handleSaveDraft()
toast('پیش‌نویس ذخیره شد', 'success')
}
// بسته کردن و برگشت به حالت قبل
collapseReply()
onClose?.() // این خط مهمه تا parent component بفهمه
}
// اگر showInitialButton true باشه و هنوز expand نشده، فقط دکمه نشون بده
if (showInitialButton && !isExpanded) {
return (
<div className={`flex justify-end ${className}`}>
<div className='flex gap-5 text-sm'>
<div
onClick={handleExpand}
className='flex gap-2 cursor-pointer items-center hover:text-primary transition-colors'
>
<img src={AnswerIcon} className='w-[17px]' />
<div>{t('mail.answer')}</div>
</div>
</div>
</div>
)
}
const handleSend = () => {
handleSendReply(originalMessage?.html[0])
collapseReply()
}
// در غیر این صورت editor رو نشون بده
// (یا showInitialButton false هست یا isExpanded true هست)
return (
<div className={`mt-6 w-full ${className}`}>
{/* Reply Header */}
<div className='flex items-center justify-between mb-4 p-3 bg-gray-50 rounded-lg border'>
<div className='flex items-center gap-2 text-sm text-gray-600'>
<img src={AnswerIcon} className='w-4 h-4' />
<span>پاسخ به {originalMessage.from.name || originalMessage.from.address}</span>
</div>
<div className='flex items-center gap-2'>
<button
onClick={collapseReply}
className='p-1 hover:bg-gray-200 rounded transition-colors'
title='بستن'
>
<ArrowDown2 size={16} />
</button>
<button
onClick={() => {
collapseReply()
onClose?.()
}}
className='p-1 hover:bg-gray-200 rounded transition-colors'
title='لغو'
>
<CloseSquare size={16} />
</button>
</div>
</div>
{/* Reply Content */}
<div className='flex gap-4'>
<img src={AvatarImage} className='size-10 flex-shrink-0' />
<div className='w-full'>
{/* To Field */}
<div className='mb-4 text-sm'>
<div className='flex items-center gap-2 p-2 bg-gray-50 rounded border'>
<span className='text-gray-600 min-w-fit'>به:</span>
<span className='text-gray-800'>{originalMessage.from.address}</span>
</div>
</div>
{/* Subject Field */}
<div className='mb-4 text-sm'>
<div className='flex items-center gap-2 p-2 bg-gray-50 rounded border'>
<span className='text-gray-600 min-w-fit'>موضوع:</span>
<span className='text-gray-800'>
{originalMessage.subject.startsWith('Re:')
? originalMessage.subject
: `Re: ${originalMessage.subject}`}
</span>
</div>
</div>
{/* Editor */}
<div className='mb-4'>
<EmailEditor
value={content}
onChange={setContent}
placeholder='پیام خود را بنویسید...'
/>
</div>
{/* Actions */}
<EmailFormActions
onSend={handleSend}
onClose={handleClose}
isSending={isSending}
/>
</div>
</div>
</div>
)
}
export default Reply