Files
advx/src/components/provas/ProvaStatus.tsx
T
2025-04-10 23:07:21 -03:00

164 lines
5.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Card } from '../../components/ui/Card';
import { format } from 'date-fns';
interface ProvaStatus {
id: string;
status: 'PENDENTE' | 'PROCESSANDO' | 'CONCLUIDO' | 'ERRO';
fileName: string;
checksumSha256: string;
checksumSha512: string;
checksumMd5: string;
reportPath: string;
error?: string;
}
export function ProvaStatus() {
const { id } = useParams<{ id: string }>();
const [status, setStatus] = useState<ProvaStatus | null>(null);
const [error, setError] = useState<string | null>(null);
const navigate = useNavigate();
useEffect(() => {
const checkStatus = async () => {
try {
const response = await fetch(`/api/provas/${id}/status`);
// Verificar se a resposta foi bem-sucedida
if (!response.ok) {
const errorText = await response.text();
throw new Error(errorText || 'Erro ao buscar status');
}
const data = await response.json();
setStatus(data);
// Continuar verificando se ainda estiver processando
if (data.status === 'PENDENTE' || data.status === 'PROCESSANDO') {
setTimeout(checkStatus, 2000);
}
} catch (error) {
console.error('Erro detalhado ao verificar status:', error);
setError('Erro ao verificar status da prova');
}
};
checkStatus();
}, [id]);
const handleDownloadReport = () => {
if (status && status.status === 'CONCLUIDO') {
window.open(`/api/provas/relatorio/${status.checksumSha256}`, '_blank');
}
};
const handleViewVerification = () => {
if (status && status.checksumSha256) {
navigate(`/provas/verificar/${status.checksumSha256}`);
}
};
if (error) return (
<div className="max-w-3xl mx-auto p-4">
<Card>
<div className="p-6 text-center">
<div className="text-red-600 mb-4">{error}</div>
<button
onClick={() => navigate('/provas/upload')}
className="px-4 py-2 bg-blue-600 text-white rounded-lg"
>
Voltar para Upload
</button>
</div>
</Card>
</div>
);
if (!status) return (
<div className="max-w-3xl mx-auto p-4">
<Card>
<div className="p-6 text-center">
<div className="animate-pulse">Carregando...</div>
</div>
</Card>
</div>
);
return (
<div className="max-w-3xl mx-auto p-4">
<Card>
<div className="p-6">
<h2 className="text-2xl font-bold mb-4">Status da Validação</h2>
<div className="space-y-4">
<div>
<p className="text-sm text-gray-500">Arquivo</p>
<p className="font-medium">{status.fileName}</p>
</div>
<div>
<p className="text-sm text-gray-500">Status</p>
<p className={`font-medium ${
status.status === 'CONCLUIDO' ? 'text-green-600' :
status.status === 'ERRO' ? 'text-red-600' :
'text-blue-600'
}`}>
{status.status === 'PENDENTE' ? 'Em fila de processamento' :
status.status === 'PROCESSANDO' ? 'Processando...' :
status.status === 'CONCLUIDO' ? 'Concluído' :
'Erro ao processar'}
</p>
</div>
{status.status === 'CONCLUIDO' && (
<>
<div>
<p className="text-sm text-gray-500">Checksums</p>
<div className="space-y-1 mt-1 text-xs font-mono">
<p>SHA-256: {status.checksumSha256}</p>
<p>SHA-512: {status.checksumSha512}</p>
<p>MD5: {status.checksumMd5}</p>
</div>
</div>
<div className="pt-4 flex flex-col sm:flex-row gap-3">
<button
onClick={handleDownloadReport}
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700"
>
Baixar Relatório
</button>
<button
onClick={handleViewVerification}
className="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md shadow-sm text-gray-700 bg-white hover:bg-gray-50"
>
Ver Verificação
</button>
</div>
</>
)}
{status.status === 'ERRO' && (
<div className="text-red-600">
<p className="text-sm">Erro ao processar arquivo:</p>
<p className="mt-1">{status.error}</p>
<div className="mt-4">
<button
onClick={() => navigate('/provas/upload')}
className="px-4 py-2 bg-blue-600 text-white rounded-lg"
>
Tentar Novamente
</button>
</div>
</div>
)}
</div>
</div>
</Card>
</div>
);
}