feat: Add emoji reaction feature and improve reply formatting

- Add emoji-picker-react package
- Create EmojiReaction component for quick emoji responses
- Replace EmojiHappy icon with interactive EmojiReaction component
- Implement emoji selection as structured reply messages
- Improve reply HTML formatting with better styling and Persian date
- Add contextual information to both emoji reactions and text replies
- Update success messages to be more concise
This commit is contained in:
hamid zarghami
2025-07-22 13:15:42 +03:30
parent f844ff53d4
commit 013d4238c9
5 changed files with 176 additions and 10 deletions
+61
View File
@@ -0,0 +1,61 @@
import { FC, useState } from 'react'
import EmojiPicker, { EmojiClickData } from 'emoji-picker-react'
import { EmojiHappy } from 'iconsax-react'
import { useOutsideClick } from '@/hooks/useOutSideClick'
interface EmojiReactionProps {
onEmojiSelect: (emoji: string) => void
className?: string
}
const EmojiReaction: FC<EmojiReactionProps> = ({ onEmojiSelect, className = '' }) => {
const [isOpen, setIsOpen] = useState(false)
// استفاده از hook موجود برای تشخیص کلیک خارج از المان
const containerRef = useOutsideClick(() => {
if (isOpen) {
setIsOpen(false)
}
})
const handleEmojiClick = (emojiData: EmojiClickData) => {
onEmojiSelect(emojiData.emoji)
setIsOpen(false)
}
const togglePicker = () => {
setIsOpen(!isOpen)
}
return (
<div ref={containerRef} className={`relative ${className}`}>
<EmojiHappy
size={24}
color='black'
className='cursor-pointer hover:opacity-70 transition-opacity'
onClick={togglePicker}
/>
{isOpen && (
<div className='absolute bottom-10 right-0 z-50'>
<div className='bg-white rounded-lg shadow-lg border border-gray-200'>
<EmojiPicker
onEmojiClick={handleEmojiClick}
width={300}
height={400}
searchDisabled
skinTonesDisabled
previewConfig={{
defaultCaption: 'یک ایموجی انتخاب کنید',
defaultEmoji: '1f60a'
}}
/>
</div>
</div>
)}
</div>
)
}
export default EmojiReaction
+32 -7
View File
@@ -50,12 +50,25 @@ export const useReply = ({
minute: "2-digit",
}).format(originalDate);
const htmlContent =
content +
"<br /><br />" +
`<div dir="rtl">در تاریخ ${persianDate} ${originalMessage.from.name} <${originalMessage.from.address}> نوشت:</div>` +
"<br /><br />" +
`<div dir="rtl">${html}</div>`;
const htmlContent = `
<div dir="rtl" style="font-family: 'Irancell', Arial, sans-serif; line-height: 1.6;">
<div style="margin-bottom: 10px; padding: 15px;">
${content}
</div>
<div style="border-top: 2px solid #e9ecef; padding-top: 10px;">
<div style=" font-size: 12px; margin-bottom: 10px; padding: 8px; border-radius: 4px;">
در پاسخ به پیام ارسالی در تاریخ ${persianDate}
<br />
از: ${originalMessage.from.name} &lt;${originalMessage.from.address}&gt;
</div>
<div >
${html}
</div>
</div>
</div>
`;
const replyData: SendEmailDto = {
from: { address: userEmail || "sender@example.com" },
@@ -73,7 +86,19 @@ export const useReply = ({
? originalMessage.subject
: `Re: ${originalMessage.subject}`,
html: htmlContent,
text: content.replace(/<[^>]*>/g, ""),
text: `${content.replace(/<[^>]*>/g, "")}
═══════════════════════════════════════════════════════
📩 در پاسخ به پیام ارسالی در تاریخ ${persianDate}
📧 از: ${originalMessage.from.name} <${originalMessage.from.address}>
متن پیام اصلی:
${
originalMessage.text ||
originalMessage.html?.join("").replace(/<[^>]*>/g, "") ||
""
}`,
};
try {