class PDFComplianceAnalyzer { constructor() { this.fileInput = document.getElementById('file-upload'); this.loadingElement = document.getElementById('loading'); this.resultsContainer = document.getElementById('analysis-results'); this.reportContainer = document.getElementById('compliance-report'); this.reportContent = document.querySelector('.report-content'); this.progressContainer = document.getElementById('progress-container'); this.progressBar = document.getElementById('progress-bar'); this.toastElement = document.getElementById('toast'); this.initializeEventListeners(); this.initializeThemeToggle(); } initializeEventListeners() { this.fileInput.addEventListener('change', (e) => this.handleFileChange(e)); this.setupDragAndDrop(); // Keyboard navigation document.addEventListener('keydown', (e) => { if (e.key === 'Escape') this.closeToast(); }); } initializeThemeToggle() { const themeToggle = document.getElementById('theme-toggle'); const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; document.body.classList.toggle('dark-theme', prefersDark); themeToggle.addEventListener('click', () => { document.body.classList.toggle('dark-theme'); this.showToast('Tema alterado'); }); } setupDragAndDrop() { const uploadArea = document.querySelector('.upload-area'); ['dragenter', 'dragover'].forEach(eventName => { uploadArea.addEventListener(eventName, (e) => { e.preventDefault(); uploadArea.classList.add('drag-over'); }); }); ['dragleave', 'drop'].forEach(eventName => { uploadArea.addEventListener(eventName, (e) => { e.preventDefault(); uploadArea.classList.remove('drag-over'); }); }); uploadArea.addEventListener('drop', (e) => { const files = Array.from(e.dataTransfer.files); if (files.length > 0) { this.validateAndProcessFile(files[0]); } }); } handleFileChange(e) { const file = e.target.files[0]; if (file) { this.validateAndProcessFile(file); } } validateAndProcessFile(file) { if (file.type !== 'application/pdf') { this.showToast('Por favor, envie apenas arquivos PDF.', 'error'); return; } if (file.size > 10 * 1024 * 1024) { this.showToast('O arquivo excede o limite de 10MB.', 'error'); return; } this.analyzePDF(file); } async analyzePDF(file) { this.showLoading(true); this.showSkeleton(); this.clearResults(); try { await this.simulateFileUpload(file); await this.validatePDF(file); const report = await this.generateComplianceReport(file); this.displayResults(report); this.showToast('Análise concluída com sucesso!', 'success'); } catch (error) { this.showError(error.message); this.showToast(error.message, 'error'); } finally { this.showLoading(false); this.hideSkeleton(); } } simulateFileUpload(file) { return new Promise((resolve) => { this.progressContainer.classList.remove('hidden'); let progress = 0; const interval = setInterval(() => { progress += 10; this.progressBar.style.width = `${progress}%`; if (progress >= 100) { clearInterval(interval); setTimeout(() => { this.progressContainer.classList.add('hidden'); resolve(); }, 200); } }, 100); }); } showSkeleton() { const template = document.getElementById('skeleton-template'); const skeleton = template.content.cloneNode(true); this.resultsContainer.appendChild(skeleton); } hideSkeleton() { const skeleton = document.querySelector('.skeleton-loader'); if (skeleton) skeleton.remove(); } showToast(message, type = 'info') { this.toastElement.textContent = message; this.toastElement.className = `toast toast-${type}`; this.toastElement.classList.remove('hidden'); setTimeout(() => this.closeToast(), 3000); } closeToast() { this.toastElement.classList.add('hidden'); } async validatePDF(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => { const content = new Uint8Array(e.target.result); const header = content.slice(0, 4); const isPDF = String.fromCharCode(...header) === '%PDF'; if (!isPDF) { reject(new Error('O arquivo não é um PDF válido.')); } resolve(true); }; reader.onerror = () => reject(new Error('Erro ao ler o arquivo.')); reader.readAsArrayBuffer(file); }); } async generateComplianceReport(file) { await new Promise(resolve => setTimeout(resolve, 1500)); return { status: 'compliant', confidence: 92.5, details: { format: 'Válido', version: 'PDF 1.7', pages: 1, signature: 'Presente e válida', metadata: 'Completo', accessibility: 'Conforme' }, checks: [ { name: 'Estrutura do documento', status: 'pass', score: 100 }, { name: 'Metadados', status: 'pass', score: 95 }, { name: 'Assinatura digital', status: 'pass', score: 100 }, { name: 'Acessibilidade', status: 'pass', score: 85 } ] }; } displayResults(report) { this.reportContainer.classList.remove('hidden'); const statusClass = report.status === 'compliant' ? 'badge-success' : 'badge-error'; const statusText = report.status === 'compliant' ? 'Conforme' : 'Não conforme'; this.reportContent.innerHTML = `
${key} | ${value} |
---|
${message}