'use client'; import * as React from 'react'; import { useMutation, useQuery } from '@tanstack/react-query'; import { Download, Search } from 'lucide-react'; import { PageHeader } from '@/components/layout/page-header'; import { RequirePermission } from '@/components/require-permission'; import { DataTable, type DataTableColumn } from '@/components/data-table/data-table'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, } from '@/components/ui/select'; import { useAuth } from '@/hooks/use-auth'; import { useToast } from '@/components/ui/toast'; import { reportsService } from '@/services/reports'; import { campaignsService } from '@/services/campaigns'; import { queuesService } from '@/services/queues'; import { agentsService } from '@/services/agents'; import type { DialAttempt, CallState } from '@/types'; import { errorMessage } from '@/lib/error-message'; import { formatDateTime, formatSeconds, formatPercent } from '@/lib/utils'; const STATES: CallState[] = [ 'CREATED', 'RESERVED', 'ORIGINATING', 'RINGING', 'ANSWERED', 'QUEUED', 'AGENT_CONNECTED', 'COMPLETED', 'FAILED', ]; function MetricCard({ label, value }: { label: string; value: React.ReactNode }) { return (

{label}

{value}

); } function Content() { const { can } = useAuth(); const { toast } = useToast(); const [filters, setFilters] = React.useState({ campaignId: 'all', queueId: 'all', agentId: 'all', state: 'all', phone: '', from: '', to: '', }); const [page, setPage] = React.useState(1); const { data: campaigns } = useQuery({ queryKey: ['campaigns'], queryFn: campaignsService.list }); const { data: queues } = useQuery({ queryKey: ['queues'], queryFn: queuesService.list }); const { data: agents } = useQuery({ queryKey: ['agents'], queryFn: agentsService.list }); const apiQuery = { campaignId: filters.campaignId === 'all' ? undefined : filters.campaignId, queueId: filters.queueId === 'all' ? undefined : filters.queueId, agentId: filters.agentId === 'all' ? undefined : filters.agentId, state: filters.state === 'all' ? undefined : filters.state, phone: filters.phone || undefined, from: filters.from || undefined, to: filters.to || undefined, }; const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['reports-calls', apiQuery, page], queryFn: () => reportsService.calls({ ...apiQuery, page, pageSize: 25 }), }); const { data: metrics } = useQuery({ queryKey: ['reports-metrics', apiQuery.campaignId, apiQuery.from, apiQuery.to], queryFn: () => reportsService.metrics({ campaignId: apiQuery.campaignId, from: apiQuery.from, to: apiQuery.to, }), }); const exportMutation = useMutation({ mutationFn: () => reportsService.exportCalls(apiQuery), onSuccess: (blob) => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'relatorio-chamadas.csv'; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); }, onError: (err) => toast({ title: 'Erro', description: errorMessage(err), variant: 'destructive' }), }); const columns: DataTableColumn[] = [ { key: 'startedAt', header: 'Início', render: (r) => formatDateTime(r.startedAt) }, { key: 'calledNumber', header: 'Número', render: (r) => r.calledNumber }, { key: 'lead', header: 'Lead', render: (r) => r.lead?.name ?? '—' }, { key: 'campaign', header: 'Campanha', render: (r) => r.campaign?.name ?? '—' }, { key: 'state', header: 'Estado', render: (r) => {r.state} }, { key: 'hangupCause', header: 'Causa', render: (r) => r.hangupCause ?? '—' }, { key: 'disposition', header: 'Disposição', render: (r) => r.disposition?.name ?? '—' }, ]; return ( <> exportMutation.mutate()}> Exportar CSV ) } />
setFilters((f) => ({ ...f, phone: e.target.value }))} />
setFilters((f) => ({ ...f, from: e.target.value }))} />
setFilters((f) => ({ ...f, to: e.target.value }))} />
refetch()} rowKey={(r) => r.id} page={data?.page ?? page} pageSize={data?.pageSize ?? 25} total={data?.total ?? 0} onPageChange={setPage} emptyMessage="Nenhuma chamada encontrada para os filtros selecionados." /> ); } export default function CallsReportPage() { return ( ); }