Files
advx/src/components/provas/VerificarProva.tsx
T
2025-04-23 00:12:44 -03:00

251 lines
7.9 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios'; // Importar axios para fazer a requisição
import { format } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import {
Container,
Box,
Typography,
CircularProgress,
Alert,
Paper,
Grid,
Divider,
Button
} from '@mui/material';
// Componente para verificação de provas digitais
export const VerificarProva: React.FC = () => {
const { hash } = useParams<{ hash: string }>();
const [prova, setProva] = useState<any>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
// URL base da API - usar a mesma do ambiente atual
const API_BASE_URL = process.env.REACT_APP_API_URL || '/api';
useEffect(() => {
const fetchProvaDetails = async () => {
try {
setLoading(true);
// Obter informações de conexão do cliente para incluir nos logs
const connectionInfo = {
userAgent: navigator.userAgent,
language: navigator.language,
platform: navigator.platform,
screenWidth: window.screen.width,
screenHeight: window.screen.height,
timestamp: new Date().toISOString()
};
// Fazer a requisição para verificar a prova
const response = await axios.get(`${API_BASE_URL}/provas/verificar/${hash}`, {
headers: {
'Content-Type': 'application/json'
}
});
// Também registrar a verificação separadamente
try {
await axios.post(`${API_BASE_URL}/provas/registrar-verificacao`, {
hash,
verificationContext: connectionInfo
});
} catch (logError) {
console.warn('Erro ao registrar verificação:', logError);
// Não interromper o fluxo principal por erro no log
}
setProva(response.data);
setLoading(false);
} catch (error) {
console.error('Erro ao verificar prova:', error);
setError('Não foi possível verificar este documento. O hash pode ser inválido ou o documento não existe.');
setLoading(false);
}
};
if (hash) {
fetchProvaDetails();
} else {
setError('Hash de verificação não fornecido');
setLoading(false);
}
}, [hash, API_BASE_URL]);
// Renderização condicional com base no estado
if (loading) {
return (
<Container maxWidth="md">
<Box
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="center"
minHeight="70vh"
>
<CircularProgress size={60} />
<Typography variant="h6" mt={2}>
Verificando autenticidade do documento...
</Typography>
</Box>
</Container>
);
}
if (error) {
return (
<Container maxWidth="md">
<Box mt={4}>
<Alert severity="error" variant="filled">
<Typography variant="h6">Verificação Falhou</Typography>
<Typography>{error}</Typography>
</Alert>
<Box mt={2}>
<Button
variant="contained"
color="primary"
onClick={() => window.location.href = '/'}
>
Voltar à página inicial
</Button>
</Box>
</Box>
</Container>
);
}
// Formatação da data para exibição
const formatarData = (dataString: string) => {
try {
const data = new Date(dataString);
return format(data, 'dd/MM/yyyy HH:mm:ss', { locale: ptBR });
} catch (error) {
return 'Data inválida';
}
};
return (
<Container maxWidth="md">
<Box mt={4} mb={4}>
{prova?.verified ? (
<Alert severity="success" variant="filled">
<Typography variant="h6">Documento Verificado com Sucesso</Typography>
<Typography>
Este documento foi validado e sua integridade foi confirmada.
</Typography>
</Alert>
) : (
<Alert severity="warning" variant="filled">
<Typography variant="h6">Verificação Inconclusiva</Typography>
<Typography>
{prova?.message || 'Não foi possível confirmar a integridade deste documento.'}
</Typography>
</Alert>
)}
</Box>
{prova && (
<Paper elevation={3}>
<Box p={3}>
<Typography variant="h5" gutterBottom>
Detalhes do Documento
</Typography>
<Divider sx={{ mb: 2 }} />
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1" fontWeight="bold">
Nome do arquivo:
</Typography>
<Typography gutterBottom>
{prova.prova?.fileName || 'Não disponível'}
</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1" fontWeight="bold">
Tipo:
</Typography>
<Typography gutterBottom>
{prova.prova?.mimeType || 'Não disponível'}
</Typography>
</Grid>
<Grid item xs={12}>
<Typography variant="subtitle1" fontWeight="bold">
Hash SHA256:
</Typography>
<Typography
gutterBottom
sx={{ wordBreak: 'break-all', fontSize: '0.9rem' }}
>
{prova.prova?.checksumSha256 || 'Não disponível'}
</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1" fontWeight="bold">
Data de registro:
</Typography>
<Typography gutterBottom>
{prova.timestamp?.timestamp ?
formatarData(prova.timestamp.timestamp) :
'Não disponível'}
</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1" fontWeight="bold">
Data de verificação:
</Typography>
<Typography gutterBottom>
{formatarData(new Date().toISOString())}
</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1" fontWeight="bold">
IP:
</Typography>
<Typography gutterBottom>
{prova.verificacao?.ip || prova.prova?.metadata?.ipAddress || 'Não disponível'}
</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1" fontWeight="bold">
Porta:
</Typography>
<Typography gutterBottom>
{prova.prova?.metadata?.clientPort ||
prova.prova?.metadata?.connectionInfo?.socketPort ||
prova.prova?.metadata?.userInfo?.ipAddress?.split(':')[1] ||
'Não disponível'}
</Typography>
</Grid>
</Grid>
{prova.prova?.reportPath && (
<Box mt={3} display="flex" justifyContent="center">
<Button
variant="contained"
color="primary"
href={`${API_BASE_URL}/provas/download-report/${prova.prova.checksumSha256}`}
target="_blank"
>
Baixar Relatório Completo
</Button>
</Box>
)}
</Box>
</Paper>
)}
</Container>
);
};
export default VerificarProva;