import { useState } from 'react'; import { Badge, Button, Modal, Input, Space, Spin, Table, Tag, Typography, Tabs, Form } from 'antd'; import { CustomerServiceOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons'; import type { TableColumnsType } from 'antd'; import { STATUS_CHAMADO_LABEL, TIPO_CHAMADO_LABEL, RESOLUCAO_CHAMADO_LABEL, type Chamado, type ItemAfetado, type ChamadoMensagem, type PedidoErpConsultaItem, } from '@sar/api-interface'; import { useChamados, useAddMensagemRep, useCancelChamado, useChamado, } from '../../lib/queries/sac'; import { useOrderErpConsulta, useOrderDetail } from '../../lib/queries/orders'; import { AbrirChamadoModal } from './AbrirChamadoModal'; const { Title, Text } = Typography; const { TextArea } = Input; const STATUS_COLOR: Record = { aberto: 'blue', em_analise: 'orange', aguardando_rep: 'purple', resolvido: 'green', cancelado: 'default', }; function pedidoLabel(chamado: Chamado) { if (chamado.numPedErp) return `ERP #${chamado.numPedErp}`; if (chamado.numPedSar) return `SAR-${String(chamado.numPedSar).padStart(5, '0')}`; return '—'; } // Busca pedido ERP por texto livre (cliente, número, etc.) e abre chamado function BuscarPedidoModal({ open, onClose }: { open: boolean; onClose: () => void }) { const [searchInput, setSearchInput] = useState(''); const [searchAtivo, setSearchAtivo] = useState(''); const [pedidoSelecionado, setPedidoSelecionado] = useState(null); // idPedido é o ID interno do ERP (usado no endpoint /orders/erp/:id) // numeroPedido é o número externo visível ao usuário const erp_id = pedidoSelecionado?.idPedido ?? null; const consulta = useOrderErpConsulta({ search: searchAtivo, limit: 20 }, !!searchAtivo); const detalhe = useOrderDetail(erp_id ? `erp-${erp_id}` : undefined); function buscar() { const trimmed = searchInput.trim(); if (!trimmed) return; setSearchAtivo(trimmed); setPedidoSelecionado(null); } function fechar() { setSearchInput(''); setSearchAtivo(''); setPedidoSelecionado(null); onClose(); } // Detalhe carregado — abre o formulário de chamado if (detalhe.data && pedidoSelecionado) { return ( ); } const resultados = consulta.data?.data ?? []; const carregandoDetalhe = detalhe.isLoading; const colunas: TableColumnsType = [ { title: 'Pedido', dataIndex: 'numeroPedido', width: 90 }, { title: 'Cliente', render: (_: unknown, r: PedidoErpConsultaItem) => r.razaoCliente ?? r.nomeCliente ?? '—', ellipsis: true, }, { title: 'Data', dataIndex: 'data', width: 95, render: (v: string) => new Date(v).toLocaleDateString('pt-BR'), }, { title: 'Total', dataIndex: 'total', width: 100, render: (v: string) => Number(v).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' }), }, ]; return ( } placeholder="Buscar por cliente, número do pedido..." value={searchInput} onChange={(e) => setSearchInput(e.target.value)} onPressEnter={buscar} autoFocus /> {searchAtivo && ( rowKey="numeroPedido" columns={colunas} dataSource={resultados} loading={consulta.isLoading || carregandoDetalhe} pagination={false} size="small" scroll={{ y: 320 }} onRow={(r) => ({ onClick: () => (r.idPedido ? setPedidoSelecionado(r) : undefined), style: { cursor: r.idPedido ? 'pointer' : 'not-allowed', opacity: r.idPedido ? 1 : 0.4, }, })} locale={{ emptyText: 'Nenhum pedido encontrado.' }} /> )} ); } function ChamadoDetalheModal({ id, open, onClose, }: { id: number; open: boolean; onClose: () => void; }) { const [texto, setTexto] = useState(''); const { data: chamado, isLoading } = useChamado(id); const addMsg = useAddMensagemRep(id); const cancel = useCancelChamado(); function enviar() { if (!texto.trim()) return; addMsg.mutate({ texto: texto.trim() }, { onSuccess: () => setTexto('') }); } const fechado = chamado && ['resolvido', 'cancelado'].includes(chamado.status); return ( {isLoading || !chamado ? ( ) : ( {STATUS_CHAMADO_LABEL[chamado.status]} {TIPO_CHAMADO_LABEL[chamado.tipo] ?? chamado.tipo} {chamado.resolucao && ( {RESOLUCAO_CHAMADO_LABEL[chamado.resolucao] ?? chamado.resolucao} )} {pedidoLabel(chamado)} {chamado.nomeCliente ? ` · ${chamado.nomeCliente}` : ''} {chamado.descricao} {chamado.notaResolucao && (
Resolução: {chamado.notaResolucao}
)} {chamado.itensAfetados && chamado.itensAfetados.length > 0 && (
Produtos afetados:{' '} {(chamado.itensAfetados as ItemAfetado[]).map((it, i) => ( {it.codProduto} — {it.nomeProduto} ({it.qtd} un) ))}
)}
{(chamado.mensagens ?? []).length === 0 ? ( Sem mensagens ainda. ) : ( ((chamado.mensagens as ChamadoMensagem[]) ?? []).map((m) => (
{m.autor === 'rep' ? 'Você' : 'Empresa'}
{m.texto}
{new Date(m.createdAt).toLocaleString('pt-BR')}
)) )}
{!fechado && (