251 lines
7.9 KiB
TypeScript
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;
|