import React, { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Search, ChevronLeft, ChevronRight, Download, ArrowUpDown, Filter, Calendar as CalendarIcon } from 'lucide-react'; import { format, parseISO } from 'date-fns'; import { PageHeader } from '../components/PageHeader.tsx'; // Debounce hook function useDebounce(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = React.useState(value); React.useEffect(() => { const handler = setTimeout(() => setDebouncedValue(value), delay); return () => clearTimeout(handler); }, [value, delay]); return debouncedValue; } // --- Types --- interface Guia { id: string; numeroGuiaPrestador: string; numeroGuiaOperadora: string | null; dataSolicitacao: string; tipoTratamento: string; status: 'EM_ANALISE' | 'AUTORIZADO' | 'AUTORIZADO_PARCIAL' | 'NEGADO' | 'CANCELADO'; beneficiarioId: string; beneficiarioNome: string; beneficiarioIdentificacao: string; } interface GuiasResponse { data: Guia[]; total: number; page: number; pageSize: number; } // --- Status Badge Component --- const StatusBadge: React.FC<{ status: Guia['status'] }> = ({ status }) => { const configs = { AUTORIZADO: { label: 'Autorizado', color: 'bg-green-100 text-green-700 border-green-200' }, AUTORIZADO_PARCIAL: { label: 'Autorizado Parcialmente', color: 'bg-yellow-100 text-yellow-700 border-yellow-200' }, NEGADO: { label: 'Negado', color: 'bg-red-100 text-red-700 border-red-200' }, EM_ANALISE: { label: 'Em Análise', color: 'bg-blue-100 text-blue-700 border-blue-200' }, CANCELADO: { label: 'Cancelado', color: 'bg-gray-100 text-gray-700 border-gray-200' }, }; const config = configs[status] || configs.EM_ANALISE; return ( {config.label} ); }; // --- Main View --- export const MeusTratamentos: React.FC = () => { // Filters & State const [page, setPage] = useState(1); const [pageSize] = useState(10); const [search, setSearch] = useState(''); const [gto, setGto] = useState(''); const [status, setStatus] = useState(''); const [dataInicio, setDataInicio] = useState(''); const [dataFim, setDataFim] = useState(''); const [sortField, setSortField] = useState('dataSolicitacao'); const [sortOrder, setSortOrder] = useState<'ASC' | 'DESC'>('DESC'); const debouncedSearch = useDebounce(search, 500); const debouncedGto = useDebounce(gto, 500); // API Fetcher const fetchGuias = async (): Promise => { const params = new URLSearchParams({ page: page.toString(), pageSize: pageSize.toString(), search: debouncedSearch, gto: debouncedGto, status, dataInicio, dataFim, sortField, sortOrder }); const res = await fetch(`http://localhost:3002/api/guias?${params}`); if (!res.ok) throw new Error('Falha ao carregar guias'); return res.json(); }; const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['guias', page, debouncedSearch, debouncedGto, status, dataInicio, dataFim, sortField, sortOrder], queryFn: fetchGuias, placeholderData: (previousData) => previousData, }); const handleSort = (field: string) => { if (sortField === field) { setSortOrder(sortOrder === 'ASC' ? 'DESC' : 'ASC'); } else { setSortField(field); setSortOrder('DESC'); } }; const totalPages = data ? Math.ceil(data.total / pageSize) : 0; const exportToCSV = () => { if (!data?.data) return; const headers = ['Data Solicitação', 'Identificação', 'Beneficiário', 'Tipo Tratamento', 'GTO', 'Situação']; const rows = data.data.map(g => [ format(parseISO(g.dataSolicitacao), 'dd/MM/yyyy'), g.beneficiarioIdentificacao, g.beneficiarioNome, g.tipoTratamento, g.numeroGuiaPrestador, g.status ]); const csvContent = "data:text/csv;charset=utf-8," + headers.join(",") + "\n" + rows.map(e => e.join(",")).join("\n"); const encodedUri = encodeURI(csvContent); const link = document.createElement("a"); link.setAttribute("href", encodedUri); link.setAttribute("download", `tratamentos_${format(new Date(), 'yyyyMMdd')}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); }; return (
{/* Filters Bar */}
{ setGto(e.target.value); setPage(1); }} className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-gray-200 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none text-sm font-semibold uppercase" />
{ setSearch(e.target.value.toUpperCase()); setPage(1); }} className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-gray-200 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none text-sm font-semibold uppercase" />
{ setDataInicio(e.target.value); setPage(1); }} className="px-3 py-1.5 bg-gray-50 border border-gray-200 rounded-lg text-xs font-semibold" /> até { setDataFim(e.target.value); setPage(1); }} className="px-3 py-1.5 bg-gray-50 border border-gray-200 rounded-lg text-xs font-semibold" />
{/* Table Section */}
{isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( )) ) : isError ? ( ) : data?.data.length === 0 ? ( ) : ( data?.data.map((gui) => ( )) )}
Identificação do Beneficiário Tipo Tratamento
Erro ao carregar dados.
Nenhum tratamento encontrado.
{format(parseISO(gui.dataSolicitacao), 'dd/MM/yyyy')} {gui.beneficiarioIdentificacao}

{gui.beneficiarioNome}

{gui.tipoTratamento} {gui.numeroGuiaPrestador}
{/* Pagination Footer */}
Mostrando {data?.data.length || 0} de {data?.total || 0} resultados
{Array.from({ length: totalPages }, (_, i) => i + 1).map(p => ( ))}
); };