diff --git a/src/modules/chat/components/ChatConversationList.jsx b/src/modules/chat/components/ChatConversationList.jsx index f7d69e9..f87095f 100644 --- a/src/modules/chat/components/ChatConversationList.jsx +++ b/src/modules/chat/components/ChatConversationList.jsx @@ -110,7 +110,7 @@ function UnreadBadge({ count }) { ); } -function SavedContactLabel({ contact }) { +function SavedContactIcon({ contact }) { const profile = contact.contactProfile; const hasSavedContact = Boolean(profile?.created_at || profile?.name || profile?.company || profile?.note); if (!hasSavedContact) return null; @@ -118,12 +118,23 @@ function SavedContactLabel({ contact }) { return ( •Salvo• @@ -213,9 +224,9 @@ export function ChatConversationList({
+ -
diff --git a/src/modules/chat/components/ChatWindow.jsx b/src/modules/chat/components/ChatWindow.jsx index b5dd7c0..ffbd453 100644 --- a/src/modules/chat/components/ChatWindow.jsx +++ b/src/modules/chat/components/ChatWindow.jsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useRef } from 'react'; +import { Fragment, useEffect, useMemo, useRef } from 'react'; function getMediaUrl(media) { if (!media?.data || !media?.mimetype) return ''; @@ -29,6 +29,68 @@ function formatMessageTime(timestamp) { return date.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }); } +function getMessageDate(timestamp) { + if (!timestamp) return null; + const numericTimestamp = Number(timestamp); + const date = new Date(numericTimestamp > 1000000000000 ? numericTimestamp : numericTimestamp * 1000); + if (Number.isNaN(date.getTime())) return null; + return date; +} + +function getDateKey(timestamp) { + const date = getMessageDate(timestamp); + if (!date) return ''; + return date.toISOString().slice(0, 10); +} + +function formatDateSeparator(timestamp) { + const date = getMessageDate(timestamp); + if (!date) return ''; + + const today = new Date(); + const isToday = + date.getFullYear() === today.getFullYear() && + date.getMonth() === today.getMonth() && + date.getDate() === today.getDate(); + + if (isToday) return 'Hoje'; + + return date.toLocaleDateString('pt-BR'); +} + +function DateSeparator({ label }) { + if (!label) return null; + + return ( +
+ + + {label} + + +
+ ); +} + function MediaRenderer({ message, contactId, onLoadMedia, isAgent }) { const mediaUrl = useMemo(() => getMediaUrl(message.media), [message.media]); const mimetype = message.media?.mimetype || ''; @@ -414,91 +476,99 @@ export function ChatWindow({ 'radial-gradient(circle at top left, rgba(0, 164, 183, 0.06), transparent 22%), linear-gradient(180deg, rgba(245, 248, 251, 0.8), rgba(255, 255, 255, 0.95))', }} > - {messages.map((message) => { + {messages.map((message, index) => { const isAgent = message.sender === 'agent'; const isSystem = message.sender === 'system'; const parsedText = parseMessageText(message.text); const messageTime = formatMessageTime(message.timestamp); + const dateKey = getDateKey(message.timestamp); + const previousDateKey = index > 0 ? getDateKey(messages[index - 1]?.timestamp) : ''; + const shouldShowDateSeparator = dateKey && dateKey !== previousDateKey; + const dateSeparator = formatDateSeparator(message.timestamp); if (isSystem) { return ( -
- {message.text} -
+ + {shouldShowDateSeparator ? : null} +
+ {message.text} +
+
); } return ( -
- - {parsedText.senderLabel ? ( - - {parsedText.senderLabel} - - ) : null} - {parsedText.body ? ( - - {parsedText.body} - - ) : null} - {messageTime ? ( - - {messageTime} - - ) : null} -
+ + {shouldShowDateSeparator ? : null} +
+ + {parsedText.senderLabel ? ( + + {parsedText.senderLabel} + + ) : null} + {parsedText.body ? ( + + {parsedText.body} + + ) : null} + {messageTime ? ( + + {messageTime} + + ) : null} +
+
); })} @@ -606,7 +676,7 @@ export function ChatWindow({ onChange={(event) => setDraft(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter') { - onSend(); + onSend?.(draft); } }} disabled={!safeContact.id || !canReply} @@ -633,7 +703,7 @@ export function ChatWindow({ />