diff --git a/src/components/portal/portal-ticket-detail.tsx b/src/components/portal/portal-ticket-detail.tsx index f689372..d2cd90e 100644 --- a/src/components/portal/portal-ticket-detail.tsx +++ b/src/components/portal/portal-ticket-detail.tsx @@ -505,7 +505,6 @@ export function PortalTicketDetail({ ticketId }: PortalTicketDetailProps) { ) : null} -
@@ -685,6 +684,7 @@ export function PortalTicketDetail({ ticketId }: PortalTicketDetailProps) {
+ { if (!open) setPreviewAttachment(null) }}> diff --git a/src/components/tickets/ticket-chat-history.tsx b/src/components/tickets/ticket-chat-history.tsx index 1b66a06..76e5054 100644 --- a/src/components/tickets/ticket-chat-history.tsx +++ b/src/components/tickets/ticket-chat-history.tsx @@ -1,13 +1,12 @@ "use client" -import { useState } from "react" +import { useState, useMemo } from "react" import { useQuery, useAction } from "convex/react" -import { formatDistanceToNow, format } from "date-fns" +import { format, isToday, isYesterday, startOfDay } from "date-fns" import { ptBR } from "date-fns/locale" import { api } from "@/convex/_generated/api" import type { Id } from "@/convex/_generated/dataModel" import { useAuth } from "@/lib/auth-client" -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Spinner } from "@/components/ui/spinner" import { cn } from "@/lib/utils" @@ -20,6 +19,7 @@ import { Download, FileText, Paperclip, + Calendar, } from "lucide-react" type ChatHistoryProps = { @@ -52,7 +52,16 @@ type ChatSession = { messages: ChatMessage[] } +type DayGroup = { + date: Date + dateKey: string + label: string + sessions: ChatSession[] + totalMessages: number +} + const MESSAGES_PER_PAGE = 20 +const DAYS_PER_PAGE = 5 function formatDuration(minutes: number): string { if (minutes < 60) { @@ -66,6 +75,16 @@ function formatDuration(minutes: number): string { return `${hours}h ${mins}min` } +function formatDayLabel(date: Date): string { + if (isToday(date)) { + return "Hoje" + } + if (isYesterday(date)) { + return "Ontem" + } + return format(date, "dd 'de' MMMM 'de' yyyy", { locale: ptBR }) +} + function MessageAttachmentPreview({ attachment }: { attachment: { storageId: string; name: string; type: string | null } }) { const getFileUrl = useAction(api.files.getUrl) const [loading, setLoading] = useState(false) @@ -155,7 +174,7 @@ function ChatSessionCard({ session, isExpanded, onToggle }: { session: ChatSessi )}
- {format(session.startedAt, "dd/MM/yyyy 'as' HH:mm", { locale: ptBR })} + {format(session.startedAt, "HH:mm", { locale: ptBR })} - {session.messageCount} mensagens - @@ -255,9 +274,62 @@ function ChatSessionCard({ session, isExpanded, onToggle }: { session: ChatSessi ) } +function DayGroupCard({ + dayGroup, + isExpanded, + onToggle, + expandedSessions, + onToggleSession +}: { + dayGroup: DayGroup + isExpanded: boolean + onToggle: () => void + expandedSessions: Set + onToggleSession: (sessionId: string) => void +}) { + return ( +
+ {/* Header do dia */} + + + {/* Sessoes do dia */} + {isExpanded && ( +
+ {dayGroup.sessions.map((session) => ( + onToggleSession(session.sessionId)} + /> + ))} +
+ )} +
+ ) +} + export function TicketChatHistory({ ticketId }: ChatHistoryProps) { const { convexUserId } = useAuth() + const [expandedDays, setExpandedDays] = useState>(new Set()) const [expandedSessions, setExpandedSessions] = useState>(new Set()) + const [visibleDays, setVisibleDays] = useState(DAYS_PER_PAGE) const chatHistory = useQuery( api.liveChat.getTicketChatHistory, @@ -266,6 +338,56 @@ export function TicketChatHistory({ ticketId }: ChatHistoryProps) { : "skip" ) + // Agrupar sessoes por dia + const dayGroups = useMemo(() => { + if (!chatHistory?.sessions) return [] + + const groups = new Map() + + chatHistory.sessions.forEach((session: ChatSession) => { + const sessionDate = new Date(session.startedAt) + const dayStart = startOfDay(sessionDate) + const dateKey = dayStart.toISOString() + + if (!groups.has(dateKey)) { + groups.set(dateKey, { + date: dayStart, + dateKey, + label: formatDayLabel(dayStart), + sessions: [], + totalMessages: 0, + }) + } + + const group = groups.get(dateKey)! + group.sessions.push(session) + group.totalMessages += session.messageCount + }) + + // Ordenar sessoes dentro de cada grupo por hora (mais recente primeiro) + groups.forEach((group) => { + group.sessions.sort((a, b) => b.startedAt - a.startedAt) + }) + + // Retornar grupos ordenados por data (mais recente primeiro) + return Array.from(groups.values()).sort((a, b) => b.date.getTime() - a.date.getTime()) + }, [chatHistory?.sessions]) + + const displayedDays = dayGroups.slice(0, visibleDays) + const hasMoreDays = dayGroups.length > visibleDays + + const toggleDay = (dateKey: string) => { + setExpandedDays((prev) => { + const next = new Set(prev) + if (next.has(dateKey)) { + next.delete(dateKey) + } else { + next.add(dateKey) + } + return next + }) + } + const toggleSession = (sessionId: string) => { setExpandedSessions((prev) => { const next = new Set(prev) @@ -278,32 +400,50 @@ export function TicketChatHistory({ ticketId }: ChatHistoryProps) { }) } + const loadMoreDays = () => { + setVisibleDays((prev) => prev + DAYS_PER_PAGE) + } + // Nao mostrar se nao ha historico if (!chatHistory || chatHistory.sessions.length === 0) { return null } return ( - - - - - Histórico de chat - - {chatHistory.sessions.length} {chatHistory.sessions.length === 1 ? "sessão" : "sessões"} - {chatHistory.totalMessages} mensagens - - - - - {chatHistory.sessions.map((session: ChatSession) => ( - toggleSession(session.sessionId)} +
+ {/* Header */} +
+
+ +

Historico de chat

+
+ + {chatHistory.sessions.length} {chatHistory.sessions.length === 1 ? "sessao" : "sessoes"} - {chatHistory.totalMessages} mensagens + +
+ + {/* Grupos por dia */} +
+ {displayedDays.map((dayGroup) => ( + toggleDay(dayGroup.dateKey)} + expandedSessions={expandedSessions} + onToggleSession={toggleSession} /> ))} - - +
+ + {/* Carregar mais dias */} + {hasMoreDays && ( +
+ +
+ )} +
) } diff --git a/src/components/tickets/ticket-detail-view.tsx b/src/components/tickets/ticket-detail-view.tsx index a66d18e..80299d3 100644 --- a/src/components/tickets/ticket-detail-view.tsx +++ b/src/components/tickets/ticket-detail-view.tsx @@ -108,8 +108,8 @@ export function TicketDetailView({ id }: { id: string }) {
- +