"use client" import { useMemo, useState } from "react" import { useQuery } from "convex/react" import { IconInbox, IconAlertTriangle, IconFilter } from "@tabler/icons-react" import { api } from "@/convex/_generated/api" import type { Id } from "@/convex/_generated/dataModel" import { useAuth } from "@/lib/auth-client" import { DEFAULT_TENANT_ID } from "@/lib/constants" import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" import { Skeleton } from "@/components/ui/skeleton" import { Badge } from "@/components/ui/badge" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { usePersistentCompanyFilter } from "@/lib/use-company-filter" const PRIORITY_LABELS: Record = { LOW: "Baixa", MEDIUM: "Média", HIGH: "Alta", URGENT: "Crítica", } const STATUS_LABELS: Record = { PENDING: "Pendentes", AWAITING_ATTENDANCE: "Aguardando atendimento", PAUSED: "Pausados", RESOLVED: "Resolvidos", } export function BacklogReport() { const [timeRange, setTimeRange] = useState("90d") const [companyId, setCompanyId] = usePersistentCompanyFilter("all") const { session, convexUserId } = useAuth() const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID const data = useQuery( api.reports.backlogOverview, convexUserId ? { tenantId, viewerId: convexUserId as Id<"users">, range: timeRange, companyId: companyId === "all" ? undefined : (companyId as Id<"companies">) } : "skip" ) const companies = useQuery(api.companies.list, convexUserId ? { tenantId, viewerId: convexUserId as Id<"users"> } : "skip") as Array<{ id: Id<"companies">; name: string }> | undefined const mostCriticalPriority = useMemo(() => { if (!data) return null const entries = Object.entries(data.priorityCounts) as Array<[string, number]> if (entries.length === 0) return null return entries.reduce((prev, current) => (current[1] > prev[1] ? current : prev)) }, [data]) if (!data) { return (
{Array.from({ length: 3 }).map((_, index) => ( ))}
) } return (
Tickets em aberto Backlog total em atendimento. {data.totalOpen} Prioridade predominante Volume por prioridade no backlog. {mostCriticalPriority ? ( {PRIORITY_LABELS[mostCriticalPriority[0]] ?? mostCriticalPriority[0]} ({mostCriticalPriority[1]}) ) : ( "—" )} Status acompanhados Distribuição dos tickets por status. {Object.keys(data.statusCounts).length}
Status do backlog Acompanhe a evolução dos tickets pelas fases do fluxo de atendimento.
90 dias 30 dias 7 dias
{(Object.entries(data.statusCounts) as Array<[string, number]>).map(([status, total]) => (

{STATUS_LABELS[status] ?? status}

{total}

))}
Backlog por prioridade Analise a pressão de atendimento conforme o nível de urgência.
{(Object.entries(data.priorityCounts) as Array<[string, number]>).map(([priority, total]) => (
{PRIORITY_LABELS[priority] ?? priority} {total} ticket{total === 1 ? "" : "s"}
))}
Filas com maior backlog Identifique onde concentrar esforços de atendimento. {data.queueCounts.length === 0 ? (

Nenhuma fila com tickets abertos no momento.

) : (
    {data.queueCounts.map((queue: { id: string; name: string; total: number }) => (
  • {queue.name}
    {queue.total} em aberto
  • ))}
)}
) }