"use client" import { useEffect, useState } from "react" import Link from "next/link" import { formatDistanceToNow } from "date-fns" import { ptBR } from "date-fns/locale" import { tickets as ticketsMock } from "@/lib/mocks/tickets" import type { Ticket } from "@/lib/schemas/ticket" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Badge } from "@/components/ui/badge" import { Card, CardContent } from "@/components/ui/card" import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@/components/ui/empty" import { NewTicketDialog } from "@/components/tickets/new-ticket-dialog" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { TicketPriorityPill } from "@/components/tickets/priority-pill" import { TicketStatusBadge } from "@/components/tickets/status-badge" const channelLabel: Record = { EMAIL: "E-mail", WHATSAPP: "WhatsApp", CHAT: "Chat", PHONE: "Telefone", API: "API", MANUAL: "Manual", } const cellClass = "px-6 py-5 align-top text-sm text-neutral-700 first:pl-8 last:pr-8" const queueBadgeClass = "inline-flex items-center rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-xs font-semibold text-neutral-700" const channelBadgeClass = "inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-xs font-semibold text-neutral-700" const tagBadgeClass = "inline-flex items-center rounded-full border border-slate-200 bg-slate-50 px-2.5 py-0.5 text-[11px] font-medium text-neutral-600" const tableRowClass = "group border-b border-slate-100 text-sm transition-colors hover:bg-slate-100/70 last:border-none" function formatDuration(ms?: number) { if (!ms || ms <= 0) return "—" const totalSeconds = Math.floor(ms / 1000) const hours = Math.floor(totalSeconds / 3600) const minutes = Math.floor((totalSeconds % 3600) / 60) const seconds = totalSeconds % 60 if (hours > 0) { return `${hours}h ${minutes.toString().padStart(2, "0")}m` } if (minutes > 0) { return `${minutes}m ${seconds.toString().padStart(2, "0")}s` } return `${seconds}s` } function AssigneeCell({ ticket }: { ticket: Ticket }) { if (!ticket.assignee) { return Sem responsável } const initials = ticket.assignee.name .split(" ") .slice(0, 2) .map((part) => part[0]?.toUpperCase()) .join("") return (
{initials}
{ticket.assignee.name} {ticket.assignee.teams?.[0] ?? "Agente"}
) } export type TicketsTableProps = { tickets?: Ticket[] } export function TicketsTable({ tickets = ticketsMock }: TicketsTableProps) { const [now, setNow] = useState(() => Date.now()) useEffect(() => { const interval = setInterval(() => { setNow(Date.now()) }, 1000) return () => clearInterval(interval) }, []) const getWorkedMs = (ticket: Ticket) => { const base = ticket.workSummary?.totalWorkedMs ?? 0 const activeStart = ticket.workSummary?.activeSession?.startedAt if (activeStart instanceof Date) { return base + Math.max(0, now - activeStart.getTime()) } return base } return ( Ticket Assunto Fila Canal Prioridade Status Tempo Responsável Atualizado {tickets.map((ticket) => (
#{ticket.reference} {ticket.queue ?? "Sem fila"}
{ticket.subject} {ticket.summary ?? "Sem resumo"}
{ticket.requester.name} {ticket.tags?.map((tag) => ( {tag} ))}
{ticket.metrics?.timeWaitingMinutes ? ( Em espera há {ticket.metrics.timeWaitingMinutes} min ) : null}
{formatDistanceToNow(ticket.updatedAt, { addSuffix: true, locale: ptBR })}
))}
{tickets.length === 0 && ( Nenhum ticket encontrado Ajuste os filtros ou crie um novo ticket. )}
) }