feat(chat): adiciona separador de dias e melhora layout do header

- Adiciona separador de data entre mensagens de dias diferentes (estilo WhatsApp)
- Mostra "Hoje", "Ontem" ou data completa (ex: "segunda-feira, 15 de dezembro")
- Separa hostname da maquina em linha propria no header
- Hostname com truncate e tooltip para nomes longos

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rever-tecnologia 2025-12-15 10:10:04 -03:00
parent 2293a0275a
commit 300179279a

View file

@ -53,6 +53,40 @@ function formatTime(timestamp: number) {
}) })
} }
function formatDateSeparator(timestamp: number) {
const date = new Date(timestamp)
const today = new Date()
const yesterday = new Date(today)
yesterday.setDate(yesterday.getDate() - 1)
const isToday = date.toDateString() === today.toDateString()
const isYesterday = date.toDateString() === yesterday.toDateString()
if (isToday) return "Hoje"
if (isYesterday) return "Ontem"
return date.toLocaleDateString("pt-BR", {
weekday: "long",
day: "2-digit",
month: "long",
})
}
function getDateKey(timestamp: number) {
return new Date(timestamp).toDateString()
}
// Componente separador de data (estilo WhatsApp)
function DateSeparator({ timestamp }: { timestamp: number }) {
return (
<div className="flex items-center justify-center py-2">
<div className="rounded-full bg-slate-200/80 px-3 py-1 text-xs font-medium text-slate-600">
{formatDateSeparator(timestamp)}
</div>
</div>
)
}
type ChatSession = { type ChatSession = {
ticketId: string ticketId: string
ticketRef: number ticketRef: number
@ -661,16 +695,22 @@ export function ChatWidget() {
)} )}
</div> </div>
{activeSession && ( {activeSession && (
<a <div className="flex flex-col">
href={`/tickets/${activeTicketId}`} <a
target="_blank" href={`/tickets/${activeTicketId}`}
rel="noopener noreferrer" target="_blank"
className="group flex items-center gap-1 text-xs text-slate-500 hover:text-slate-900 transition-colors" rel="noopener noreferrer"
> className="group flex items-center gap-1 text-xs text-slate-500 hover:text-slate-900 transition-colors"
<span>#{activeSession.ticketRef}</span> >
{machineHostname && <span> - {machineHostname}</span>} <span>#{activeSession.ticketRef}</span>
<ExternalLink className="size-3 opacity-0 group-hover:opacity-100 transition-opacity" /> <ExternalLink className="size-3 opacity-0 group-hover:opacity-100 transition-opacity" />
</a> </a>
{machineHostname && (
<span className="max-w-[140px] truncate text-xs text-slate-400" title={machineHostname}>
{machineHostname}
</span>
)}
</div>
)} )}
</div> </div>
</div> </div>
@ -757,16 +797,22 @@ export function ChatWidget() {
</div> </div>
) : ( ) : (
<div className="space-y-3"> <div className="space-y-3">
{messages.map((msg) => { {messages.map((msg, index) => {
const isOwn = String(msg.authorId) === String(viewerId) const isOwn = String(msg.authorId) === String(viewerId)
const bodyText = msg.body?.trim() ?? "" const bodyText = msg.body?.trim() ?? ""
const shouldShowBody = const shouldShowBody =
bodyText.length > 0 && bodyText.length > 0 &&
!(bodyText === "[Anexo]" && (msg.attachments?.length ?? 0) > 0) !(bodyText === "[Anexo]" && (msg.attachments?.length ?? 0) > 0)
// Verificar se precisa mostrar separador de data
const prevMsg = index > 0 ? messages[index - 1] : null
const showDateSeparator = !prevMsg || getDateKey(msg.createdAt) !== getDateKey(prevMsg.createdAt)
return ( return (
<div <div key={msg.id}>
key={msg.id} {showDateSeparator && <DateSeparator timestamp={msg.createdAt} />}
className={cn("flex gap-2", isOwn ? "flex-row-reverse" : "flex-row")} <div
className={cn("flex gap-2", isOwn ? "flex-row-reverse" : "flex-row")}
> >
<div <div
className={cn( className={cn(
@ -803,6 +849,7 @@ export function ChatWidget() {
</p> </p>
</div> </div>
</div> </div>
</div>
) )
})} })}
<div ref={messagesEndRef} /> <div ref={messagesEndRef} />