Files
InflavioApps/src/App.jsx
T

260 lines
8.5 KiB
React

import React, { useState } from 'react';
import {
ShieldCheck,
ArrowRight,
RotateCcw,
AlertCircle,
Sparkles,
Lock,
Loader2,
MessageSquare,
Bookmark
} from 'lucide-react';
import Header from './components/Header';
import SecurityBadge from './components/SecurityBadge';
import UploadZone from './components/UploadZone';
import PasswordInput from './components/PasswordInput';
import CertificateInfo from './components/CertificateInfo';
import OutputFiles from './components/OutputFiles';
import OpenSslReference from './components/OpenSslReference';
import AppWPP from './components/wpp/AppWPP';
import CustomerPortal from './components/portal/CustomerPortal';
import AppLockScreen from './components/AppLockScreen';
import { convertPfx } from './utils/certConverter';
export default function App() {
const [isUnlocked, setIsUnlocked] = useState(() => {
return (
sessionStorage.getItem('inflavio_app_authenticated') === 'true' ||
localStorage.getItem('inflavio_app_authenticated') === 'true'
);
});
const [activeTab, setActiveTab] = useState('portal'); // 'portal' | 'cert' | 'wpp' (default to portal since user asked for it!)
const [file, setFile] = useState(null);
const [arrayBuffer, setArrayBuffer] = useState(null);
const [baseName, setBaseName] = useState('certificado');
const [password, setPassword] = useState('');
const [isConverting, setIsConverting] = useState(false);
const [conversionResult, setConversionResult] = useState(null);
const [errorMessage, setErrorMessage] = useState('');
const handleUnlockApp = () => {
setIsUnlocked(true);
};
const handleLockApp = () => {
sessionStorage.removeItem('inflavio_app_authenticated');
localStorage.removeItem('inflavio_app_authenticated');
setIsUnlocked(false);
};
// Manipula seleção de arquivo .pfx
const handleFileSelected = (selectedFile) => {
setFile(selectedFile);
setConversionResult(null);
setErrorMessage('');
// Extrai nome base sem a extensão
const nameWithoutExt = selectedFile.name.replace(/\.[^/.]+$/, '');
setBaseName(nameWithoutExt || 'certificado');
// Lê os bytes brutos do arquivo
const reader = new FileReader();
reader.onload = (e) => {
setArrayBuffer(e.target.result);
};
reader.onerror = () => {
setErrorMessage('Falha ao ler o arquivo selecionado no seu computador.');
};
reader.readAsArrayBuffer(selectedFile);
};
// Limpa tudo para recomeçar
const handleFileCleared = () => {
setFile(null);
setArrayBuffer(null);
setPassword('');
setConversionResult(null);
setErrorMessage('');
setBaseName('certificado');
};
// Executa a conversão criptográfica
const handleConvert = () => {
if (!arrayBuffer) {
setErrorMessage('Por favor, selecione um arquivo de certificado .pfx primeiro.');
return;
}
setIsConverting(true);
setErrorMessage('');
// Executa em pequeno timeout para permitir renderizar o estado de carregamento
setTimeout(() => {
try {
const result = convertPfx(arrayBuffer, password);
if (result.success) {
setConversionResult(result);
setErrorMessage('');
} else {
setConversionResult(null);
setErrorMessage(result.error);
}
} catch (err) {
setConversionResult(null);
setErrorMessage('Ocorreu um erro inesperado ao converter: ' + (err.message || ''));
} finally {
setIsConverting(false);
}
}, 80);
};
if (!isUnlocked) {
return <AppLockScreen onUnlock={handleUnlockApp} />;
}
return (
<div className="app-layout">
{/* Barra de Navegação Superior com Alternador de Apps */}
<Header
activeTab={activeTab}
onSelectTab={setActiveTab}
onLockApp={handleLockApp}
/>
{/* Conteúdo Principal Dinâmico */}
<main className="main-content">
{activeTab === 'portal' && (
/* Central de Acessos */
<CustomerPortal />
)}
{activeTab === 'cert' && (
/* Conversor de Certificados PFX */
<div className="container">
{/* Banner de Segurança & Privacidade */}
<SecurityBadge />
{/* Card Principal de Conversão */}
<section className="card-converter">
<div className="card-header-bar">
<div className="card-header-title">
<Sparkles size={20} className="text-cyan" />
<h2>Conversão de Certificado Digital (.pfx)</h2>
</div>
<span className="step-badge">Etapa 1 de 2</span>
</div>
{/* Zona de Upload / Drag & Drop */}
<UploadZone
file={file}
onFileSelected={handleFileSelected}
onFileCleared={handleFileCleared}
/>
{/* Campo de Senha (habilitado quando há arquivo) */}
{file && (
<div className="form-controls-wrapper">
<PasswordInput
password={password}
onChange={setPassword}
onSubmit={handleConvert}
disabled={isConverting}
/>
{/* Botões de Ação */}
<div className="actions-bar">
<button
type="button"
className="btn-convert"
onClick={handleConvert}
disabled={isConverting}
>
{isConverting ? (
<>
<Loader2 size={18} className="animate-spin" />
<span>Processando Criptografia...</span>
</>
) : (
<>
<Lock size={18} />
<span>Converter para .CRT, .PEM e .KEY</span>
<ArrowRight size={18} />
</>
)}
</button>
<button
type="button"
className="btn-reset"
onClick={handleFileCleared}
disabled={isConverting}
title="Limpar e selecionar outro arquivo"
>
<RotateCcw size={16} />
<span>Limpar</span>
</button>
</div>
</div>
)}
{/* Mensagem de Erro amigável */}
{errorMessage && (
<div className="alert-error-box">
<AlertCircle size={20} />
<div className="alert-error-text">
<strong>Atenção:</strong> {errorMessage}
</div>
</div>
)}
</section>
{/* Exibição dos Resultados após conversão */}
{conversionResult && (
<section className="results-container">
{/* Metadados e Validade do Certificado */}
<CertificateInfo metadata={conversionResult.metadata} />
{/* Arquivos Gerados com Abas, Cópia e Download */}
<OutputFiles
results={conversionResult}
baseName={baseName}
metadata={conversionResult.metadata}
/>
{/* Referência Técnica dos Comandos OpenSSL equivalentes */}
<OpenSslReference baseName={baseName} />
</section>
)}
</div>
)}
{activeTab === 'wpp' && (
/* Aplicativo WPPConnect Integrado */
<div className="wpp-view-wrapper">
<AppWPP />
</div>
)}
</main>
{/* Rodapé Informativo */}
<footer className="footer">
<div className="footer-content">
<p>
{activeTab === 'portal' && 'InflavioApps — Central de Acessos C2 Sistemas.'}
{activeTab === 'cert' && 'InflavioApps — Conversão PKCS#12 / X.509 em conformidade com padrões ICP-Brasil e OpenSSL.'}
{activeTab === 'wpp' && 'InflavioApps — Gerenciador de Sessões WPPConnect integrado ao portal.'}
</p>
<div className="footer-links">
<span className="footer-shield">
<ShieldCheck size={14} /> 100% no cliente (Executa em qualquer navegador)
</span>
</div>
</div>
</footer>
</div>
);
}