Add chat widget improvements and chat history component
Widget improvements: - Pulsating badge with unread message count on floating button - Clickable ticket reference link in chat header - ExternalLink icon on hover Desktop (Raven) improvements: - Track previous unread count for new message detection - Send native Windows notifications for new messages - Focus chat window when new messages arrive Chat history: - New query getTicketChatHistory for fetching chat sessions and messages - New component TicketChatHistory displaying chat sessions - Sessions can be expanded/collapsed to view messages - Pagination support for long conversations - Added to both dashboard and portal ticket views 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b194d77d57
commit
d766de4fda
6 changed files with 453 additions and 9 deletions
|
|
@ -594,3 +594,93 @@ export const listAgentSessions = query({
|
|||
return result.sort((a, b) => b.lastActivityAt - a.lastActivityAt)
|
||||
},
|
||||
})
|
||||
|
||||
// Historico de sessoes de chat de um ticket (para exibicao no painel)
|
||||
export const getTicketChatHistory = query({
|
||||
args: {
|
||||
ticketId: v.id("tickets"),
|
||||
viewerId: v.id("users"),
|
||||
},
|
||||
handler: async (ctx, { ticketId, viewerId }) => {
|
||||
const ticket = await ctx.db.get(ticketId)
|
||||
if (!ticket) {
|
||||
return { sessions: [], totalMessages: 0 }
|
||||
}
|
||||
|
||||
const viewer = await ctx.db.get(viewerId)
|
||||
if (!viewer || viewer.tenantId !== ticket.tenantId) {
|
||||
return { sessions: [], totalMessages: 0 }
|
||||
}
|
||||
|
||||
// Buscar todas as sessoes do ticket (ativas e finalizadas)
|
||||
const sessions = await ctx.db
|
||||
.query("liveChatSessions")
|
||||
.withIndex("by_ticket", (q) => q.eq("ticketId", ticketId))
|
||||
.collect()
|
||||
|
||||
if (sessions.length === 0) {
|
||||
return { sessions: [], totalMessages: 0 }
|
||||
}
|
||||
|
||||
// Buscar todas as mensagens do ticket
|
||||
const allMessages = await ctx.db
|
||||
.query("ticketChatMessages")
|
||||
.withIndex("by_ticket_created", (q) => q.eq("ticketId", ticketId))
|
||||
.collect()
|
||||
|
||||
// Agrupar mensagens por sessao (baseado no timestamp)
|
||||
// Mensagens entre startedAt e endedAt pertencem a sessao
|
||||
const sessionResults = await Promise.all(
|
||||
sessions
|
||||
.sort((a, b) => b.startedAt - a.startedAt) // Mais recente primeiro
|
||||
.map(async (session) => {
|
||||
const sessionMessages = allMessages.filter((msg) => {
|
||||
// Mensagem criada durante a sessao
|
||||
if (msg.createdAt < session.startedAt) return false
|
||||
if (session.endedAt && msg.createdAt > session.endedAt) return false
|
||||
return true
|
||||
})
|
||||
|
||||
// Obter nome da maquina
|
||||
let machineName = "Cliente"
|
||||
if (ticket.machineId) {
|
||||
const machine = await ctx.db.get(ticket.machineId)
|
||||
if (machine?.hostname) {
|
||||
machineName = machine.hostname
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sessionId: session._id,
|
||||
agentName: session.agentSnapshot?.name ?? "Agente",
|
||||
agentEmail: session.agentSnapshot?.email ?? null,
|
||||
agentAvatarUrl: session.agentSnapshot?.avatarUrl ?? null,
|
||||
machineName,
|
||||
status: session.status,
|
||||
startedAt: session.startedAt,
|
||||
endedAt: session.endedAt ?? null,
|
||||
messageCount: sessionMessages.length,
|
||||
messages: sessionMessages
|
||||
.sort((a, b) => a.createdAt - b.createdAt)
|
||||
.map((msg) => ({
|
||||
id: msg._id,
|
||||
body: msg.body,
|
||||
authorName: msg.authorSnapshot?.name ?? "Usuario",
|
||||
authorId: String(msg.authorId),
|
||||
createdAt: msg.createdAt,
|
||||
attachments: (msg.attachments ?? []).map((att) => ({
|
||||
storageId: att.storageId,
|
||||
name: att.name,
|
||||
type: att.type ?? null,
|
||||
})),
|
||||
})),
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
return {
|
||||
sessions: sessionResults,
|
||||
totalMessages: allMessages.length,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue