frontend: fix PublicProvaUpload
Signed-off-by: Rodrigo B. de Sousa Martins <rodrigo@martinsevieira.adv.br>
This commit is contained in:
1 parent
fe54b55af0
commit
59ea762227
1 file changed
+49
-6
@@ -3,6 +3,8 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { useDropzone } from 'react-dropzone';
|
import { useDropzone } from 'react-dropzone';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
// Página pública: NÃO requer autenticação do usuário
|
||||||
|
|
||||||
export function ClientProvaUpload() {
|
export function ClientProvaUpload() {
|
||||||
const [file, setFile] = useState<File | null>(null);
|
const [file, setFile] = useState<File | null>(null);
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
@@ -43,9 +45,31 @@ export function ClientProvaUpload() {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Validação extra do arquivo antes do upload
|
||||||
|
function validateFile(file: File | null): string | null {
|
||||||
|
if (!file) return 'Nenhum arquivo selecionado.';
|
||||||
|
const allowedTypes = [
|
||||||
|
'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf'
|
||||||
|
];
|
||||||
|
if (!allowedTypes.includes(file.type)) {
|
||||||
|
return 'Tipo de arquivo não suportado. Use JPG, PNG, GIF, WEBP ou PDF.';
|
||||||
|
}
|
||||||
|
if (file.size > 10 * 1024 * 1024) {
|
||||||
|
return 'Arquivo excede o tamanho máximo de 10MB.';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const onDrop = useCallback(async (acceptedFiles: File[]) => {
|
const onDrop = useCallback(async (acceptedFiles: File[]) => {
|
||||||
if (acceptedFiles.length > 0) {
|
if (acceptedFiles.length > 0) {
|
||||||
const selectedFile = acceptedFiles[0];
|
const selectedFile = acceptedFiles[0];
|
||||||
|
const validationError = validateFile(selectedFile);
|
||||||
|
if (validationError) {
|
||||||
|
toast.error(validationError);
|
||||||
|
setFile(null);
|
||||||
|
setFilePreview(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setFile(selectedFile);
|
setFile(selectedFile);
|
||||||
|
|
||||||
// Criar preview para imagens
|
// Criar preview para imagens
|
||||||
@@ -77,6 +101,12 @@ export function ClientProvaUpload() {
|
|||||||
toast.error('Por favor, selecione um arquivo primeiro');
|
toast.error('Por favor, selecione um arquivo primeiro');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Validação extra antes do envio
|
||||||
|
const validationError = validateFile(file);
|
||||||
|
if (validationError) {
|
||||||
|
toast.error(validationError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setUploading(true);
|
setUploading(true);
|
||||||
setUploadProgress(0);
|
setUploadProgress(0);
|
||||||
@@ -120,7 +150,7 @@ export function ClientProvaUpload() {
|
|||||||
// Adicionar timestamp preciso do cliente
|
// Adicionar timestamp preciso do cliente
|
||||||
formData.append('client_timestamp', new Date().toISOString());
|
formData.append('client_timestamp', new Date().toISOString());
|
||||||
|
|
||||||
// Criar simulação de progresso
|
// Simulação de progresso
|
||||||
const progressInterval = setInterval(() => {
|
const progressInterval = setInterval(() => {
|
||||||
setUploadProgress(prev => {
|
setUploadProgress(prev => {
|
||||||
if (prev >= 95) {
|
if (prev >= 95) {
|
||||||
@@ -131,10 +161,18 @@ export function ClientProvaUpload() {
|
|||||||
});
|
});
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
const response = await fetch('/api/provas/upload', {
|
// Upload sem autenticação (página pública)
|
||||||
|
let response: Response;
|
||||||
|
try {
|
||||||
|
response = await fetch('/api/provas/upload', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
});
|
});
|
||||||
|
} catch (networkError) {
|
||||||
|
clearInterval(progressInterval);
|
||||||
|
setUploadProgress(0);
|
||||||
|
throw new Error('Erro de conexão. Verifique sua internet e tente novamente.');
|
||||||
|
}
|
||||||
|
|
||||||
clearInterval(progressInterval);
|
clearInterval(progressInterval);
|
||||||
setUploadProgress(100);
|
setUploadProgress(100);
|
||||||
@@ -155,9 +193,14 @@ export function ClientProvaUpload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ler o corpo da resposta
|
// Ler o corpo da resposta
|
||||||
const result = await response.json();
|
let result: any;
|
||||||
|
try {
|
||||||
|
result = await response.json();
|
||||||
|
} catch {
|
||||||
|
throw new Error('Resposta inesperada do servidor.');
|
||||||
|
}
|
||||||
|
|
||||||
if (result.id) {
|
if (result && result.id) {
|
||||||
toast.success('Arquivo enviado com sucesso!');
|
toast.success('Arquivo enviado com sucesso!');
|
||||||
// Navegar para a página de status
|
// Navegar para a página de status
|
||||||
navigate(`/public/provas/status/${result.id}`);
|
navigate(`/public/provas/status/${result.id}`);
|
||||||
@@ -165,10 +208,10 @@ export function ClientProvaUpload() {
|
|||||||
throw new Error('ID do documento não encontrado na resposta');
|
throw new Error('ID do documento não encontrado na resposta');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error('Erro detalhado no upload:', error);
|
console.error('Erro detalhado no upload:', error);
|
||||||
setError(error.message || 'Erro ao enviar arquivo. Por favor, tente novamente.');
|
setError(error.message || 'Erro ao enviar arquivo. Por favor, tente novamente.');
|
||||||
toast.error('Falha no upload: ' + error.message);
|
toast.error('Falha no upload: ' + (error.message || 'Erro desconhecido'));
|
||||||
} finally {
|
} finally {
|
||||||
setUploading(false);
|
setUploading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user