import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { Link } from "wouter"; import { BrowserFrame } from "@/components/Browser/BrowserFrame"; import { BarChart3, Star, Shield, Users, MessageSquare, Ticket, TrendingUp, ArrowLeft, DollarSign, CheckCircle2, AlertTriangle, Clock, Download } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Progress } from "@/components/ui/progress"; interface OverviewReport { period: string; conversations: { total: number; resolved: number; open: number; avg_csat: number; avg_handle_minutes: number; channels_used: number }; tickets: { total: number; resolved: number; open: number; sla_breaches: number; avg_csat: number }; contacts: { total: number; leads: number; customers: number; new_in_period: number }; deals: { total: number; won: number; lost: number; won_value: number; win_rate_pct: number }; generated_at: string; } interface AgentReport { agent_id: string; agent_name: string; conversations_handled: number; resolved: number; avg_csat: number; avg_handle_minutes: number; tickets_handled: number; tickets_resolved: number; } interface SlaReport { period: string; protocols: { total: number; breached: number; compliant: number; compliance_rate_pct: number }; tickets_by_priority: Array<{ priority: string; total: number; breached: number; avg_resolution_minutes: number }>; } interface CsatSummary { period: string; total_responses: number; avg_score: number; satisfaction_rate_pct: number; distribution: { 5: number; 4: number; 3: number; "1-2": number }; } export default function XosReports() { const [period, setPeriod] = useState("30d"); const [activeTab, setActiveTab] = useState("overview"); const { data: overview, isLoading } = useQuery({ queryKey: ["/api/xos/reports/overview", period], queryFn: async () => { const res = await fetch(`/api/xos/reports/overview?period=${period}`); return res.json(); }, }); const { data: agentReport = [] } = useQuery({ queryKey: ["/api/xos/reports/agents", period], queryFn: async () => { const res = await fetch(`/api/xos/reports/agents?period=${period}`); return res.json(); }, }); const { data: slaReport } = useQuery({ queryKey: ["/api/xos/reports/sla", period], queryFn: async () => { const res = await fetch(`/api/xos/reports/sla?period=${period}`); return res.json(); }, }); const { data: csatSummary } = useQuery({ queryKey: ["/api/xos/csat/summary", period], queryFn: async () => { const res = await fetch(`/api/xos/csat/summary?period=${period}`); return res.json(); }, }); const formatCurrency = (v: number) => new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(v || 0); const periodLabel: Record = { "7d": "7 dias", "30d": "30 dias", "90d": "90 dias", "1y": "1 ano" }; const getPriorityColor = (p: string) => ({ low: "text-slate-500", normal: "text-blue-600", high: "text-orange-600", urgent: "text-red-600" }[p] || "text-slate-600"); const getPriorityBadge = (p: string) => ({ low: "bg-slate-100 text-slate-700", normal: "bg-blue-100 text-blue-700", high: "bg-orange-100 text-orange-700", urgent: "bg-red-100 text-red-700" }[p] || "bg-gray-100 text-gray-700"); const csatBar = (label: string, count: number, total: number, color: string) => (
{label} 0 ? (count / total) * 100 : 0} className={`flex-1 h-3 ${color}`} /> {count}
); if (isLoading) { return (
); } const conv = overview?.conversations; const tick = overview?.tickets; const contacts = overview?.contacts; const deals = overview?.deals; return (
{/* Header */}

Relatórios XOS

Análise de atendimento e CRM

Visão Geral CSAT SLA Agentes {/* Overview */}

Período: {periodLabel[period]}

{/* Top KPI row */}

Conversas

{conv?.total || 0}

{conv?.resolved || 0} resolvidas ({conv?.total ? Math.round((conv.resolved / conv.total) * 100) : 0}%)

Tickets

{tick?.total || 0}

{tick?.sla_breaches || 0} SLA violados

Receita Ganha

{formatCurrency(deals?.won_value || 0)}

{deals?.won || 0} deals • {deals?.win_rate_pct || 0}% taxa

Novos Contatos

{contacts?.new_in_period || 0}

{contacts?.leads || 0} leads • {contacts?.customers || 0} clientes
{/* Detail cards */}
Atendimento

{conv?.avg_handle_minutes || 0}min

Tempo Médio de Atendimento

{conv?.channels_used || 0}

Canais Utilizados

{conv?.resolved || 0}

Resolvidas

{conv?.open || 0}

Em Aberto

{conv?.avg_csat ? (

{Number(conv.avg_csat).toFixed(1)} / 5

CSAT Médio das Conversas

) : null}
Pipeline de Vendas

{deals?.won || 0}

Ganhos

{deals?.lost || 0}

Perdidos

Taxa de conversão {deals?.win_rate_pct || 0}%

Valor Total Ganho

{formatCurrency(deals?.won_value || 0)}

{/* CSAT */} {csatSummary ? ( <>

{Number(csatSummary.avg_score).toFixed(1)}

Nota Média / 5

{csatSummary.satisfaction_rate_pct}%

Taxa de Satisfação (4-5 ★)

{csatSummary.total_responses}

Total de Avaliações

Distribuição de Notas Período: {periodLabel[period]} {csatBar("⭐⭐⭐⭐⭐", csatSummary.distribution[5], csatSummary.total_responses, "[&>div]:bg-emerald-500")} {csatBar("⭐⭐⭐⭐", csatSummary.distribution[4], csatSummary.total_responses, "[&>div]:bg-green-400")} {csatBar("⭐⭐⭐", csatSummary.distribution[3], csatSummary.total_responses, "[&>div]:bg-yellow-400")} {csatBar("⭐⭐", csatSummary.distribution["1-2"], csatSummary.total_responses, "[&>div]:bg-red-400")} ) : (

Nenhuma avaliação no período

)}
{/* SLA */} {slaReport && ( <>
= 90 ? "bg-gradient-to-br from-emerald-500 to-emerald-600" : slaReport.protocols.compliance_rate_pct >= 70 ? "bg-gradient-to-br from-yellow-500 to-yellow-600" : "bg-gradient-to-br from-red-500 to-red-600"} text-white`}>

{slaReport.protocols.compliance_rate_pct}%

Compliance de SLA

{slaReport.protocols.compliant}

Protocolos dentro do SLA

{slaReport.protocols.breached}

Violações de SLA

Tickets por Prioridade {slaReport.tickets_by_priority.length === 0 ? (

Nenhum ticket no período

) : (
{slaReport.tickets_by_priority.map(row => ( ))}
Prioridade Total Violações Tempo Médio Res.
{row.priority} {row.total} 0 ? "text-red-600 font-semibold" : "text-emerald-600"}> {row.breached} {row.avg_resolution_minutes ? (
{Number(row.avg_resolution_minutes).toFixed(0)}min
) : "—"}
)}
)}
{/* Agents */} Performance por Agente Período: {periodLabel[period]}
{agentReport.map(agent => { const resolutionRate = agent.conversations_handled > 0 ? Math.round((agent.resolved / agent.conversations_handled) * 100) : 0; return ( ); })} {agentReport.length === 0 && ( )}
Agente Conversas Resolvidas CSAT TMA Tickets
{agent.agent_name} {agent.conversations_handled}
{agent.resolved} {resolutionRate}%
{agent.avg_csat ? (
{Number(agent.avg_csat).toFixed(1)}
) : }
{agent.avg_handle_minutes ? `${Number(agent.avg_handle_minutes).toFixed(0)}min` : "—"} {agent.tickets_handled} / {agent.tickets_resolved}
Nenhum dado de agente no período
); }