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:
@@ -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
|
||||
@@ -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} <${originalMessage.from.address}>
|
||||
</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 {
|
||||
|
||||
Reference in New Issue
Block a user