From 512cb4ea7e43bb67aa5e86cb922fb9fb0b54cd7c Mon Sep 17 00:00:00 2001 From: fpereirasilv Date: Thu, 15 Oct 2026 12:05:56 -0300 Subject: [PATCH] feat: initial commit - CertConverter PFX & AppWPP (React) --- .gitignore | 24 + .oxlintrc.json | 8 + Dockerfile | 32 + README.md | 72 + docker-compose.yml | 9 + index.html | 14 + nginx.conf | 37 + package-lock.json | 1442 +++++++++++++++ package.json | 26 + public/.htaccess | 20 + public/favicon.svg | 1 + public/icons.svg | 24 + public/web.config | 32 + src/App.css | 1 + src/App.jsx | 243 +++ src/assets/hero.png | Bin 0 -> 13057 bytes src/assets/react.svg | 1 + src/assets/vite.svg | 1 + src/components/CertificateInfo.jsx | 147 ++ src/components/Header.jsx | 64 + src/components/HostGuideModal.jsx | 225 +++ src/components/OpenSslReference.jsx | 84 + src/components/OutputFiles.jsx | 200 ++ src/components/PasswordInput.jsx | 47 + src/components/SecurityBadge.jsx | 17 + src/components/UploadZone.jsx | 102 + src/components/wpp/AppWPP.jsx | 566 ++++++ src/components/wpp/ModalConfirm.jsx | 71 + src/components/wpp/ModalListSessions.jsx | 95 + src/components/wpp/ModalQRCode.jsx | 120 ++ src/components/wpp/ModalServer.jsx | 154 ++ src/components/wpp/ModalSession.jsx | 135 ++ src/components/wpp/ModalSettings.jsx | 143 ++ src/components/wpp/WppSessionCard.jsx | 156 ++ src/index.css | 2150 ++++++++++++++++++++++ src/main.jsx | 10 + src/utils/appWppStorage.js | 72 + src/utils/certConverter.js | 199 ++ src/utils/downloadHelper.js | 93 + src/utils/initialWppData.json | 89 + src/utils/wppConnectApi.js | 217 +++ vite.config.js | 7 + 42 files changed, 7150 insertions(+) create mode 100644 .gitignore create mode 100644 .oxlintrc.json create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 index.html create mode 100644 nginx.conf create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/.htaccess create mode 100644 public/favicon.svg create mode 100644 public/icons.svg create mode 100644 public/web.config create mode 100644 src/App.css create mode 100644 src/App.jsx create mode 100644 src/assets/hero.png create mode 100644 src/assets/react.svg create mode 100644 src/assets/vite.svg create mode 100644 src/components/CertificateInfo.jsx create mode 100644 src/components/Header.jsx create mode 100644 src/components/HostGuideModal.jsx create mode 100644 src/components/OpenSslReference.jsx create mode 100644 src/components/OutputFiles.jsx create mode 100644 src/components/PasswordInput.jsx create mode 100644 src/components/SecurityBadge.jsx create mode 100644 src/components/UploadZone.jsx create mode 100644 src/components/wpp/AppWPP.jsx create mode 100644 src/components/wpp/ModalConfirm.jsx create mode 100644 src/components/wpp/ModalListSessions.jsx create mode 100644 src/components/wpp/ModalQRCode.jsx create mode 100644 src/components/wpp/ModalServer.jsx create mode 100644 src/components/wpp/ModalSession.jsx create mode 100644 src/components/wpp/ModalSettings.jsx create mode 100644 src/components/wpp/WppSessionCard.jsx create mode 100644 src/index.css create mode 100644 src/main.jsx create mode 100644 src/utils/appWppStorage.js create mode 100644 src/utils/certConverter.js create mode 100644 src/utils/downloadHelper.js create mode 100644 src/utils/initialWppData.json create mode 100644 src/utils/wppConnectApi.js create mode 100644 vite.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..1255078 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "oxc"], + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..71f9b6f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# Estágio 1: Build da aplicação React +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copia manifestos de dependência +COPY package*.json ./ + +# Instalação limpa +RUN npm ci + +# Copia código fonte +COPY . . + +# Compila para produção +RUN npm run build + +# Estágio 2: Servidor Web Nginx ultra-leve +FROM nginx:alpine + +# Remove configuração padrão +RUN rm -rf /usr/share/nginx/html/* + +# Copia arquivos compilados do builder +COPY --from=builder /app/dist /usr/share/nginx/html + +# Copia arquivo de configuração do Nginx +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..a7ea9d1 --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# Suíte Web: Conversor de Certificados PFX & AppWPP (WhatsApp Manager) + +Aplicação web completa desenvolvida em **React.js + Vite**, integrando duas soluções essenciais em uma única interface moderna, autônoma e de alta performance: + +1. 🔒 **Conversor de Certificados Digitais (.PFX):** + Converte certificados do formato PKCS#12 (`*.pfx` ou `*.p12`) para **`*.crt`**, **`*.pem`** e **`*.key`**, reproduzindo 100% da lógica dos comandos nativos do OpenSSL no navegador (100% Client-Side). +2. 💬 **AppWPP (Gerenciador de Sessões WPPConnect):** + Migrado da versão Electron (`D:\Flavio\Projetos\AppWPP`) para **React.js puro**, permitindo gerenciar servidores WPPConnect, iniciar sessões, escanear QR Codes em tempo real, consultar status, gerar tokens e sincronizar dados com backup JSON ou Supabase. + +--- + +## 🚀 Como Executar Localmente + +### 1. Iniciar o Servidor de Desenvolvimento +```bash +cd C:\Openssl\bin\cert-converter-app +npm run dev +``` +Acesse no navegador: +* 💻 **No computador local:** [http://localhost:5173](http://localhost:5173) +* 📱 **Na rede local:** `http://192.168.0.3:5173` + +### 2. Gerar Versão de Produção (Build) +```bash +npm run build +``` +A pasta estática e otimizada **`dist/`** será gerada pronta para hospedar. + +--- + +## 🛠️ Recursos das Aplicações + +### 1. Conversor de Certificados Digitais (.PFX) +- **Equivalência OpenSSL:** + - **`*.crt`**: `openssl pkcs12 -in cert.pfx -clcerts -nokeys -out cert.crt` *(Apenas o certificado folha do cliente)*. + - **`*.pem`**: `openssl pkcs12 -in cert.pfx -nokeys -out cert.pem` *(Cadeia completa pública)*. + - **`*.key`**: `openssl pkcs12 -in cert.pfx -nocerts -nodes -out cert.key` *(Chave privada pronta para uso imediato em Nginx, Apache, IIS e NF-e)*. +- **Inspeção de Metadados:** Titular, CNPJ/CPF detectado automaticamente, AC Emissora, Validade e Dias Restantes, Serial e Thumbprints SHA-1/SHA-256. +- **Exportação:** Copiar código com 1 clique, download individual ou **Baixar Pacote (.ZIP)** completo. + +### 2. AppWPP (Gerenciador WPPConnect) +- **Gerenciamento de Servidores:** Cadastro de múltiplos servidores WPPConnect (URL Base e Secret Key) com teste de conexão. +- **Sessões do WhatsApp:** + - Iniciar / Fechar / Desconectar sessões. + - Consulta de status em tempo real (`connected`, `qr`, `connecting`, `disconnected`). + - Modal interativo de **QR Code com atualização automática** e fechamento instantâneo após a leitura do celular. + - Geração e cópia de Token JWT de autenticação. + - Limpeza de dados de sessão no servidor. + - Inicialização em lote de todas as sessões pendentes. + - Listagem de todas as sessões registradas diretamente no servidor. +- **Persistência & Backup:** + - Armazenamento local no navegador (`localStorage`) com carga automática dos dados pré-existentes (`appwpp-data.json`). + - Exportação e importação de backups em formato JSON. + - Configuração opcional de integração com Supabase. + +--- + +## 🌐 Guia de Hospedagem em Produção + +| Plataforma | Procedimento | +| :--- | :--- | +| **Vercel** *(Recomendado)* | Execute `npx vercel` na pasta do projeto ou conecte ao repositório GitHub. | +| **Netlify** | Execute `npm run build` e arraste a pasta `dist` em [app.netlify.com/drop](https://app.netlify.com/drop). | +| **GitHub Pages** | Execute `npm run deploy` utilizando o pacote `gh-pages`. | +| **Docker / Linux** | Execute `docker compose up -d --build` (inicia na porta 8080 com Nginx otimizado). | +| **Windows Server (IIS)** | Execute `npm run build` e copie a pasta `dist` para o diretório do site no IIS (arquivo `web.config` já incluso). | +| **Apache / cPanel** | Suba os arquivos da pasta `dist` para `public_html` (arquivo `.htaccess` já incluso). | + +--- + +## 📄 Licença +Distribuído sob a licença MIT. Livre para uso pessoal e comercial. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..094bfd6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +services: + cert-converter: + build: . + container_name: cert-converter-app + restart: unless-stopped + ports: + - "8080:80" + environment: + - NODE_ENV=production diff --git a/index.html b/index.html new file mode 100644 index 0000000..c5b29d0 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + + CertConverter PFX - Conversor de Certificados Digitais (.pfx para .crt, .pem, .key) + + + +
+ + + diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..f03400b --- /dev/null +++ b/nginx.conf @@ -0,0 +1,37 @@ +server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html index.htm; + + # Compressão Gzip + gzip on; + gzip_vary on; + gzip_min_length 10240; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/javascript; + gzip_disable "MSIE [1-6]\."; + + # Headers de Segurança + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options "nosniff"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + + # SPA Routing (Single Page Application) + location / { + try_files $uri $uri/ /index.html; + } + + # Cache de assets estáticos + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, no-transform"; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..36486c8 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1442 @@ +{ + "name": "cert-converter-app", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cert-converter-app", + "version": "0.0.0", + "dependencies": { + "jszip": "^3.10.2", + "lucide-react": "^1.57.0", + "node-forge": "^1.4.0", + "react": "^19.2.8", + "react-dom": "^19.2.8" + }, + "devDependencies": { + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.7", + "@vitejs/plugin-react": "^6.1.1", + "oxlint": "^1.81.0", + "vite": "^8.3.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.154.0.tgz", + "integrity": "sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.88.0.tgz", + "integrity": "sha512-k6Fgkf86ubfeH4GvqYsRolfuVAp0pfYVZvifSlXNHPdMaWUOfxUrmLEeDD7hF6U2oJuhsVxhSWq86/xCJ+9MmA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.88.0.tgz", + "integrity": "sha512-AsIyhl9o1ejwtac7NMbhKpMdSml6NWR0ljKjZERxC8OHYDAW8o/Om9n1QHVLi4VCEUo42Zte2/Op9kyoGpJZMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.88.0.tgz", + "integrity": "sha512-qgBjB7eEKcCB4RqjXGuoSZq74g0wD09fWFJ+HWcCJcKaga8TeUHtb+BY0SsxdleSLBgx4RZ7qmgo0EzqEq7JoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.88.0.tgz", + "integrity": "sha512-sCz3X5Mw/xdzEzn4fsCt1Iq8NKJnGNfhR+b9B5k+4DysYAHsmIhYoocnBPiQ9kvY3+pUun2A0Z8Vtun/Nv6YoQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.88.0.tgz", + "integrity": "sha512-xTOdYOIqCufgIj0knvxu86FBfovP6QBiD7ngNva01gb8xPQCD5gXkE5APGczH35zStim1O3zqvFbLQmY85xXRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.88.0.tgz", + "integrity": "sha512-BLadtw88NdYJBrAtC1dYzrPfSP2d5zgx6iuZycdD0YmZBJ2Nqbit9Z4PSaIb6gxK25dweArGMPbOmq/0ugwUPg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.88.0.tgz", + "integrity": "sha512-wILSczl/DaZsCcf7j7tvNbssp8hxEHIJxrv4j7+JjI3TAL1U/JTWbeUtoJJC/vo8+2hkTmHLYoKJjmiNbijdXw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.88.0.tgz", + "integrity": "sha512-jutT2Hy8JCuZuMwIFHo2HtyxfOfBJHyQxlBHBK1SL9W2f8n/WhjAP0FnDMz9d/mjhv9+QA0mx5AdQ9fDjsrFFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.88.0.tgz", + "integrity": "sha512-8N8iGV9hh4Lkeuq7QsEkjoXNRRflqR1G2qyoGYXcA0k5qllrdqmfylKEXyHIVERxqNDyMO4StqDQ0uLxXcBQAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.88.0.tgz", + "integrity": "sha512-5ydcQt3znNQ/rGEWYRvpS2cK9+T18P2VYgnyJ+eloEAwi9YUmsXy5VGrRqNWIK6qzWwHGnEE3ojVqqQNo+f0hA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.88.0.tgz", + "integrity": "sha512-iGx0uvFT54b/5DPJdEBCxYIrVB3v0uTy+JhRh3CyEp8/22BXDkG8rffkFwREdLsdj9mOrPbJYVOZw8ipcBuzjw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.88.0.tgz", + "integrity": "sha512-Wt47mKMWelVjRjuR7BCFxXkB0m79K1sTEbqMHRWciKUgo5iv7sWsF4RXSOyFYHD9zerNrkRZblnN273rhwOA1Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.88.0.tgz", + "integrity": "sha512-g3L12KCS4+1gtUt3RbJ4F+Yxx4LNmmZLEPfhd8rAHEJjJk2lAgNfnjGoP/phJyhG5WS6VbNYbJtadJelNfvTMA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.88.0.tgz", + "integrity": "sha512-og/XHVDOD9ZJgRiZkT9DgzQd4sr+JZW7e4l17Q/jVMZiIbeEd4uIu9iAoUbTF1gIvVZoRc4QDOxyVUvQGp4WHg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.88.0.tgz", + "integrity": "sha512-EmhBsp+xuKb6YbZNEMLBo80Xw71AZOIm18do8ni/GLX/Lw1XzNhVYpbxO1KasYtoAvrGtCOdCPULRlIE0bPbTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.88.0.tgz", + "integrity": "sha512-DBUcx/KwYdg1DAz+G01P/GFv512J04EsZadbHptx2FTpWT/MWRg21ZToNHt9pnsfQRBQ3et/g+vqzbvrdAVbuA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.88.0.tgz", + "integrity": "sha512-xeVd0n4XG5HvynxfYvXi6uB+JvZbVZataowPS8cYpMbYg9mwE4sSyElFQd4LVJFifq8bRLDSR18XgEildmcXAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.88.0.tgz", + "integrity": "sha512-MA6iOw//amleaz2mVMsZrA7NHlEexjTrhIxSMFCXQi6IUuQO+3Od00GZhr2iCYw6RFzMW36jkKK/WHBXMsoQAw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.88.0.tgz", + "integrity": "sha512-3Sz6rVWe8Dy+ufsXurFN1GX2dX43F/lQMSLelK9gFjiba7nHvLlqlhR5cHlWVnCpSqUY1hN9pyCX9XToe6ve6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.14.tgz", + "integrity": "sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.14.tgz", + "integrity": "sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.14.tgz", + "integrity": "sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.14.tgz", + "integrity": "sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.14.tgz", + "integrity": "sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.14.tgz", + "integrity": "sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.14.tgz", + "integrity": "sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.14.tgz", + "integrity": "sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.14.tgz", + "integrity": "sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.14.tgz", + "integrity": "sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.14.tgz", + "integrity": "sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.14.tgz", + "integrity": "sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.14.tgz", + "integrity": "sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.14.tgz", + "integrity": "sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.14.tgz", + "integrity": "sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.3.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.2.tgz", + "integrity": "sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "oxc-transform-react": "^0.152.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "oxc-transform-react": { + "optional": true + } + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/jszip": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.2.tgz", + "integrity": "sha512-3l+rb15IOWtUhU0H5MFqES/T6Kh7abYwjosBey/vD6hDt8zoEffkSC5Ws5SGtgVw3gBx2NEbhTeSW1+kWkpyTQ==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lucide-react": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.57.0.tgz", + "integrity": "sha512-bXFZEucYhAzLD62Jse76AbTR6LiSLTn3Tqir2f1n8rZrWAdLodYy7jnRZSPIT89dRLk/IseMOUWG82wJtTyTTw==", + "license": "ISC", + "peerDependencies": { + "@types/react": "*", + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-forge": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/oxlint": { + "version": "1.88.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.88.0.tgz", + "integrity": "sha512-uIcFgw8BmqvFRGzH5+r7d2zJMEexwNSrEmM6WQNnGh3VkO0XYTEFoyxyNE6tjKMUib9Cue4XJA2DoWruO5D6aw==", + "dev": true, + "license": "MIT", + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/oxc-project" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.88.0", + "@oxlint/binding-android-arm64": "1.88.0", + "@oxlint/binding-darwin-arm64": "1.88.0", + "@oxlint/binding-darwin-x64": "1.88.0", + "@oxlint/binding-freebsd-x64": "1.88.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.88.0", + "@oxlint/binding-linux-arm-musleabihf": "1.88.0", + "@oxlint/binding-linux-arm64-gnu": "1.88.0", + "@oxlint/binding-linux-arm64-musl": "1.88.0", + "@oxlint/binding-linux-ppc64-gnu": "1.88.0", + "@oxlint/binding-linux-riscv64-gnu": "1.88.0", + "@oxlint/binding-linux-riscv64-musl": "1.88.0", + "@oxlint/binding-linux-s390x-gnu": "1.88.0", + "@oxlint/binding-linux-x64-gnu": "1.88.0", + "@oxlint/binding-linux-x64-musl": "1.88.0", + "@oxlint/binding-openharmony-arm64": "1.88.0", + "@oxlint/binding-win32-arm64-msvc": "1.88.0", + "@oxlint/binding-win32-ia32-msvc": "1.88.0", + "@oxlint/binding-win32-x64-msvc": "1.88.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=7.0.2003", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.30", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.30.tgz", + "integrity": "sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.20", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/react": { + "version": "19.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.1.tgz", + "integrity": "sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.1.tgz", + "integrity": "sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.1" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/rolldown": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.14.tgz", + "integrity": "sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.154.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.14", + "@rolldown/binding-android-arm64": "1.2.14", + "@rolldown/binding-darwin-arm64": "1.2.14", + "@rolldown/binding-darwin-x64": "1.2.14", + "@rolldown/binding-freebsd-x64": "1.2.14", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.14", + "@rolldown/binding-linux-arm64-gnu": "1.2.14", + "@rolldown/binding-linux-arm64-musl": "1.2.14", + "@rolldown/binding-linux-ppc64-gnu": "1.2.14", + "@rolldown/binding-linux-s390x-gnu": "1.2.14", + "@rolldown/binding-linux-x64-gnu": "1.2.14", + "@rolldown/binding-linux-x64-musl": "1.2.14", + "@rolldown/binding-openharmony-arm64": "1.2.14", + "@rolldown/binding-win32-arm64-msvc": "1.2.14", + "@rolldown/binding-win32-x64-msvc": "1.2.14" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "license": "MIT" + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vite": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.4.tgz", + "integrity": "sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.29", + "rolldown": "~1.2.12", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.7.1", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c420740 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "cert-converter-app", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "oxlint", + "preview": "vite preview" + }, + "dependencies": { + "jszip": "^3.10.2", + "lucide-react": "^1.57.0", + "node-forge": "^1.4.0", + "react": "^19.2.8", + "react-dom": "^19.2.8" + }, + "devDependencies": { + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.7", + "@vitejs/plugin-react": "^6.1.1", + "oxlint": "^1.81.0", + "vite": "^8.3.0" + } +} diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..c9f4316 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,20 @@ + + RewriteEngine On + RewriteBase / + RewriteRule ^index\.html$ - [L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /index.html [L] + + +# Compressão Gzip + + AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json + + +# Headers de Segurança + + Header set X-Content-Type-Options "nosniff" + Header set X-Frame-Options "SAMEORIGIN" + Header set X-XSS-Protection "1; mode=block" + diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons.svg b/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/web.config b/public/web.config new file mode 100644 index 0000000..f4186a4 --- /dev/null +++ b/public/web.config @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..97a501e --- /dev/null +++ b/src/App.css @@ -0,0 +1 @@ +/* Estilos globais gerenciados em src/index.css */ diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..106253d --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,243 @@ +import React, { useState } from 'react'; +import { + ShieldCheck, + ArrowRight, + RotateCcw, + AlertCircle, + Sparkles, + Lock, + Loader2, + MessageSquare +} 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 HostGuideModal from './components/HostGuideModal'; +import AppWPP from './components/wpp/AppWPP'; +import { convertPfx } from './utils/certConverter'; + +export default function App() { + const [activeTab, setActiveTab] = useState('cert'); // 'cert' | 'wpp' + 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 [isHostingGuideOpen, setIsHostingGuideOpen] = useState(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); + }; + + return ( +
+ {/* Barra de Navegação Superior com Alternador de Apps */} +
setIsHostingGuideOpen(true)} + /> + + {/* Conteúdo Principal */} +
+ {activeTab === 'cert' ? ( +
+ {/* Banner de Segurança & Privacidade */} + + + {/* Card Principal de Conversão */} +
+
+
+ +

Conversão de Certificado Digital (.pfx)

+
+ Etapa 1 de 2 +
+ + {/* Zona de Upload / Drag & Drop */} + + + {/* Campo de Senha (habilitado quando há arquivo) */} + {file && ( +
+ + + {/* Botões de Ação */} +
+ + + +
+
+ )} + + {/* Mensagem de Erro amigável */} + {errorMessage && ( +
+ +
+ Atenção: {errorMessage} +
+
+ )} +
+ + {/* Exibição dos Resultados após conversão */} + {conversionResult && ( +
+ {/* Metadados e Validade do Certificado */} + + + {/* Arquivos Gerados com Abas, Cópia e Download */} + + + {/* Referência Técnica dos Comandos OpenSSL equivalentes */} + +
+ )} +
+ ) : ( + /* Aplicativo WPPConnect Integrado */ +
+ +
+ )} +
+ + {/* Rodapé Informativo */} +
+
+

+ {activeTab === 'cert' + ? 'CertConverter Web — Conversão PKCS#12 / X.509 em conformidade com padrões ICP-Brasil e OpenSSL.' + : 'AppWPP Web — Gerenciador de Sessões WPPConnect integrado ao portal de utilitários.'} +

+
+ + • + + 100% no cliente (Executa em qualquer navegador) + +
+
+
+ + {/* Modal com Guia Passo a Passo de Hospedagem */} + setIsHostingGuideOpen(false)} + /> +
+ ); +} diff --git a/src/assets/hero.png b/src/assets/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..02251f4b956c55af2d76fd0788124d7eee2b45eb GIT binary patch literal 13057 zcmV+cGycqpP)V|)f$;Qooc7=_G zlYe)HToTQIc!$)^+J1M1y0*T%w!p~7%ux`!eRhO?c80XDxKQ*R^lUUMnA>6NT^?feoZ8xxvP32D&s-9ow zqjcM}eesrC)NeDmsf)*P7wJ|K!&xP%Zy4iI8lF)Tv2!reW)tCzg_1=PmOwd1SQfxa z8;58t!=z~Ba7CYlNWVG>he8aRPY|+-JmozNhn!#9i#77Aa_Edt$ijyCWL#=~I>~2X zZNrQ8I0=D+NWD4pq=7~(i zhfThMNw|G>g^y9pGzxX7ZSApl@tIxFcs{p#MX{Ax&XZT+cR#U+OWc@S)pkIuI}dzu zH?^Q=<(y&Vq-oxSLfc0Zmq81bjZWf}RnssBaD6}2g-XJHLcN_|*IOu>m|x$nbm(?E zyNy!Zp=RroS;?Vg*kmoJYBi!n5{_^@rA!)=t#a^;N$8GL!*DsQb}`yvEuX!G@||An znOfUZAevPrkV_qjl|<~3QRZzG&h@C9Y5z zqpNH4xqbF_InIPh)kX}Vn^5kyed|mOuq+2>M;v~KO37a#yrEn3XDqtOl=rc6_KZ!; zreo)DFVB4|>1Zd(bvMI%8uM;3!)YMYu&cG?(PE!B~y@3yKBMt|R zAf=I16tFwPsl)!jDqvYkLHaAQ+f@W1m6F5aZvwhm4JL z{_l)@b;)mDSzle2gyFP5-r1x-5X{G}ot%VyWP@vEW80!Q=f%RTfpg>B*TA^pyWYUQ z<=xPtz}WcZ!;rFl4m1D&FFHv?K~#9!?A%+fn=lXt;9!Fc#kQ;zk~gZFsH z8e5iu@c_pzX&qb8&Dum*oXwB+fm6l6gFfC|o*wgEiy6tw~&co z9Vd_4)P%wP-KwQW7|lN-znGK#?N+j24U=$982myIBM+vsiKsc*@4-rwJxuAaHKna6 zT3wi!C~a4ZKH03qU}_1bKyx0&$CaK7_%Z+Kl$)fF5^op zZApQF2TvDav!s|krTjw-8US6ep z%!VmX4luub+fseQz_D9ATJQ?iQQwD}TZz{-yo#l12a%+7bT@E(X-hyaVS-5vuXc#^ zx^w;L21;NphGVoj*{s3f4dme0y2LC=G1-7THd`#z?;tuC{^9k(dM{Rf2GOxg7Jzho z7nSZHl7?M9kdalX`)YgoKEfiae5+;$(OGeN1eqxrv!ZCVKyH>xiyNqfe8xzY8*7)H zQls8KMp)F4D>ED;idMOU^^WhVF@q>ZSmeB0y~qC~|DB648hr%Sh|*T(4q|w2l?m2+ zvBVw3@7+Mz?^Yc#+se6KM;a<=(W-I>k)$-qL2V*t}VaW`;?P4)WqI%maIDq8!oUcSYAD`}wWjkSyAVsnF65#2zQ zZ>(K*TlS(E#4y$4Zq+e^_&}d)q20hCe3!LfLYP%nQpLJ~gM6a1hJlz3)aS<9C9me| zAcmJ#>tOwBy{HoP0Sm1&_(E+S@6 zgBIFUoei8zJmdpiq8q5=OY7t@`)JWxn_&GvKVr=Zdb_pEL_j|=?f;WK^U9Q0efd#K z9q7SfJTl4pmA$jsZ5oK8@O9#!I3Cv-kL)<8SalSsp#dcpvJ}Nz#G6FC0%9|7Fi#8; zGDJXtj!&GljT3*HE@0EE>G8Se&d)*nkqe}-?`3vPl&UqK?xG z!3XJ4M-x`EuQjhBbu?ik-)rmIt=DF_N?TVMP)8Gjn)TZ2V%H|zENbeix}kOxd@0}Q z>)HuH6Ean!uS#~4g2Ne2WsMGel|h%j9*W_quQheG^JqmKhc*RYzp0wKlGjBq2VzY_ zgOv8WC1+%W=W)k)Yp_`8kfE=uiiwOZTXi8Uj9YGr$f@yJcJ;#&-Nq~sJ7anE(@;QN z=~br%7%7`isKStX|7!1?L(apl^QvPKlrHV4S+6tNVQ*R1iGdC~WMNE1$a+=rpQmcB z>wxiLIBvOnm;u*;9Y!kJdy(T4lk|8>JAm(&wEsFIF1$_*{>2ZNd$V6DS=SfrGxAv0 zzKe377JI`&o9Ljr+VnS*EwehA{f&{cKZF(6*MG5!p5MvrFA3ll{fmRG*L@6^cb;o^ z3Wm8c?Sc6$`>~VEWw(c$Y?nRO;2Q$=ulpqPtM^=1IZx;@xK0PgO7rKQ^WHVLwtgUT z%|JF{^f(VH)wLKQ%dYiu2RmchBdxL0-M?wxxul_z*{h6ZZ`>-k(vizs((vW8Lt6Z6 zY;Dt?@JWyN`O`f;&d1Mb?e%9oyRK1ql?EE5XB2(W)|D1~Rx35$H6@6)$F?)7V|zEO zI}fu0-0}8W5=6sg$fPnZ~7=tTudl?Ecb@pxbo)vni%gP-?hL|%*?62C;x6?@E`VRnJv z?fTb;k4x;TS7Cu-z%J}uy}e-pwpLQ17Q@4DC+FCdAmNKklG$`I_pyw7E{fYmw~{Fj zi?6KcVy=Wrel)EB_DWO|0CKmI|13!gBV?X`Ozp7x>?6jr`>Qz=^4ea35!$*f}) zS$i+x_k+@P2q1RFUH^ZTTk7=n?cjfR>hTq3l3SY~#w+I8SSutXGyhw;Ws~=zMQ%Vc z>$On~47Ut?P*_!TOQ&PFmLAyJieB2X4_Fd_!WxI-AY`q1Lc-oK?+qcOTzlQ?@~x@OT}*9jTVNfl@3rGvZpWI=eKg>T zZb@6YWz)J=IhP7CF|c?G62vMEG%#U}?#86$0jR4sG~i(jRd#jmn`7b(O#?N;3a;1t zhXLssmUwGhp79luw#(*V8WL0|8+E z6=YZ_O@er~$LrD_PYGc(kJgB=;yw#+Z3X6LDUZ(NcwN=B-hjdiHm!JFar%m{(5bEW z@@_VEtG$5;`EJZ|OkJ@l&G9n((w@uNFwmU%bG|s#TbcJJos!{e+bjCjrCq_}LcN!UFgKtgg7siV*7# z!}1whTRRi*-avJPu->C}Z8EiuK$#886+H_#_!btv+rsiBbv2jAJvJ+O0{#}y(%L3H zfjU-kq_-L@2XrL*ae{{qYJkD{@dw%*bkh2P&YS-0!Xt!PRz7KHV0+~j(t9W8lAVWR zt@B*DgURgEz4>WuN>o?_iKcw$?k{||Pg7{Q2o4|VmJ)mg?{VQJA<}zEr^YAAS zgGm5RT4T3p)U;yz-tfBO^kw8?IoG!IVmc+Z3m#}AOQ?5MRa>)OcU!$N^_+yK6ayn? zK>~WK0!#ysuj^oNLakm)Zvu+J)OSubX^kv!c*xgdIvs;kln!rgG4*uZ;w0mQQO4XD zO9P{GNdv!=cQ(CAL{S(%KtuV^zC&Q{%g)PoXnp^gn^>c*`E>$hLYg2HjnbVGtWLa{7zHdG1jT@B{|Dm16 z7K2(jsfG+m*Zxof)iXxu+!H5Mo-0$pkyV3VV4B@Qms46M zuBxGRV@HxU7Wwx-6CB zaU*HO<_qn$5GH>&@?nRy1{z zkik!sLfWQ)r#75)vVwCBU*r_)Q6mp?!j85{#Xqse)ApRdE$V0%I0*~e(_{)5H)`Mk z#rExC>yjhZxuL@|+#v4#<Axw$+VpV zuT;!2Vww$je$DpAW`$FX_Ab|Ip%$;&T$-lW8jS~B$>G}rd>eQG+$h9lQx4Mx0w={m zx9?T6VU`>sR}XClkAhHEShOUe8awiq zmizhL+}5UKs3}6~It7vBTig9dfQ2Q8coo+Miiaw7n~>4ybv2Ptt0^^=VqX(t*Yya9 zr`FxxFX8(v*H=+uJ#JJWIB2A(==HDYx~^zZ2nu?2`}|Wsa*f3h3ixc+U|FDtAG$Y! z*lc_7se5Oso-Cgqe0){{!8H4g$3<8!R<6JOurD;((({c$1(pwb>(#TT!sge@4>r2@ zVL7>U`0`nsWAYErezk4(Z!gMI2?UTo{J3Ajo(u4)KYIRd>BRcG4BoS3G0EXyEp@tw z%P7__?A^a>Q&AKL@ayDO9D*Qkc!NHnO9l}kpp_6hXbMppYL(X1L?njdFT|-h2<_$; zAtDZ!1Rf%|yb!qbWKd}%0b`LzBeyNy43|QO(&h2mxQLUL)|0%agVOW)6TV!&Ip^Ls z`PG2cygM8)IecQx=Fc+nqYRo4hS^^-nM_&-y8?EJXUczP=DIw(GkTJdpEdh<_STs{ z|A)4n1GKdE=Wu!!nYoZHcUQ4S&R;oDOKX2lrkdF(mK>hz<$Pp>igjOcvoRIjlN=W8 zu8Gx5(roqn8$>gEE5vy{GiGeW8Tq{vnf3hS-V=$tZkQuftUVuU8o6k&dn=Yg3)6MOIH>nlK^-2+C6BZITr~1@So?NvG#TwL)|~=1YXGMTLpS<)ziK_CSOabe z=cB#5)yz|@0i9dSo?*CX)}UP=s6)B+F@~Em(u@Q(I9J9i_V{LmMu8BfXYMh~*oPP+ z!3~xTv|(>|=n6ZOtT~C@V!z!w%18*8T2t6}U2S##rC)mekBql&VsBX;$~ByGE$oA9 z`0Wzq8p?R{4)$l*on;!cLa}Dh^Xe?owiQZt9nH1fxxh$pN9K%CtOw?u3>85L7rr!d zXs)l{TZ{xXP&U8exz?9cv~dNNibOmt*K4I$?RxqIBZ0(?Mg-9FS{*9Bc49Qc1`=sIF-rye`aNT1G@4NwXcnyc@+bw_mTsR>5< zF<2;X0QesG_pw|TonqVBhRtfqI>ty(SIu&VOXd0CrLlfp+;WH7HYjhqnu^oAY!9cB z=B6#R?Rfz9BP`dJ=@v_?70s3HxQPk+{6Y+lM85f2NF^00*^OcM0~?JOZfR9ZPYF+# zYSs}(_BUYV8{n@2a1hD^SV41bwmi2uztR;PeBgF1F-`9>`zoNss-@3LaF2sjl~>OaaVmp7PNp+UT`6@}gR%uzqHDVeEZ14{Yt?n%JeQm+t(1_u zSc}oj^{b;+rlS|ME%+LjzSI&xu0Bblxo$MJ-J$kJ?Qu_XUXh}*@*-x@ny|}wVM%Lg z3tNB`yvr*}N?ClGL;H2cglcvErIccU3(eP7>@~4nOIcI~-`P8tSQnx=jI&{9)!1}l z;gQ%_h>ZlPSV@o@Azq1R$C6ja5!^ZGh;YRhhxs58qJWo9@Bceac&yy(pET1hnn`~7@}2L0&dfPKYs$ih7m2}R!25!(hxqA(!UIw; zK4+~Jowy3=RNC6nE=ncU{LH5?*9@W24lacJlvCZXB$CYtE@>c+~H zkV=(5I&gb{xn2!~f&fs2NQgAL6`p|kyt6kpWk}iVlqIp(H;ig`{_U9yxs1jzu^ETM z7~)Rg8C-NueqTYP&U8l{DY=Y47cR zOR@U%$KQV{mkRF|4)z9Y^t3K`@p>duY&QLUFeh6VoV`a`$U@)(z!-N*5Cj<11$EZW&hJLX83TO{lJYP74rlDZQPkm@t<=U^I)x@|UnHHkdQlh?!ltZwl92rE;;^ zZuIappj4dhld1}kttYYV-j|KF1Kus zWBnzttD^00%LFK(wrwNragFub6xiV8QE2rm<`&fcR4SLFcdtLxVuN!Aal-g6dE4%k zARZ}|xeo;K{0yf7@9aua%2j5o)CPcIOc6uLHFJOcgtB5owlcNAwyAHc0QB0Dts?c@ zUemG~j_E&W7R%+x-IO4FJl8e&*2Blmp1S#RA|)geVrxvP)NHdYuxi~g&Etn?QdNK8ZDKZ?QFLU?zh30G|t9G>a_X4zk}Ygw<^$7K!GIn(Io$>(d4ODJQ2XSd%jpK zm7>ptl$a3GyB}5-%p4>Q*p#VL^B{yQMuFCM^#l#+N!Ne z5_PrJWB=@Iy+t)H`g1lX`{bm($KE5I?0c(JEYm#t{F}j!xtsbob0{xu@0TB_*>G7w0ICn zr#VoBktqHZ~XxhiKD*lcG|b;H*|Ny3P^8ceV`sfBRfrhwZ!T+MFZ!F1Bt{q$8d9i6o?~ zODj^POr}&ivSa^R^YFIq7o0giLBKCycH_aU`F6)O6JX%nPTwh~Q`eq6*0iE#Srj2^ z*_hN3%*b83zfafy60@Cp3{J({RlSaEn&E?mrxRNC9GQ7#+f=s! z0KBf-9Ny_v2VbE%aB|Di)5kNJ^t&C`4D(>t7zYUWUFtbxt+Oq=!@O7BU)}>d*R72o zFF)3jQD_lLe4is&xzyJYC1-c{8TX$RU>&>P$%)ufpez0XSAukmh!xcekg`s$c<>-q zI#zn^JU0zzF}V60)o$_gY}PQH>b2M9&8fRZa#OauglPb zeQ@pMm&=!vNgos4CluQjLMV!pfkmxK+35bi^k&=k>9h02?l+u+m0agG;(h2|Jslc-llvtEwn~*w3bx7qnvZACG<8}AGeaDVvcHbKd2>3G^ zSFPULUn-?Pmo^-_`mLZr??uNH`2=I&yajlrF{DtUxMy#Nu}z=3y7qbUA;5`)hibMR zhXL@@uKyV0-2&A@t@!xyrBnMJl&^o@Gx$&5_q6?D=ji5grd-~=?dlg;ur(_V0wjh! zA=JV^C1m+DDkOsgr<%O9ZQFg!0}pD(#PSz4Dr_EyS5$`)VIAv);4n-SFP~YtC7sH= z7&*MfpH;gd*FHbkmD#)hVxb6xjc9~`t?_{=JS+@ip_cTicXxG<=7m9& zPX+Z8IC*GSAXuGCrZDHgR$r%jyk-fctis2Kx4HvZ|B~8uC@o)m^>Hy-O!&TKA?$&n zkP2Xc54w~!=z2?^NafyL*L0V9cbYrugHBBUj`xVyZmGFR&kvk#>1J*Z~i zNTz}?IAdJ$gkqd2!Gw(%LzE!O5s4C7q4%T~e_P{+z=DNDKrG**p=U`d5yg^vp`;Zn zsU=8gd0a9s4s0FPJePWR9eH5=+O^Kks&kC-iblNqTh2&Pw*^(4384f+D8N|fewZu_ zg2ejQ)ov;ztz;NQl7yj;A`(!H!XQu_$sqY9h_IrH*}_%1{L&_YLDvO?%R5Z-t+ClW z_qERbL?HKUZ!nt+!E9S`uoh^5A|DaIHe*_gf1`E_Vq+}{&T@t$EGhMnRjJ4z2w_W8 zp+qjs7as22^&S3wY1?+}^j-I=RcCE>#|39)g(lU7v_8;?=qK(9D8-*pPdiy)P3lIblG`+?%ea| zYoD3dopYt!tKgFicfNmNi(EWE=E4hC6(r|PYtanqJlmt57YOVrr2^tfrG(eG9C##X zu&1t@%L$RIvpj!wUA z8i>Pqot#_+Cnp6L2XPcZy1ar|9MnY+7eNvK1E)@Tr#2KsXq1*>)uUCozT7L##ok?o zhA6ofP4E|b*9tAfG?uf$#}>TIR&1A!yslP8}i7w-EzW(x#9VEvx18k%Tn=-$VV zkOtUr0b2!w3t>h?#8AZl^Az*(6KCGlD;4j~yx};`#2gN1_gv=%7KVzecIRakN{f*4 zeaI>yH;-o4OGhvGTU)(quWI)-q?V*(sVesSMv|wMUQ3hLEt=lBB$KZ9TyHr>)f7o%) zPYeU<3P)*P10*7vE)nA5#{c=6-E-_>r_u4e3i!I2+UksELwDqwMeBZ9FSP$;^Ajro z_@M#_Ss$?ejoB@!wN|kbGKs(0zLo%0QpQXW#t;oC$B0MZYZ&Ej?8~fNhcCVvPo3vo zFn0WWZaPliF^8_}yzb`*f@yg0uWv6HgNI)xa=pO%Ck(C<=-60l#uD3(wXP~c7!NoX z0&^6=N`zcc90F#qt@=Rn@r!3(*1v(Tl{B!m?Mc7yIA+nEHpY{YWr$=)F7rhR1P}(v zt{YhY#;jsW6G>#xhP*B`OCk|Pf+NN;ju1rxa*HAgoGq*rvqw&xe~;t1JA31$s?GBb z*g7&@cbKo4n<`>)!UlIAgR6q&))B0KYU8r66GbFj?8Guw4E%&}Qi_lT003LtoIZei zwD~=XZmeo+yZ2Pq3KYCF-R&11^p= z@H%s+=G`}wrbJ{()Mh71#2SP3Zy3m>l1n?0N-N1Q;z6?oSxr-G(H5m4EO>~&;}VKi zfY}3w+9z>vp#d)hVuu`)vG_aaH%3b=WKMnSu&c31;<3O;bz2iD=w+o4#oBb36 z5ZCF*Gu?zjZIR0S>_%pHY2$k8D^n7Sz_K8tCDeXM+dO<#LSg%h6`~dnVG1N@T7v&e z%wEd1!k{^zfz_1BTW{!$!B%g)J^2b87!9Y>>100X1SgT7s0z$o>^lAA=Gp_cC1(h=*5Tmf8z&LGJJ>$|K^~s`z9*OWz5MFUr?>Bi?_PGBB)#psD5?>n+q{o_ zz7~ez&;t#h8l$jwGPCC&xq2YetXYQT+0F3j(`xmNGf8dj#an|p#I*pvI*kwW4iuB> z+q3_7xB8y;pLzHG-S%+UHQA zvqp;$kmGJY>lLsN4C~&TcvAS1SErTcwcw0r@wngk zShAUA1M9b#g}^pL-zH7Q#z^&j#r9F8BTVfkR&qF<=e35goTu7c|GN)0mokj4m0%~0 zXJ8j4Hc_l;HJ&uU*Iw`8d_EscJ``s0tk9mkKo^&#TYXm-EoAzTQObxa@^u~g2t#T) zJz|rE!I_?i4dCJC=B8(_pZ{YR>|V?0iCcnU;E@$239^x?SYCfNaMHN;CtHIS_zHN9 zTkQc1v@O35okiFtq5_u+5FkY55ap@pi)O?}x0D1c*qB0KpYR}>Ul+B0Vmr}Z@+%mJ|As}sis_=ROPbov@*2thpE&?!V#Qgu$snYvCZ zrkhmkMU+fSf-s8(L37fPr&M*jRs{{THb!aXQu|P9l_-vJhHvLzMGH zE?1U0H_+PmNABp9`|KzkGfrrZ%XvdGo6*<{d5m9~L7 z_^`M;X6xDo=m6LY6RfvJEvsTK1!u8d2HPx|$S}p;sRy!I zWL55Yxu~_B`OP@~(q6&W3#)~I&+MGL%GWR$#udC151^wsswhqlii;rP9jJpiI7o&Z zAb})=HY7?4HA|re3ns`%$)FuvKCFWjhb~?IE)F6dF2K5}poj-NK6Gf;hw$t3=1txY zoxQxZWrQU6K!%|~!m?~Bnw-6Rr!F3BZ{u5!LqnZTDON}Coj9^@&le)V!NYrVwS~B% zEL+>Sr@}qGwGvu|HrOo|gSt__ezN^&%~{*)a=rf7y1HujUcr`zZB<4#l@T#eN)si} z)lZA<{=tKx8E%c9>A(##6}_p+~EZpKsl5a4pj`E*;_-6`ysiv zffA!7=MT1vCz}-m4~tjVey1b2KSR4OEtLd-(_DdUqYZ74LaDkhH?KFh?%WAOP2WbX zp@zT+Dx|5_f%JQiAGvVw!oh+g3e50u!aPfMxdC=E)XB{F5IcEZhePIM- zph6Y`$Oy?JBL<8Ex(SqEhLeQ@XcrdA>a?rx+_~HLA;l14)WmmpH}_w?Pg#HBZs0eS zwypwAW?M-x+3AU-(GGWSJ=ngxUEcEZ5OsX(Qlt!MQ zn^(`S{GHkAv(8@D`EAfSYig%Cxv?z!{=w^F#y)5_d7FuKZH7qlR-#5B0bt806%D0I zT7VdVP_?q*%Rq8UR;JkD4i^RXowt+E%#V2U>TfDqzZSDZ+dR!a#T3I>-z_$q9@k|m zy5~A*m~&JWP@E7a=pc}4kVHTc4h&R;Li7d@f`|hKMLkbb^uhOakNr3&FLjlm~i5NBM< zFaYI{;cpiHCNRdE0dg*>qIm(_t?#$h=(SCw?h3rJV2*ER8{O4^3#=dO)KwklZkoqU zS8i5c%YL*y*4;FY#D=XmkQnYj%LH)?02~gSJH`Qp1XY64g>%c_K$xseI&|e)7vRoL zAqRba$G@%fSGA7X7hQk%_3NVOYVS+$leU_!&6*5uN)8#5ZBz_6ASCA;azYS-Rt@ki zg2NWz(=;t}SC(~Ibl63$5C8FPmhXqb^)5#jaJ~I{Ex3xZ!+2h8$}}h_g@Be>HZ;72 z6#y#>AY3^skuVKF#0WxFBQ()5d5_nWb?c6c>EeMM|Mh+*&wEpPyxHCq{R-Gdr-`hN zF=1sxl&mBoK+#qRLl9#CEN|Fg8>nbmsTg3a1;#M9enQ$RgWk}kp#-5wh=EF&1tl%mJln2V^8o%Qv(*=zEuO7y z=m*8?xpUn-*@h5Cl_3BK3joiGkyaScK+>|MWdMRWm@RT!Q1piAlv5hL@B6>3&GI8) zP!xBc6}ZNIpJLL%2a8Y!+(<=f%WX>_uWVxlga9!D*oYt$l0cxRDMvqfU;Kq_mLK5k z)dvqYcgLa_Lz?3HyeF)@$%$&6lI?r4I>6W#M*<)vq{?&Oqrx``d`mhpVPr> z#q078F6gw_X<=?KR>8%^t%@wbITvNMu!hKiTSkCTJkw>1!e*Y{%31#_yMf=LW7{RJ zYoC^w$6%3cBtVG5)x#{Hg6IVTh9XEcM{gQwXk!R^y95^f-hZ`d{aVa+xW1EO4wDV4 zB?JgD7*?qkvc|$nIykTvNl2x0j3Q!MXoLL^)~}d7jcYf(H8D~c+?$pKL(px>Z3`eb z04RzS6_AgFT6Pn#iZAg$Sl_j8#;6ShF%&(Fag#E2asU@@LaN;=b=Wf7sgPKhfzhBM zC@eFL8^MrnA*9&Khe*Ab@CC9*uyJGXyi(;y2>lQLJZt;ShtJi?3Yf_t`F+$hY!+Q2Ndsx=U+bjTiAy7djLji>7k%k`$9&--f<*BNA3Hy&ZrHH|4 zG5H&9cB?O#zI1_OOf0Ce%mDfQxdtp3vU%(iY6yji3iISS61XLv#z|!zI_sZqza@B+ zyu9st5-h+`H7QUKx9}3w@oU@EO}&cEzG?fu!!bLO->%zkcg;i9^j`S~=WKMnDi1f= P00000NkvXXu0mjft=yBf literal 0 HcmV?d00001 diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/vite.svg b/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/src/components/CertificateInfo.jsx b/src/components/CertificateInfo.jsx new file mode 100644 index 0000000..2ee1698 --- /dev/null +++ b/src/components/CertificateInfo.jsx @@ -0,0 +1,147 @@ +import React from 'react'; +import { + CheckCircle2, + AlertTriangle, + XCircle, + Calendar, + Building, + User, + Key, + Hash, + ShieldCheck, + Clock +} from 'lucide-react'; + +export default function CertificateInfo({ metadata }) { + if (!metadata) return null; + + const { subject, issuer, validity, taxId, keyDetails, serialNumber, fingerprints, totalCerts } = metadata; + + // Status de validade + const getStatusBadge = () => { + if (validity.isExpired) { + return ( + + + Expirado ({Math.abs(validity.daysRemaining)} dias atrás) + + ); + } + if (validity.daysRemaining <= 30) { + return ( + + + Expira em breve ({validity.daysRemaining} dias) + + ); + } + return ( + + + Válido / Ativo ({validity.daysRemaining} dias restantes) + + ); + }; + + return ( +
+
+
+ +

Metadados e Inspeção do Certificado

+
+ {getStatusBadge()} +
+ +
+ {/* Titular */} +
+
+ + Titular / Nome Comum (CN) +
+
+ {subject.commonName || 'Não especificado'} +
+ {taxId && ( +
+ {taxId.type}: {taxId.value} +
+ )} +
+ + {/* Emissor */} +
+
+ + Autoridade Emissora (Issuer) +
+
+ {issuer.commonName || issuer.organization || 'Não especificado'} +
+
+ + {/* Chave e Tamanho */} +
+
+ + Chave Criptográfica +
+
+ {keyDetails ? `${keyDetails.type} (${keyDetails.bits} bits)` : 'Chave não encontrada'} + {metadata.hasPrivateKey && Chave Privada Incluída} +
+
+ + {/* Validade Inicial */} +
+
+ + Válido a partir de +
+
{validity.notBeforeFormatted}
+
+ + {/* Validade Final */} +
+
+ + Válido até +
+
{validity.notAfterFormatted}
+
+ + {/* Serial Number */} +
+
+ + Número de Série +
+
{serialNumber || 'N/A'}
+
+ + {/* Cadeia de Certificados */} +
+
+ + Total de Certificados na Cadeia +
+
+ {totalCerts} certificado(s) detectado(s) +
+
+ + {/* Fingerprint SHA-1 */} +
+
+ + Impressão Digital (Thumbprint SHA-1) +
+
+ {fingerprints?.sha1 || 'N/A'} +
+
+
+
+ ); +} diff --git a/src/components/Header.jsx b/src/components/Header.jsx new file mode 100644 index 0000000..20358da --- /dev/null +++ b/src/components/Header.jsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { ShieldCheck, MessageSquare, Server, Layers } from 'lucide-react'; + +export default function Header({ activeTab, onSelectTab, onOpenHostingGuide }) { + return ( +
+
+
+
+ {activeTab === 'cert' ? ( + + ) : ( + + )} +
+
+

+ {activeTab === 'cert' ? 'CertConverter PFX' : 'AppWPP Manager'} +

+

+ {activeTab === 'cert' + ? 'Conversor de Certificado Digital (.pfx para .crt, .pem, .key)' + : 'Gerenciador de Sessões WPPConnect / WhatsApp'} +

+
+
+ + {/* Seletor Central de Aplicação */} +
+ + + +
+ +
+ +
+
+
+ ); +} diff --git a/src/components/HostGuideModal.jsx b/src/components/HostGuideModal.jsx new file mode 100644 index 0000000..811c3c8 --- /dev/null +++ b/src/components/HostGuideModal.jsx @@ -0,0 +1,225 @@ +import React, { useState } from 'react'; +import { + X, + Server, + Globe, + Layers, + Terminal, + Check, + Copy, + FileCode, + HardDrive +} from 'lucide-react'; + +export default function HostGuideModal({ isOpen, onClose }) { + const [activePlatform, setActivePlatform] = useState('vercel'); + const [copiedKey, setCopiedKey] = useState(null); + + if (!isOpen) return null; + + const handleCopy = (code, key) => { + navigator.clipboard.writeText(code); + setCopiedKey(key); + setTimeout(() => setCopiedKey(null), 2000); + }; + + const platforms = [ + { id: 'vercel', name: 'Vercel', icon: Globe }, + { id: 'netlify', name: 'Netlify', icon: Layers }, + { id: 'github', name: 'GitHub Pages', icon: Terminal }, + { id: 'docker', name: 'Docker / Linux', icon: Server }, + { id: 'iis', name: 'Windows IIS', icon: HardDrive }, + ]; + + return ( +
+
e.stopPropagation()}> +
+
+ +
+

Guia de Hospedagem & Deploy

+

Como publicar esta aplicação React em produção

+
+
+ +
+ + {/* Abas de Plataforma */} +
+ {platforms.map((p) => { + const Icon = p.icon; + return ( + + ); + })} +
+ + {/* Conteúdo da Plataforma */} +
+ {/* VERCEL */} + {activePlatform === 'vercel' && ( +
+

Hospedar na Vercel (Recomendado - Gratuito e Instantâneo)

+

+ A Vercel é a plataforma mais simples para hospedar aplicações Vite/React. Possui SSL automático e CDN global. +

+ +
Opção 1: Via Linha de Comando (CLI da Vercel)
+
+
+                  {`# 1. Instale a CLI da Vercel globalmente
+npm i -g vercel
+
+# 2. Na pasta do projeto, execute o comando de deploy
+vercel`}
+                
+ +
+ +
Opção 2: Conectar com o Repositório GitHub
+
    +
  1. Suba este projeto para o seu repositório no GitHub.
  2. +
  3. Acesse vercel.com e faça login com seu GitHub.
  4. +
  5. Clique em Add New Project e importe o repositório.
  6. +
  7. O Framework Preset será detectado automaticamente como Vite.
  8. +
  9. Clique em Deploy. Seu link HTTPS estará no ar em segundos!
  10. +
+
+ )} + + {/* NETLIFY */} + {activePlatform === 'netlify' && ( +
+

Hospedar na Netlify (Deploy com Arrastar e Soltar ou Git)

+

Você pode fazer o deploy sem nem precisar de conta Git, apenas gerando a pasta estática:

+ +
Método Drop (Arrastar Pasta):
+
+
+                  {`# 1. Gere a compilação de produção
+npm run build
+
+# 2. A pasta 'dist' será gerada com os arquivos estáticos prontos.`}
+                
+ +
+ +
    +
  1. Acesse app.netlify.com/drop.
  2. +
  3. Arraste a pasta dist gerada direto para a tela do navegador.
  4. +
  5. Pronto! O site recebe uma URL pública com HTTPS imediato.
  6. +
+
+ )} + + {/* GITHUB PAGES */} + {activePlatform === 'github' && ( +
+

Hospedar no GitHub Pages

+

Hospedagem gratuita direto no seu repositório do GitHub.

+ +
+
+                  {`# 1. Instale o gh-pages como dependência de desenvolvimento
+npm install -D gh-pages
+
+# 2. Adicione no package.json:
+# "homepage": "https://seu-usuario.github.io/cert-converter-app",
+# "scripts": {
+#    "predeploy": "npm run build",
+#    "deploy": "gh-pages -d dist"
+# }
+
+# 3. Dispare o deploy:
+npm run deploy`}
+                
+ +
+
+ )} + + {/* DOCKER / LINUX */} + {activePlatform === 'docker' && ( +
+

Hospedar em Servidor Próprio / Linux com Docker & Nginx

+

Para empresas ou redes internas que desejam rodar o conversor em servidor on-premise isolado:

+ +
+
+                  {`# 1. Construir a imagem Docker
+docker build -t cert-converter-app .
+
+# 2. Rodar o container na porta 80
+docker run -d -p 80:80 --name cert-converter cert-converter-app`}
+                
+ +
+ +

+ Um arquivo Dockerfile e nginx.conf otimizados já foram criados na raiz do projeto. +

+
+ )} + + {/* IIS */} + {activePlatform === 'iis' && ( +
+

Hospedar no Windows Server (IIS)

+

Ideal para empresas com infraestrutura interna Windows:

+ +
    +
  1. Execute npm run build para gerar a pasta dist.
  2. +
  3. Copie os arquivos da pasta dist para o diretório do IIS (ex: C:\inetpub\wwwroot\cert-converter).
  4. +
  5. Crie um site ou aplicativo no Gerenciador do IIS apontando para essa pasta.
  6. +
  7. + Certifique-se de que o arquivo web.config incluído no projeto esteja na raiz para gerenciar as rotas. +
  8. +
+
+ )} +
+ +
+ +
+
+
+ ); +} diff --git a/src/components/OpenSslReference.jsx b/src/components/OpenSslReference.jsx new file mode 100644 index 0000000..025f51e --- /dev/null +++ b/src/components/OpenSslReference.jsx @@ -0,0 +1,84 @@ +import React, { useState } from 'react'; +import { Terminal, Copy, Check, ChevronDown, ChevronUp } from 'lucide-react'; + +export default function OpenSslReference({ baseName = 'certificado' }) { + const [isOpen, setIsOpen] = useState(false); + const [copiedIndex, setCopiedIndex] = useState(null); + + const commands = [ + { + title: '1. Conversão para CRT (Apenas Certificado do Cliente)', + flags: '-clcerts -nokeys', + cmd: `openssl pkcs12 -in ${baseName}.pfx -clcerts -nokeys -out ${baseName}.crt`, + desc: 'Extrai exclusivamente o certificado cliente (-clcerts) omitindo a chave privada (-nokeys).' + }, + { + title: '2. Conversão para PEM (Cadeia Completa de Certificados)', + flags: '-nokeys', + cmd: `openssl pkcs12 -in ${baseName}.pfx -nokeys -out ${baseName}.pem`, + desc: 'Extrai todos os certificados da cadeia pública (cliente, intermediários e raiz), sem chaves privadas.' + }, + { + title: '3. Conversão para KEY (Chave Privada Descriptografada)', + flags: '-nocerts -nodes', + cmd: `openssl pkcs12 -in ${baseName}.pfx -nocerts -nodes -out ${baseName}.key`, + desc: 'Extrai apenas a chave privada (-nocerts) sem senha/descriptografada (-nodes) para uso direto em servidores.' + } + ]; + + const handleCopy = (text, index) => { + navigator.clipboard.writeText(text); + setCopiedIndex(index); + setTimeout(() => setCopiedIndex(null), 2000); + }; + + return ( +
+
setIsOpen(!isOpen)} + role="button" + tabIndex={0} + > +
+ + Equivalência com Comandos CLI do OpenSSL +
+ +
+ + {isOpen && ( +
+

+ Este aplicativo web executa rigorosamente as mesmas operações criptográficas que os comandos nativos do OpenSSL abaixo: +

+ +
+ {commands.map((c, idx) => ( +
+
+ {c.title} + {c.flags} +
+
+ {c.cmd} + +
+
{c.desc}
+
+ ))} +
+
+ )} +
+ ); +} diff --git a/src/components/OutputFiles.jsx b/src/components/OutputFiles.jsx new file mode 100644 index 0000000..fa3a631 --- /dev/null +++ b/src/components/OutputFiles.jsx @@ -0,0 +1,200 @@ +import React, { useState } from 'react'; +import { + FileCode2, + Key, + FileText, + Download, + Copy, + Check, + Archive, + ExternalLink, + ShieldAlert +} from 'lucide-react'; +import { downloadFile, downloadAllAsZip } from '../utils/downloadHelper'; + +export default function OutputFiles({ results, baseName, metadata }) { + const [activeTab, setActiveTab] = useState('crt'); + const [copiedKey, setCopiedKey] = useState(null); + + if (!results) return null; + + const handleCopy = (content, keyName) => { + navigator.clipboard.writeText(content); + setCopiedKey(keyName); + setTimeout(() => { + setCopiedKey(null); + }, 2000); + }; + + const handleDownloadSingle = (type) => { + const filename = `${baseName}.${type}`; + downloadFile(results[type], filename); + }; + + const handleDownloadZip = () => { + downloadAllAsZip(results, baseName, metadata); + }; + + const tabs = [ + { + id: 'crt', + label: `${baseName}.crt`, + ext: '.CRT', + title: 'Certificado do Cliente', + desc: 'Apenas o certificado folha/cliente do titular (sem certificados intermediários da CA e sem chave privada).', + command: `openssl pkcs12 -in ${baseName}.pfx -clcerts -nokeys -out ${baseName}.crt`, + content: results.crt, + icon: FileCode2, + badge: 'Público', + badgeClass: 'badge-blue' + }, + { + id: 'pem', + label: `${baseName}.pem`, + ext: '.PEM', + title: 'Cadeia Completa de Certificados', + desc: 'Contém todos os certificados da cadeia (certificado cliente + certificados intermediários e raiz), sem chaves.', + command: `openssl pkcs12 -in ${baseName}.pfx -nokeys -out ${baseName}.pem`, + content: results.pem, + icon: FileText, + badge: 'Cadeia Completa', + badgeClass: 'badge-purple' + }, + { + id: 'key', + label: `${baseName}.key`, + ext: '.KEY', + title: 'Chave Privada (Descriptografada)', + desc: 'Chave privada pronta para uso em servidores web (Nginx, Apache), microsserviços ou sistemas de emissão de NF-e (-nodes).', + command: `openssl pkcs12 -in ${baseName}.pfx -nocerts -nodes -out ${baseName}.key`, + content: results.key, + icon: Key, + badge: 'Privado / Confidencial', + badgeClass: 'badge-amber', + isSecret: true + } + ]; + + const currentTab = tabs.find(t => t.id === activeTab) || tabs[0]; + + return ( +
+
+
+

Arquivos Convertidos

+

+ Geração concluída com sucesso. Escolha um arquivo para pré-visualizar ou baixe o pacote completo. +

+
+ +
+ + {/* Cards de Atalho Rápido */} +
+ {tabs.map((tab) => ( +
setActiveTab(tab.id)} + role="button" + tabIndex={0} + > +
+ {tab.ext} + +
+
{baseName}.{tab.id}
+
{tab.title}
+
+ ))} +
+ + {/* Visualizador de Arquivo com Abas */} +
+
+
+ {tabs.map((tab) => { + const Icon = tab.icon; + return ( + + ); + })} +
+ +
+ + +
+
+ + {/* Informações da Aba Ativa */} +
+
+ {currentTab.title}: {currentTab.desc} +
+ {currentTab.isSecret && ( +
+ + Atenção: A chave privada não deve ser compartilhada publicamente. +
+ )} +
+ + {/* Bloco de Código com o Conteúdo */} +
+
+            {currentTab.content || '// Conteúdo vazio ou não gerado'}
+          
+
+
+
+ ); +} diff --git a/src/components/PasswordInput.jsx b/src/components/PasswordInput.jsx new file mode 100644 index 0000000..102376c --- /dev/null +++ b/src/components/PasswordInput.jsx @@ -0,0 +1,47 @@ +import React, { useState } from 'react'; +import { Lock, Eye, EyeOff, KeyRound } from 'lucide-react'; + +export default function PasswordInput({ password, onChange, onSubmit, disabled }) { + const [showPassword, setShowPassword] = useState(false); + + const handleKeyDown = (e) => { + if (e.key === 'Enter' && onSubmit) { + e.preventDefault(); + onSubmit(); + } + }; + + return ( +
+ +
+ onChange(e.target.value)} + onKeyDown={handleKeyDown} + disabled={disabled} + placeholder="Digite a senha do certificado PFX..." + className="password-input" + autoComplete="off" + /> + +
+

+ Caso o certificado não possua senha, deixe este campo em branco. +

+
+ ); +} diff --git a/src/components/SecurityBadge.jsx b/src/components/SecurityBadge.jsx new file mode 100644 index 0000000..7d8be89 --- /dev/null +++ b/src/components/SecurityBadge.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { Lock, Cpu, Globe } from 'lucide-react'; + +export default function SecurityBadge() { + return ( +
+
+ + 100% Client-Side & Seguro +
+

+ Todo o processamento criptográfico ocorre localmente no seu próprio navegador através do motor Web Crypto. + Seu arquivo .pfx e sua senha nunca saem do seu computador nem são enviados para servidores externos. +

+
+ ); +} diff --git a/src/components/UploadZone.jsx b/src/components/UploadZone.jsx new file mode 100644 index 0000000..a561596 --- /dev/null +++ b/src/components/UploadZone.jsx @@ -0,0 +1,102 @@ +import React, { useRef, useState } from 'react'; +import { UploadCloud, FileCheck, X, AlertCircle } from 'lucide-react'; + +export default function UploadZone({ file, onFileSelected, onFileCleared }) { + const [isDragging, setIsDragging] = useState(false); + const fileInputRef = useRef(null); + + const handleDragOver = (e) => { + e.preventDefault(); + setIsDragging(true); + }; + + const handleDragLeave = (e) => { + e.preventDefault(); + setIsDragging(false); + }; + + const handleDrop = (e) => { + e.preventDefault(); + setIsDragging(false); + if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { + validateAndSetFile(e.dataTransfer.files[0]); + } + }; + + const handleInputChange = (e) => { + if (e.target.files && e.target.files.length > 0) { + validateAndSetFile(e.target.files[0]); + } + }; + + const validateAndSetFile = (selectedFile) => { + const ext = selectedFile.name.split('.').pop().toLowerCase(); + if (ext === 'pfx' || ext === 'p12') { + onFileSelected(selectedFile); + } else { + alert('Por favor, selecione um arquivo de certificado com extensão .pfx ou .p12'); + } + }; + + const formatFileSize = (bytes) => { + if (bytes < 1024) return bytes + ' bytes'; + if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; + return (bytes / (1024 * 1024)).toFixed(2) + ' MB'; + }; + + return ( +
+ + + {!file ? ( +
fileInputRef.current?.click()} + role="button" + tabIndex={0} + > +
+ +
+

Arraste seu arquivo .pfx aqui ou clique para selecionar

+

Suporta arquivos PKCS#12 (.pfx, .p12)

+ +
+ ) : ( +
+
+
+ +
+
+
{file.name}
+
+ PFX / PKCS#12 + {formatFileSize(file.size)} +
+
+
+ +
+ )} +
+ ); +} diff --git a/src/components/wpp/AppWPP.jsx b/src/components/wpp/AppWPP.jsx new file mode 100644 index 0000000..688a698 --- /dev/null +++ b/src/components/wpp/AppWPP.jsx @@ -0,0 +1,566 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { + Server, + Plus, + Settings, + Play, + List, + Trash2, + Search, + Smartphone, + Globe, + Activity, + MessageSquare, + AlertCircle, + CheckCircle2, + Info, + Edit2 +} from 'lucide-react'; +import { getStoredServers, saveServers } from '../../utils/appWppStorage'; +import { + startSession, + closeSession, + logoutSession, + checkSessionStatus, + clearSessionData, + generateToken, + ensureQRPrefix +} from '../../utils/wppConnectApi'; +import WppSessionCard from './WppSessionCard'; +import ModalServer from './ModalServer'; +import ModalSession from './ModalSession'; +import ModalQRCode from './ModalQRCode'; +import ModalListSessions from './ModalListSessions'; +import ModalSettings from './ModalSettings'; +import ModalConfirm from './ModalConfirm'; + +export default function AppWPP() { + const [servers, setServers] = useState([]); + const [activeServerId, setActiveServerId] = useState(null); + const [searchQuery, setSearchQuery] = useState(''); + const [toasts, setToasts] = useState([]); + + // Modals state + const [isServerModalOpen, setIsServerModalOpen] = useState(false); + const [serverToEdit, setServerToEdit] = useState(null); + + const [isSessionModalOpen, setIsSessionModalOpen] = useState(false); + const [sessionToEdit, setSessionToEdit] = useState(null); + + const [isQRModalOpen, setIsQRModalOpen] = useState(false); + const [activeQRSession, setActiveQRSession] = useState(null); + + const [isListSessionsOpen, setIsListSessionsOpen] = useState(false); + const [isSettingsOpen, setIsSettingsOpen] = useState(false); + + // Styled Confirm Modal state + const [confirmModal, setConfirmModal] = useState({ + isOpen: false, + title: '', + message: '', + description: '', + confirmText: 'Confirmar', + type: 'warning', + onConfirm: () => {} + }); + + // Carrega servidores armazenados na montagem + useEffect(() => { + const list = getStoredServers(); + setServers(list); + if (list.length > 0) { + setActiveServerId(list[0].id); + } + }, []); + + // Salva no localStorage sempre que `servers` mudar + const updateServersState = (updatedList) => { + setServers(updatedList); + saveServers(updatedList); + }; + + const showToast = (message, type = 'info') => { + const id = Date.now().toString() + Math.random().toString(); + setToasts((prev) => [...prev, { id, message, type }]); + setTimeout(() => { + setToasts((prev) => prev.filter((t) => t.id !== id)); + }, 3500); + }; + + const activeServer = servers.find((s) => s.id === activeServerId) || null; + + // Servidor CRUD + const handleSaveServer = (serverData) => { + let updated; + const exists = servers.some((s) => s.id === serverData.id); + if (exists) { + updated = servers.map((s) => (s.id === serverData.id ? { ...s, ...serverData } : s)); + showToast(`Servidor "${serverData.name}" atualizado!`, 'success'); + } else { + updated = [...servers, serverData]; + setActiveServerId(serverData.id); + showToast(`Servidor "${serverData.name}" adicionado com sucesso!`, 'success'); + } + updateServersState(updated); + }; + + const handleRemoveServer = () => { + if (!activeServer) return; + setConfirmModal({ + isOpen: true, + title: 'Remover Servidor', + message: `Tem certeza que deseja remover o servidor "${activeServer.name}"?`, + description: 'Todas as sessões cadastradas para este servidor deixarão de ser exibidas na listagem.', + confirmText: 'Remover Servidor', + type: 'danger', + onConfirm: () => { + const updated = servers.filter((s) => s.id !== activeServer.id); + updateServersState(updated); + setActiveServerId(updated.length > 0 ? updated[0].id : null); + showToast(`Servidor "${activeServer.name}" removido.`, 'info'); + } + }); + }; + + // Sessão CRUD + const handleSaveSession = async (sessionData, originalName) => { + if (!activeServer) return; + + let updatedSessions = [...(activeServer.sessions || [])]; + if (originalName) { + updatedSessions = updatedSessions.map((s) => (s.name === originalName ? sessionData : s)); + showToast(`Sessão "${sessionData.name}" atualizada!`, 'success'); + } else { + if (updatedSessions.some((s) => s.name === sessionData.name)) { + showToast('Já existe uma sessão com este nome.', 'error'); + return; + } + updatedSessions.push(sessionData); + showToast(`Sessão "${sessionData.name}" criada!`, 'success'); + } + + const updatedServer = { ...activeServer, sessions: updatedSessions }; + const updatedServers = servers.map((s) => (s.id === activeServer.id ? updatedServer : s)); + updateServersState(updatedServers); + + // Se for nova sessão, tenta gerar token e iniciar + if (!originalName) { + try { + const token = await generateToken(activeServer, sessionData.name); + if (token) { + sessionData.token = token; + updateServersState( + servers.map((s) => + s.id === activeServer.id + ? { ...s, sessions: updatedSessions.map((x) => (x.name === sessionData.name ? { ...x, token } : x)) } + : s + ) + ); + } + } catch (e) {} + handleStartSession(sessionData.name, true); + } + }; + + const handleRemoveSession = (sessionName) => { + if (!activeServer) return; + setConfirmModal({ + isOpen: true, + title: 'Excluir Sessão', + message: `Deseja realmente excluir a sessão "${sessionName}"?`, + description: 'Esta sessão será removida do gerenciador para este servidor.', + confirmText: 'Excluir Sessão', + type: 'danger', + onConfirm: () => { + const updatedSessions = activeServer.sessions.filter((s) => s.name !== sessionName); + const updatedServers = servers.map((s) => + s.id === activeServer.id ? { ...s, sessions: updatedSessions } : s + ); + updateServersState(updatedServers); + showToast(`Sessão "${sessionName}" removida.`, 'info'); + } + }); + }; + + // Ações de Sessão + const handleStartSession = async (sessionName, openQR = true) => { + if (!activeServer) return; + + // Atualiza estado local para connecting + updateSessionProperty(sessionName, { status: 'connecting' }); + + if (openQR) { + setActiveQRSession(sessionName); + setIsQRModalOpen(true); + } + + try { + const data = await startSession(activeServer, sessionName); + if ((data.status || '').toLowerCase() === 'qrcode' && (data.qrcode || data.urlcode)) { + const qr = ensureQRPrefix(data.qrcode || data.urlcode); + updateSessionProperty(sessionName, { qrCode: qr, status: 'qr' }); + showToast(`Escaneie o QR Code para "${sessionName}".`, 'warning'); + } else if (data.status === 'connected') { + updateSessionProperty(sessionName, { status: 'connected', connectedAt: new Date().toLocaleString('pt-BR') }); + showToast(`Sessão "${sessionName}" conectada com sucesso!`, 'success'); + } else { + updateSessionProperty(sessionName, { status: 'qr' }); + showToast(`Aguardando QR Code para "${sessionName}".`, 'warning'); + } + } catch (err) { + console.error('Start session error:', err); + updateSessionProperty(sessionName, { status: 'qr' }); + showToast(`Aguardando leitura do QR Code para "${sessionName}".`, 'warning'); + } + }; + + const handleCloseSession = async (sessionName) => { + if (!activeServer) return; + try { + await closeSession(activeServer, sessionName); + updateSessionProperty(sessionName, { status: 'disconnected' }); + showToast(`Sessão "${sessionName}" fechada.`, 'success'); + } catch (err) { + showToast(`Erro ao fechar sessão: ${err.message}`, 'error'); + } + }; + + const handleLogoutSession = async (sessionName) => { + if (!activeServer) return; + try { + await logoutSession(activeServer, sessionName); + updateSessionProperty(sessionName, { status: 'disconnected' }); + showToast(`Sessão "${sessionName}" desconectada.`, 'success'); + } catch (err) { + showToast(`Erro ao desconectar: ${err.message}`, 'error'); + } + }; + + const handleCheckStatus = async (sessionName) => { + if (!activeServer) return; + try { + const status = await checkSessionStatus(activeServer, sessionName); + const isConnected = status === true || status === 'connected'; + const newStatus = isConnected ? 'connected' : 'disconnected'; + updateSessionProperty(sessionName, { + status: newStatus, + connectedAt: isConnected ? new Date().toLocaleString('pt-BR') : undefined + }); + showToast(`Status de "${sessionName}": ${newStatus}`, isConnected ? 'success' : 'warning'); + } catch (err) { + showToast(`Erro ao verificar status: ${err.message}`, 'error'); + } + }; + + const handleClearSession = (sessionName) => { + if (!activeServer) return; + setConfirmModal({ + isOpen: true, + title: 'Limpar Dados da Sessão', + message: `Limpar arquivos e dados de "${sessionName}" no servidor?`, + description: 'Esta operação removerá os tokens e os arquivos em cache da sessão diretamente no servidor WPPConnect.', + confirmText: 'Limpar Arquivos e Dados', + type: 'warning', + onConfirm: async () => { + try { + await clearSessionData(activeServer, sessionName); + showToast(`Dados da sessão "${sessionName}" limpos com sucesso no servidor.`, 'success'); + } catch (err) { + showToast(`Erro ao limpar dados: ${err.message}`, 'error'); + } + } + }); + }; + + const handleStartAll = async () => { + if (!activeServer || !activeServer.sessions) return; + showToast('Iniciando todas as sessões...', 'info'); + for (const session of activeServer.sessions) { + if (session.status !== 'connected') { + await handleStartSession(session.name, false); + } + } + showToast('Processamento de inicialização concluído.', 'success'); + }; + + const updateSessionProperty = (sessionName, props) => { + if (!activeServer) return; + const updatedSessions = activeServer.sessions.map((s) => + s.name === sessionName ? { ...s, ...props } : s + ); + const updatedServers = servers.map((srv) => + srv.id === activeServer.id ? { ...srv, sessions: updatedSessions } : srv + ); + updateServersState(updatedServers); + }; + + // Filtro de sessões + const filteredSessions = (activeServer?.sessions || []).filter((s) => + s.name.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + return ( +
+ {/* Sidebar de Servidores */} + + + {/* Conteúdo Principal do Servidor Selecionado */} +
+ {activeServer ? ( +
+ {/* Topbar do Servidor */} +
+
+
+

{activeServer.name}

+ + {activeServer.online ? 'Online' : 'Offline'} + +
+ {activeServer.baseUrl} +
+ +
+ + + + + +
+
+ + {/* Toolbar de Sessões (Busca e Nova Sessão) */} +
+
+ + setSearchQuery(e.target.value)} + className="wpp-search-input" + /> +
+ + +
+ + {/* Grid de Cards de Sessões */} +
+ {filteredSessions.map((session) => ( + { + setSessionToEdit(s); + setIsSessionModalOpen(true); + }} + onClear={handleClearSession} + onRemove={handleRemoveSession} + onShowQR={(name) => { + setActiveQRSession(name); + setIsQRModalOpen(true); + }} + /> + ))} + + {filteredSessions.length === 0 && ( +
+ +

Nenhuma sessão encontrada

+

+ {searchQuery + ? 'Nenhuma sessão corresponde à busca informada.' + : 'Clique em "+ Nova Sessão" acima para cadastrar sua primeira sessão do WhatsApp.'} +

+
+ )} +
+
+ ) : ( +
+ +

Bem-vindo ao AppWPP

+

Selecione ou adicione um servidor WPPConnect para gerenciar suas sessões do WhatsApp.

+ +
+ )} +
+ + {/* Modals */} + setIsServerModalOpen(false)} + onSave={handleSaveServer} + serverToEdit={serverToEdit} + /> + + setIsSessionModalOpen(false)} + onSave={handleSaveSession} + sessionToEdit={sessionToEdit} + /> + + setIsQRModalOpen(false)} + server={activeServer} + sessionName={activeQRSession} + onConnected={(name) => { + updateSessionProperty(name, { status: 'connected', connectedAt: new Date().toLocaleString('pt-BR') }); + showToast(`Sessão "${name}" conectada com sucesso!`, 'success'); + }} + /> + + setIsListSessionsOpen(false)} + server={activeServer} + /> + + setIsSettingsOpen(false)} + servers={servers} + onImportServers={(newServers) => { + updateServersState(newServers); + if (newServers.length > 0) setActiveServerId(newServers[0].id); + }} + /> + + {/* Modal de Confirmação Estilizado */} + setConfirmModal((prev) => ({ ...prev, isOpen: false }))} + onConfirm={confirmModal.onConfirm} + title={confirmModal.title} + message={confirmModal.message} + description={confirmModal.description} + confirmText={confirmModal.confirmText} + type={confirmModal.type} + /> + + {/* Toasts */} +
+ {toasts.map((t) => ( +
+ {t.type === 'success' && } + {t.type === 'error' && } + {t.type === 'warning' && } + {t.type === 'info' && } + {t.message} +
+ ))} +
+
+ ); +} diff --git a/src/components/wpp/ModalConfirm.jsx b/src/components/wpp/ModalConfirm.jsx new file mode 100644 index 0000000..2183f14 --- /dev/null +++ b/src/components/wpp/ModalConfirm.jsx @@ -0,0 +1,71 @@ +import React from 'react'; +import { X, AlertTriangle, Trash2, ShieldAlert } from 'lucide-react'; + +export default function ModalConfirm({ + isOpen, + onClose, + onConfirm, + title = 'Confirmar Ação', + message, + description, + confirmText = 'Confirmar', + cancelText = 'Cancelar', + type = 'warning', // 'warning' | 'danger' + icon: CustomIcon +}) { + if (!isOpen) return null; + + const isDanger = type === 'danger'; + const IconComponent = CustomIcon || (isDanger ? Trash2 : AlertTriangle); + + return ( +
+
e.stopPropagation()} + style={{ maxWidth: '460px' }} + > +
+
+
+ +
+

{title}

+
+ +
+ +
+

{message}

+ {description && ( +

{description}

+ )} +
+ +
+ + + +
+
+
+ ); +} diff --git a/src/components/wpp/ModalListSessions.jsx b/src/components/wpp/ModalListSessions.jsx new file mode 100644 index 0000000..ca718f1 --- /dev/null +++ b/src/components/wpp/ModalListSessions.jsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from 'react'; +import { X, Server, Loader2, RefreshCw } from 'lucide-react'; +import { listAllServerSessions } from '../../utils/wppConnectApi'; + +export default function ModalListSessions({ isOpen, onClose, server }) { + const [sessions, setSessions] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + useEffect(() => { + if (isOpen && server) { + loadSessions(); + } + }, [isOpen, server]); + + const loadSessions = async () => { + if (!server) return; + setLoading(true); + setError(''); + try { + const list = await listAllServerSessions(server); + setSessions(list); + } catch (err) { + setError(err.message || 'Erro ao consultar sessões no servidor.'); + } finally { + setLoading(false); + } + }; + + if (!isOpen) return null; + + return ( +
+
e.stopPropagation()} style={{ maxWidth: '580px' }}> +
+
+ +

Sessões no Servidor ({server?.name})

+
+ +
+ +
+ {loading ? ( +
+ +

Consultando servidor WPPConnect...

+
+ ) : error ? ( +
+ {error} +
+ ) : sessions.length === 0 ? ( +

+ Nenhuma sessão ativa encontrada diretamente neste servidor. +

+ ) : ( +
+ {sessions.map((sessName, idx) => { + const localSession = server.sessions?.find(s => s.name === sessName); + const isConnected = localSession?.status === 'connected'; + return ( +
+ {sessName} + + {isConnected ? 'Conectado' : 'Registrado'} + +
+ ); + })} +
+ )} +
+ +
+ + +
+
+
+ ); +} diff --git a/src/components/wpp/ModalQRCode.jsx b/src/components/wpp/ModalQRCode.jsx new file mode 100644 index 0000000..c41f291 --- /dev/null +++ b/src/components/wpp/ModalQRCode.jsx @@ -0,0 +1,120 @@ +import React, { useEffect, useState } from 'react'; +import { X, QrCode, RefreshCw, CheckCircle2, Loader2, Smartphone } from 'lucide-react'; +import { fetchQRCode, checkSessionStatus, ensureQRPrefix } from '../../utils/wppConnectApi'; + +export default function ModalQRCode({ isOpen, onClose, server, sessionName, onConnected }) { + const [qrSrc, setQrSrc] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [isConnected, setIsConnected] = useState(false); + + useEffect(() => { + if (!isOpen || !server || !sessionName) return; + + setIsConnected(false); + const session = server.sessions?.find(s => s.name === sessionName); + if (session?.qrCode) { + setQrSrc(ensureQRPrefix(session.qrCode)); + } + + // Carrega o QR Code inicial + loadQR(); + + // 1. Polling para atualizar o QR Code a cada 25s + const qrInterval = setInterval(() => { + loadQR(); + }, 25000); + + // 2. Polling rápido a cada 2.5s para checar se o usuário escaneou e conectou + const statusInterval = setInterval(async () => { + try { + const status = await checkSessionStatus(server, sessionName); + if (status === true || status === 'connected') { + setIsConnected(true); + clearInterval(statusInterval); + clearInterval(qrInterval); + if (onConnected) onConnected(sessionName); + setTimeout(() => { + onClose(); + }, 1800); + } + } catch (e) {} + }, 2500); + + return () => { + clearInterval(qrInterval); + clearInterval(statusInterval); + }; + }, [isOpen, server, sessionName]); + + const loadQR = async () => { + if (!server || !sessionName) return; + setIsLoading(true); + try { + const qr = await fetchQRCode(server, sessionName); + if (qr) setQrSrc(qr); + } catch (e) { + console.warn('Erro ao carregar QR Code:', e); + } finally { + setIsLoading(false); + } + }; + + if (!isOpen) return null; + + return ( +
+
e.stopPropagation()} style={{ maxWidth: '420px', textAlign: 'center' }}> +
+
+ +

QR Code: {sessionName}

+
+ +
+ +
+ {isConnected ? ( +
+ +

WhatsApp Conectado!

+

A sessão foi autenticada com sucesso.

+
+ ) : qrSrc ? ( +
+
+ QR Code WhatsApp +
+
+ + Abra o WhatsApp > Dispositivos Conectados > Conectar +
+
+ ) : ( +
+ +

Aguardando o servidor gerar o QR Code...

+
+ )} +
+ +
+ + +
+
+
+ ); +} diff --git a/src/components/wpp/ModalServer.jsx b/src/components/wpp/ModalServer.jsx new file mode 100644 index 0000000..35e6851 --- /dev/null +++ b/src/components/wpp/ModalServer.jsx @@ -0,0 +1,154 @@ +import React, { useState, useEffect } from 'react'; +import { X, Server, Eye, EyeOff, Check, AlertCircle, Loader2 } from 'lucide-react'; +import { testServerConnection, normalizeUrl } from '../../utils/wppConnectApi'; + +export default function ModalServer({ isOpen, onClose, onSave, serverToEdit }) { + const [name, setName] = useState(''); + const [baseUrl, setBaseUrl] = useState(''); + const [secretKey, setSecretKey] = useState(''); + const [showSecret, setShowSecret] = useState(false); + const [testStatus, setTestStatus] = useState(null); // { loading, success, message, error } + + useEffect(() => { + if (serverToEdit) { + setName(serverToEdit.name || ''); + setBaseUrl(serverToEdit.baseUrl || ''); + setSecretKey(serverToEdit.secretKey || ''); + } else { + setName(''); + setBaseUrl(''); + setSecretKey(''); + } + setTestStatus(null); + }, [serverToEdit, isOpen]); + + if (!isOpen) return null; + + const handleTest = async () => { + if (!baseUrl || !secretKey) { + setTestStatus({ error: 'Preencha a URL e a Secret Key antes de testar.' }); + return; + } + setTestStatus({ loading: true }); + try { + const res = await testServerConnection(baseUrl, secretKey); + if (res.ok) { + setTestStatus({ success: true, message: res.message }); + } else { + setTestStatus({ error: res.error }); + } + } catch (err) { + setTestStatus({ error: err.message || 'Falha na conexão com o servidor' }); + } + }; + + const handleSave = (e) => { + e.preventDefault(); + if (!name.trim() || !baseUrl.trim() || !secretKey.trim()) { + alert('Por favor, preencha todos os campos obrigatórios.'); + return; + } + onSave({ + id: serverToEdit ? serverToEdit.id : Date.now().toString(), + name: name.trim(), + baseUrl: normalizeUrl(baseUrl), + secretKey: secretKey.trim(), + online: serverToEdit ? serverToEdit.online : false, + sessions: serverToEdit ? serverToEdit.sessions : [] + }); + onClose(); + }; + + return ( +
+
e.stopPropagation()} style={{ maxWidth: '520px' }}> +
+
+ +

{serverToEdit ? 'Editar Servidor' : 'Adicionar Servidor WPPConnect'}

+
+ +
+ +
+
+
+ + setName(e.target.value)} + required + /> +
+ +
+ + setBaseUrl(e.target.value)} + required + /> +
+ +
+ +
+ setSecretKey(e.target.value)} + required + /> + +
+
+ + {testStatus && ( +
+ {testStatus.loading && } + {testStatus.success && } + {testStatus.error && } + {testStatus.loading ? 'Testando conexão...' : testStatus.message || testStatus.error} +
+ )} +
+ +
+ +
+ + +
+
+
+
+
+ ); +} diff --git a/src/components/wpp/ModalSession.jsx b/src/components/wpp/ModalSession.jsx new file mode 100644 index 0000000..4077634 --- /dev/null +++ b/src/components/wpp/ModalSession.jsx @@ -0,0 +1,135 @@ +import React, { useState, useEffect } from 'react'; +import { X, MessageSquare, Key, Globe, Shield } from 'lucide-react'; + +export default function ModalSession({ isOpen, onClose, onSave, sessionToEdit }) { + const [name, setName] = useState(''); + const [token, setToken] = useState(''); + const [webhook, setWebhook] = useState(''); + const [waitQrCode, setWaitQrCode] = useState(false); + const [proxyUrl, setProxyUrl] = useState(''); + + useEffect(() => { + if (sessionToEdit) { + setName(sessionToEdit.name || ''); + setToken(sessionToEdit.token || ''); + setWebhook(sessionToEdit.webhook || ''); + setWaitQrCode(sessionToEdit.waitQrCode || false); + setProxyUrl(sessionToEdit.proxy?.url || ''); + } else { + setName(''); + setToken(''); + setWebhook(''); + setWaitQrCode(false); + setProxyUrl(''); + } + }, [sessionToEdit, isOpen]); + + if (!isOpen) return null; + + const handleSubmit = (e) => { + e.preventDefault(); + if (!name.trim()) { + alert('Informe o nome da sessão.'); + return; + } + + onSave({ + name: name.trim(), + token: token.trim(), + webhook: webhook.trim(), + waitQrCode, + proxy: proxyUrl.trim() ? { url: proxyUrl.trim() } : null, + status: sessionToEdit ? sessionToEdit.status : 'disconnected', + connectedAt: sessionToEdit ? sessionToEdit.connectedAt : '', + qrCode: sessionToEdit ? sessionToEdit.qrCode : '' + }, sessionToEdit?.name); + onClose(); + }; + + return ( +
+
e.stopPropagation()} style={{ maxWidth: '520px' }}> +
+
+ +

{sessionToEdit ? 'Editar Sessão' : 'Nova Sessão WhatsApp'}

+
+ +
+ +
+
+
+ + setName(e.target.value)} + required + /> +
+ +
+ + setToken(e.target.value)} + /> +
+ +
+ + setWebhook(e.target.value)} + /> +
+ +
+ setWaitQrCode(e.target.checked)} + style={{ width: '18px', height: '18px', accentColor: '#00e676' }} + /> + +
+ +
+ + setProxyUrl(e.target.value)} + /> +
+
+ +
+ + +
+
+
+
+ ); +} diff --git a/src/components/wpp/ModalSettings.jsx b/src/components/wpp/ModalSettings.jsx new file mode 100644 index 0000000..a47e857 --- /dev/null +++ b/src/components/wpp/ModalSettings.jsx @@ -0,0 +1,143 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { X, Settings, Download, Upload, Database, Check, AlertCircle } from 'lucide-react'; +import { getSupabaseConfig, saveSupabaseConfig, exportAppWppBackup } from '../../utils/appWppStorage'; + +export default function ModalSettings({ isOpen, onClose, servers, onImportServers }) { + const [supabaseUrl, setSupabaseUrl] = useState(''); + const [supabaseKey, setSupabaseKey] = useState(''); + const [msg, setMsg] = useState(null); + const fileInputRef = useRef(null); + + useEffect(() => { + if (isOpen) { + const cfg = getSupabaseConfig(); + setSupabaseUrl(cfg.supabaseUrl || ''); + setSupabaseKey(cfg.supabaseAnonKey || ''); + setMsg(null); + } + }, [isOpen]); + + if (!isOpen) return null; + + const handleSaveSupabase = (e) => { + e.preventDefault(); + saveSupabaseConfig({ supabaseUrl: supabaseUrl.trim(), supabaseAnonKey: supabaseKey.trim() }); + setMsg({ type: 'success', text: 'Configurações salvas localmente com sucesso!' }); + setTimeout(() => setMsg(null), 3000); + }; + + const handleExportBackup = () => { + exportAppWppBackup(servers); + setMsg({ type: 'success', text: 'Backup exportado com sucesso!' }); + }; + + const handleImportFile = (e) => { + const file = e.target.files?.[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = (event) => { + try { + const json = JSON.parse(event.target.result); + if (json && Array.isArray(json.servers)) { + onImportServers(json.servers); + setMsg({ type: 'success', text: `${json.servers.length} servidor(es) importado(s) com sucesso!` }); + } else { + setMsg({ type: 'error', text: 'Formato inválido. O arquivo JSON deve conter um array "servers".' }); + } + } catch (err) { + setMsg({ type: 'error', text: 'Erro ao processar arquivo JSON: ' + err.message }); + } + }; + reader.readAsText(file); + }; + + return ( +
+
e.stopPropagation()} style={{ maxWidth: '540px' }}> +
+
+ +

Configurações & Backup (AppWPP)

+
+ +
+ +
+ {msg && ( +
+ {msg.type === 'success' ? : } + {msg.text} +
+ )} + + {/* Backup e Sincronização Local */} +
+

+ + Backup e Importação (appwpp-data.json) +

+

+ Exporte seus servidores e sessões para transferir entre máquinas ou importe um arquivo existente. +

+
+ + + +
+
+ + {/* Supabase Config */} +
+

+ + Conexão Supabase (Opcional) +

+

+ Configure a sincronização com banco de dados Supabase na nuvem. +

+
+
+ + setSupabaseUrl(e.target.value)} + /> +
+
+ + setSupabaseKey(e.target.value)} + /> +
+ +
+
+
+ +
+ +
+
+
+ ); +} diff --git a/src/components/wpp/WppSessionCard.jsx b/src/components/wpp/WppSessionCard.jsx new file mode 100644 index 0000000..95352ed --- /dev/null +++ b/src/components/wpp/WppSessionCard.jsx @@ -0,0 +1,156 @@ +import React from 'react'; +import { + Play, + X, + LogOut, + Activity, + Edit3, + Trash2, + QrCode, + Clock, + Key, + Copy, + Check +} from 'lucide-react'; + +export default function WppSessionCard({ + session, + onStart, + onCloseSession, + onLogout, + onCheckStatus, + onEdit, + onClear, + onRemove, + onShowQR +}) { + const [copiedToken, setCopiedToken] = React.useState(false); + + const getStatusBadge = () => { + switch (session.status) { + case 'connected': + return Conectado; + case 'qr': + return ( + + ); + case 'connecting': + return Conectando...; + default: + return Desconectado; + } + }; + + const handleCopyToken = () => { + if (!session.token) return; + navigator.clipboard.writeText(session.token); + setCopiedToken(true); + setTimeout(() => setCopiedToken(false), 2000); + }; + + return ( +
+
+ {session.name} + {getStatusBadge()} +
+ +
+ {session.connectedAt && ( +
+ + {session.connectedAt} +
+ )} + + {session.token && ( +
+ + {session.token.slice(0, 18)}... + {copiedToken ? : } +
+ )} +
+ +
+ + + + + + + + + + + + + +
+
+ ); +} diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..678c679 --- /dev/null +++ b/src/index.css @@ -0,0 +1,2150 @@ +:root { + --bg-primary: #0b0f19; + --bg-secondary: #111827; + --bg-card: #161e31; + --bg-card-hover: #1c263e; + --bg-input: #0f1523; + --border-color: #23304b; + --border-hover: #374b73; + --border-active: #0ea5e9; + + --text-primary: #f8fafc; + --text-secondary: #94a3b8; + --text-muted: #64748b; + + --accent-cyan: #06b6d4; + --accent-blue: #3b82f6; + --accent-emerald: #10b981; + --accent-amber: #f59e0b; + --accent-rose: #f43f5e; + --accent-purple: #a855f7; + + --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Courier New', monospace; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: var(--font-family); + background-color: var(--bg-primary); + color: var(--text-primary); + min-height: 100vh; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +/* Layout */ +.app-layout { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.container { + width: 100%; + max-width: 980px; + margin: 0 auto; + padding: 0 1.25rem; +} + +.main-content { + flex: 1; + padding: 2rem 0 4rem; +} + +/* Header */ +.header { + background-color: rgba(17, 24, 39, 0.85); + backdrop-filter: blur(12px); + border-bottom: 1px solid var(--border-color); + position: sticky; + top: 0; + z-index: 40; +} + +.header-container { + max-width: 980px; + margin: 0 auto; + padding: 1rem 1.25rem; + display: flex; + align-items: center; + justify-content: space-between; +} + +.header-brand { + display: flex; + align-items: center; + gap: 0.875rem; +} + +.brand-icon-wrapper { + background: linear-gradient(135deg, #0ea5e9, #3b82f6); + color: white; + padding: 0.5rem; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 14px rgba(14, 165, 233, 0.35); +} + +.brand-title { + font-size: 1.25rem; + font-weight: 700; + letter-spacing: -0.02em; + background: linear-gradient(90deg, #f8fafc, #93c5fd); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.brand-subtitle { + font-size: 0.8125rem; + color: var(--text-secondary); +} + +.guide-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background-color: var(--bg-card); + border: 1px solid var(--border-color); + color: #38bdf8; + padding: 0.5rem 0.875rem; + border-radius: 8px; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.guide-button:hover { + background-color: var(--bg-card-hover); + border-color: #38bdf8; + box-shadow: 0 2px 10px rgba(56, 189, 248, 0.2); +} + +/* Security Banner */ +.security-banner { + background: linear-gradient(90deg, rgba(16, 185, 129, 0.08), rgba(6, 182, 212, 0.08)); + border: 1px solid rgba(16, 185, 129, 0.25); + border-radius: 12px; + padding: 1rem 1.25rem; + margin-bottom: 2rem; + display: flex; + align-items: center; + gap: 1rem; +} + +.security-badge { + display: inline-flex; + align-items: center; + gap: 0.375rem; + background-color: rgba(16, 185, 129, 0.15); + color: #34d399; + border: 1px solid rgba(16, 185, 129, 0.3); + padding: 0.25rem 0.625rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + white-space: nowrap; +} + +.security-text { + font-size: 0.84rem; + color: #cbd5e1; + line-height: 1.45; +} + +.security-text strong { + color: #f8fafc; +} + +/* Card Converter */ +.card-converter { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 16px; + padding: 1.75rem; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); + margin-bottom: 2rem; +} + +.card-header-bar { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1.5rem; +} + +.card-header-title { + display: flex; + align-items: center; + gap: 0.625rem; +} + +.card-header-title h2 { + font-size: 1.15rem; + font-weight: 600; + color: var(--text-primary); +} + +.step-badge { + background-color: var(--bg-input); + border: 1px solid var(--border-color); + color: var(--text-muted); + font-size: 0.75rem; + padding: 0.25rem 0.625rem; + border-radius: 9999px; +} + +/* Upload Zone */ +.upload-section { + margin-bottom: 1.5rem; +} + +.dropzone { + border: 2px dashed var(--border-color); + border-radius: 14px; + padding: 2.75rem 1.5rem; + text-align: center; + background-color: rgba(15, 21, 35, 0.6); + cursor: pointer; + transition: all 0.25s ease; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.dropzone:hover, .dropzone-active { + border-color: var(--accent-cyan); + background-color: rgba(6, 182, 212, 0.05); + transform: translateY(-1px); +} + +.dropzone-icon { + color: var(--accent-cyan); + margin-bottom: 1rem; + transition: transform 0.2s ease; +} + +.dropzone:hover .dropzone-icon { + transform: translateY(-3px) scale(1.05); +} + +.dropzone-title { + font-size: 1.05rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.375rem; +} + +.dropzone-subtitle { + font-size: 0.8125rem; + color: var(--text-muted); + margin-bottom: 1.25rem; +} + +.btn-select-file { + background-color: rgba(14, 165, 233, 0.15); + border: 1px solid rgba(14, 165, 233, 0.4); + color: #38bdf8; + padding: 0.6rem 1.25rem; + border-radius: 8px; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-select-file:hover { + background-color: #0284c7; + color: white; + border-color: #0284c7; +} + +/* File Card Selected */ +.file-card { + display: flex; + align-items: center; + justify-content: space-between; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 1rem 1.25rem; +} + +.file-info-left { + display: flex; + align-items: center; + gap: 1rem; +} + +.file-icon-box { + background-color: rgba(16, 185, 129, 0.12); + color: var(--accent-emerald); + padding: 0.625rem; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; +} + +.file-name { + font-weight: 600; + font-size: 0.95rem; + color: var(--text-primary); + word-break: break-all; +} + +.file-meta { + display: flex; + align-items: center; + gap: 0.5rem; + margin-top: 0.25rem; +} + +.file-badge { + background-color: rgba(59, 130, 246, 0.15); + color: #60a5fa; + font-size: 0.7rem; + font-weight: 600; + padding: 0.125rem 0.5rem; + border-radius: 4px; +} + +.file-size { + font-size: 0.775rem; + color: var(--text-muted); +} + +.btn-remove-file { + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.5rem; + border-radius: 6px; + transition: all 0.2s ease; +} + +.btn-remove-file:hover { + background-color: rgba(244, 63, 94, 0.15); + color: var(--accent-rose); +} + +/* Password Section */ +.form-controls-wrapper { + margin-top: 1.5rem; + border-top: 1px solid var(--border-color); + padding-top: 1.5rem; +} + +.password-section { + margin-bottom: 1.5rem; +} + +.password-label { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + color: var(--text-secondary); + margin-bottom: 0.5rem; +} + +.password-input-wrapper { + position: relative; + display: flex; + align-items: center; +} + +.password-input { + width: 100%; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + color: var(--text-primary); + padding: 0.75rem 2.75rem 0.75rem 1rem; + border-radius: 10px; + font-size: 0.95rem; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.password-input:focus { + outline: none; + border-color: var(--accent-cyan); + box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.15); +} + +.password-toggle-btn { + position: absolute; + right: 0.75rem; + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.35rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; +} + +.password-toggle-btn:hover { + color: var(--text-primary); +} + +.password-hint { + font-size: 0.75rem; + color: var(--text-muted); + margin-top: 0.375rem; +} + +/* Actions Bar */ +.actions-bar { + display: flex; + align-items: center; + gap: 1rem; + margin-top: 1.25rem; +} + +.btn-convert { + flex: 1; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.625rem; + background: linear-gradient(135deg, #0ea5e9, #2563eb); + color: white; + border: none; + padding: 0.85rem 1.5rem; + border-radius: 10px; + font-size: 0.95rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 4px 15px rgba(14, 165, 233, 0.3); +} + +.btn-convert:hover:not(:disabled) { + background: linear-gradient(135deg, #0284c7, #1d4ed8); + box-shadow: 0 6px 20px rgba(14, 165, 233, 0.45); + transform: translateY(-1px); +} + +.btn-convert:disabled { + opacity: 0.7; + cursor: not-allowed; +} + +.btn-reset { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + color: var(--text-secondary); + padding: 0.85rem 1.25rem; + border-radius: 10px; + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-reset:hover:not(:disabled) { + background-color: var(--bg-card-hover); + color: var(--text-primary); +} + +/* Alert Error */ +.alert-error-box { + margin-top: 1.5rem; + background-color: rgba(244, 63, 94, 0.1); + border: 1px solid rgba(244, 63, 94, 0.3); + color: #fda4af; + padding: 1rem 1.25rem; + border-radius: 10px; + display: flex; + align-items: flex-start; + gap: 0.75rem; +} + +.alert-error-text { + font-size: 0.875rem; + line-height: 1.4; +} + +/* Results Container */ +.results-container { + display: flex; + flex-direction: column; + gap: 1.75rem; + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} + +/* Certificate Info Card */ +.card-cert-info { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 16px; + padding: 1.5rem 1.75rem; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25); +} + +.cert-info-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1.25rem; + flex-wrap: wrap; + gap: 0.75rem; +} + +.cert-info-title-group { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.cert-info-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--text-primary); +} + +.badge-status { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; +} + +.badge-active { + background-color: rgba(16, 185, 129, 0.15); + color: #34d399; + border: 1px solid rgba(16, 185, 129, 0.3); +} + +.badge-warning { + background-color: rgba(245, 158, 11, 0.15); + color: #fbbf24; + border: 1px solid rgba(245, 158, 11, 0.3); +} + +.badge-expired { + background-color: rgba(244, 63, 94, 0.15); + color: #fb7185; + border: 1px solid rgba(244, 63, 94, 0.3); +} + +.cert-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1.25rem; +} + +.cert-grid-item.full-width { + grid-column: span 2; +} + +.cert-label { + display: flex; + align-items: center; + gap: 0.375rem; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-muted); + margin-bottom: 0.25rem; +} + +.cert-value { + font-size: 0.95rem; + color: var(--text-primary); + word-break: break-all; +} + +.font-highlight { + font-size: 1.05rem; + font-weight: 600; + color: #e0f2fe; +} + +.tax-id-tag { + display: inline-block; + background-color: rgba(14, 165, 233, 0.15); + color: #38bdf8; + border: 1px solid rgba(14, 165, 233, 0.3); + padding: 0.2rem 0.6rem; + border-radius: 6px; + font-size: 0.8rem; + margin-top: 0.375rem; +} + +.cert-mono { + font-family: var(--font-mono); + font-size: 0.85rem; + color: #cbd5e1; +} + +.tag-pill { + font-size: 0.7rem; + font-weight: 600; + padding: 0.15rem 0.5rem; + border-radius: 9999px; + margin-left: 0.5rem; +} + +.tag-pill-success { + background-color: rgba(16, 185, 129, 0.15); + color: #34d399; + border: 1px solid rgba(16, 185, 129, 0.3); +} + +/* Output Files Section */ +.output-section { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 16px; + padding: 1.75rem; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25); +} + +.output-header-bar { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1.25rem; + flex-wrap: wrap; + gap: 1rem; +} + +.output-heading { + font-size: 1.15rem; + font-weight: 600; + color: var(--text-primary); +} + +.output-subheading { + font-size: 0.8125rem; + color: var(--text-muted); +} + +.btn-download-zip { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: linear-gradient(135deg, #10b981, #059669); + color: white; + border: none; + padding: 0.65rem 1.25rem; + border-radius: 10px; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 4px 14px rgba(16, 185, 129, 0.3); +} + +.btn-download-zip:hover { + background: linear-gradient(135deg, #059669, #047857); + box-shadow: 0 6px 18px rgba(16, 185, 129, 0.45); + transform: translateY(-1px); +} + +/* Quick Cards */ +.quick-download-cards { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.quick-card { + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 1rem; + cursor: pointer; + transition: all 0.2s ease; +} + +.quick-card:hover { + border-color: var(--border-hover); + background-color: var(--bg-card-hover); +} + +.quick-card-selected { + border-color: var(--accent-cyan); + background-color: rgba(6, 182, 212, 0.05); + box-shadow: 0 0 0 1px var(--accent-cyan); +} + +.quick-card-top { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.625rem; +} + +.badge-blue { + background-color: rgba(59, 130, 246, 0.15); + color: #60a5fa; + border: 1px solid rgba(59, 130, 246, 0.3); +} + +.badge-purple { + background-color: rgba(168, 85, 247, 0.15); + color: #c084fc; + border: 1px solid rgba(168, 85, 247, 0.3); +} + +.badge-amber { + background-color: rgba(245, 158, 11, 0.15); + color: #fbbf24; + border: 1px solid rgba(245, 158, 11, 0.3); +} + +.btn-icon-download { + background-color: rgba(255, 255, 255, 0.05); + border: 1px solid var(--border-color); + color: var(--text-primary); + border-radius: 6px; + padding: 0.375rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.btn-icon-download:hover { + background-color: var(--accent-cyan); + color: #0b0f19; + border-color: var(--accent-cyan); +} + +.quick-card-name { + font-family: var(--font-mono); + font-size: 0.95rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.25rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.quick-card-title { + font-size: 0.775rem; + color: var(--text-muted); +} + +/* File Viewer */ +.file-viewer-container { + border: 1px solid var(--border-color); + border-radius: 12px; + overflow: hidden; + background-color: var(--bg-input); +} + +.viewer-tab-bar { + display: flex; + align-items: center; + justify-content: space-between; + background-color: rgba(17, 24, 39, 0.95); + border-bottom: 1px solid var(--border-color); + padding: 0.5rem 0.75rem; + flex-wrap: wrap; + gap: 0.5rem; +} + +.viewer-tabs { + display: flex; + align-items: center; + gap: 0.25rem; +} + +.viewer-tab-btn { + display: inline-flex; + align-items: center; + gap: 0.375rem; + background: transparent; + border: none; + color: var(--text-secondary); + padding: 0.45rem 0.75rem; + border-radius: 6px; + font-size: 0.8125rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.viewer-tab-btn:hover { + color: var(--text-primary); + background-color: rgba(255, 255, 255, 0.05); +} + +.viewer-tab-btn-active { + color: var(--accent-cyan); + background-color: rgba(6, 182, 212, 0.12); + font-weight: 600; +} + +.viewer-tab-actions { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.btn-copy-code, .btn-download-file-direct { + display: inline-flex; + align-items: center; + gap: 0.375rem; + background-color: var(--bg-card); + border: 1px solid var(--border-color); + color: var(--text-secondary); + padding: 0.4rem 0.75rem; + border-radius: 6px; + font-size: 0.775rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-copy-code:hover, .btn-download-file-direct:hover { + background-color: var(--bg-card-hover); + color: var(--text-primary); + border-color: var(--border-hover); +} + +.btn-download-file-direct { + color: #38bdf8; + border-color: rgba(56, 189, 248, 0.3); +} + +.btn-download-file-direct:hover { + background-color: rgba(56, 189, 248, 0.1); + border-color: #38bdf8; +} + +.viewer-meta-bar { + padding: 0.625rem 1rem; + background-color: rgba(11, 15, 25, 0.5); + border-bottom: 1px solid var(--border-color); + font-size: 0.775rem; + color: var(--text-secondary); + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 0.5rem; +} + +.alert-key-security { + display: inline-flex; + align-items: center; + gap: 0.375rem; + color: #fbbf24; + font-weight: 500; +} + +.code-block-wrapper { + max-height: 280px; + overflow-y: auto; + padding: 1rem; + background-color: #080c14; +} + +.code-pre { + font-family: var(--font-mono); + font-size: 0.8125rem; + line-height: 1.5; + color: #a5b4fc; + white-space: pre; + word-break: normal; +} + +/* OpenSSL Reference */ +.openssl-ref-card { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 14px; + overflow: hidden; +} + +.openssl-ref-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.15rem 1.5rem; + cursor: pointer; + background-color: rgba(17, 24, 39, 0.6); + transition: background-color 0.2s ease; +} + +.openssl-ref-header:hover { + background-color: rgba(17, 24, 39, 0.9); +} + +.openssl-ref-title { + display: flex; + align-items: center; + gap: 0.625rem; + font-size: 0.95rem; + font-weight: 600; + color: var(--text-primary); +} + +.btn-toggle-ref { + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; +} + +.openssl-ref-body { + padding: 1.25rem 1.5rem; + border-top: 1px solid var(--border-color); + background-color: rgba(11, 15, 25, 0.4); +} + +.openssl-ref-intro { + font-size: 0.8125rem; + color: var(--text-secondary); + margin-bottom: 1rem; +} + +.cmd-list { + display: flex; + flex-direction: column; + gap: 0.875rem; +} + +.cmd-item { + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 0.875rem 1rem; +} + +.cmd-item-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; + font-size: 0.8125rem; + color: #e2e8f0; +} + +.cmd-flag-tag { + font-family: var(--font-mono); + background-color: rgba(6, 182, 212, 0.12); + color: var(--accent-cyan); + font-size: 0.725rem; + padding: 0.125rem 0.5rem; + border-radius: 4px; +} + +.cmd-code-line { + display: flex; + align-items: center; + justify-content: space-between; + background-color: #080c14; + border: 1px solid rgba(255, 255, 255, 0.05); + border-radius: 6px; + padding: 0.5rem 0.75rem; + margin-bottom: 0.375rem; +} + +.cmd-code-line code { + font-family: var(--font-mono); + font-size: 0.8rem; + color: #38bdf8; + word-break: break-all; +} + +.btn-copy-cmd { + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.25rem; + margin-left: 0.5rem; + border-radius: 4px; +} + +.btn-copy-cmd:hover { + color: var(--text-primary); +} + +.cmd-desc { + font-size: 0.75rem; + color: var(--text-muted); +} + +/* Modal Guide */ +.modal-backdrop { + position: fixed; + inset: 0; + background-color: rgba(0, 0, 0, 0.75); + backdrop-filter: blur(8px); + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + padding: 1.25rem; +} + +.modal-dialog { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 18px; + width: 100%; + max-width: 760px; + max-height: 90vh; + display: flex; + flex-direction: column; + overflow: hidden; + box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5); + animation: modalScale 0.25s ease; +} + +@keyframes modalScale { + from { transform: scale(0.95); opacity: 0; } + to { transform: scale(1); opacity: 1; } +} + +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 1.75rem; + border-bottom: 1px solid var(--border-color); + background-color: rgba(17, 24, 39, 0.8); +} + +.modal-title-box { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.modal-title { + font-size: 1.15rem; + font-weight: 600; + color: var(--text-primary); +} + +.modal-subtitle { + font-size: 0.8rem; + color: var(--text-muted); +} + +.modal-close-btn { + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.375rem; + border-radius: 6px; +} + +.modal-close-btn:hover { + color: var(--text-primary); +} + +.modal-tabs { + display: flex; + border-bottom: 1px solid var(--border-color); + background-color: var(--bg-input); + overflow-x: auto; + padding: 0.25rem 1rem 0; + gap: 0.25rem; +} + +.modal-tab-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: transparent; + border: none; + border-bottom: 2px solid transparent; + color: var(--text-secondary); + padding: 0.75rem 1rem; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + white-space: nowrap; +} + +.modal-tab-btn:hover { + color: var(--text-primary); +} + +.modal-tab-btn-active { + color: var(--accent-cyan); + border-bottom-color: var(--accent-cyan); + font-weight: 600; +} + +.modal-body { + padding: 1.75rem; + overflow-y: auto; + flex: 1; +} + +.guide-content h4 { + font-size: 1.05rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.guide-content p { + font-size: 0.875rem; + color: var(--text-secondary); + margin-bottom: 1.25rem; + line-height: 1.5; +} + +.guide-content h5 { + font-size: 0.9rem; + font-weight: 600; + color: #e2e8f0; + margin: 1.25rem 0 0.5rem; +} + +.guide-code-box { + position: relative; + background-color: #080c14; + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 1rem; + margin-bottom: 1rem; +} + +.guide-code-box pre { + font-family: var(--font-mono); + font-size: 0.8125rem; + color: #7dd3fc; + overflow-x: auto; + line-height: 1.45; +} + +.btn-copy-guide { + position: absolute; + top: 0.75rem; + right: 0.75rem; + background-color: rgba(255, 255, 255, 0.08); + border: 1px solid var(--border-color); + color: var(--text-primary); + border-radius: 6px; + padding: 0.375rem; + cursor: pointer; +} + +.btn-copy-guide:hover { + background-color: var(--accent-cyan); + color: #0b0f19; +} + +.guide-steps { + margin-left: 1.25rem; + font-size: 0.875rem; + color: var(--text-secondary); + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.guide-steps strong { + color: #f8fafc; +} + +.guide-note { + background-color: rgba(14, 165, 233, 0.08); + border-left: 3px solid var(--accent-cyan); + padding: 0.625rem 0.875rem; + border-radius: 4px; + font-size: 0.8125rem; + color: #bae6fd; + margin-top: 1rem; +} + +.modal-footer { + padding: 1rem 1.75rem; + border-top: 1px solid var(--border-color); + background-color: rgba(17, 24, 39, 0.6); + display: flex; + justify-content: flex-end; +} + +.btn-modal-close { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + color: var(--text-primary); + padding: 0.55rem 1.25rem; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-modal-close:hover { + background-color: var(--bg-card-hover); + border-color: var(--border-hover); +} + +/* Footer */ +.footer { + border-top: 1px solid var(--border-color); + background-color: var(--bg-secondary); + padding: 1.5rem 0; + margin-top: auto; +} + +.footer-content { + max-width: 980px; + margin: 0 auto; + padding: 0 1.25rem; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + font-size: 0.8rem; + color: var(--text-muted); + text-align: center; +} + +.footer-links { + display: flex; + align-items: center; + gap: 0.75rem; + flex-wrap: wrap; + justify-content: center; +} + +.link-plain { + background: transparent; + border: none; + color: #38bdf8; + cursor: pointer; + font-size: 0.8rem; + padding: 0; + text-decoration: underline; +} + +.link-plain:hover { + color: #7dd3fc; +} + +.footer-shield { + display: inline-flex; + align-items: center; + gap: 0.25rem; + color: #34d399; +} + +/* Utilities */ +.text-cyan { color: var(--accent-cyan); } +.text-emerald { color: var(--accent-emerald); } +.text-sm { font-size: 0.75rem; } + +.animate-spin { + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* Responsividade */ +@media (max-width: 768px) { + .cert-grid { + grid-template-columns: 1fr; + } + .cert-grid-item.full-width { + grid-column: span 1; + } + .quick-download-cards { + grid-template-columns: 1fr; + } + .actions-bar { + flex-direction: column; + } + .btn-convert, .btn-reset { + width: 100%; + } + .viewer-tab-bar { + flex-direction: column; + align-items: stretch; + } + .viewer-tab-actions { + justify-content: flex-end; + } + .header-container { + flex-direction: column; + gap: 0.75rem; + align-items: stretch; + } + .app-nav-tabs { + justify-content: center; + } + .wpp-app-container { + flex-direction: column; + } + .wpp-sidebar { + width: 100%; + border-right: none; + border-bottom: 1px solid var(--border-color); + } +} + +/* ========================================================================= + APP SWITCHER & APPWPP (WHATSAPP SESSION MANAGER) STYLES + ========================================================================= */ + +/* Top Navigation Tabs */ +.app-nav-tabs { + display: flex; + align-items: center; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + padding: 0.25rem; + border-radius: 12px; + gap: 0.25rem; +} + +.app-nav-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: transparent; + border: none; + color: var(--text-secondary); + padding: 0.45rem 0.95rem; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.app-nav-btn:hover { + color: var(--text-primary); +} + +.app-nav-btn-active { + background-color: var(--bg-card); + color: #38bdf8; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); + font-weight: 600; +} + +.app-nav-btn-active.app-nav-btn-wpp { + color: #34d399; +} + +.nav-badge-pill { + background-color: rgba(16, 185, 129, 0.2); + color: #34d399; + border-radius: 9999px; + font-size: 0.7rem; + padding: 0.1rem 0.45rem; + font-weight: 700; +} + +/* AppWPP Layout */ +.wpp-view-wrapper { + width: 100%; + max-width: 1260px; + margin: 0 auto; + padding: 0 1.25rem; +} + +.wpp-app-container { + display: flex; + min-height: 720px; + background-color: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: 16px; + overflow: hidden; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); + position: relative; +} + +/* Sidebar */ +.wpp-sidebar { + width: 290px; + flex-shrink: 0; + background-color: #080c14; + border-right: 1px solid var(--border-color); + display: flex; + flex-direction: column; +} + +.wpp-sidebar-header { + padding: 1.25rem 1.15rem; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid var(--border-color); +} + +.wpp-logo-badge { + background: linear-gradient(135deg, #059669, #10b981); + color: white; + padding: 0.45rem; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 10px rgba(16, 185, 129, 0.3); +} + +.wpp-app-title { + font-size: 1.1rem; + font-weight: 700; + color: #f8fafc; + line-height: 1.2; +} + +.wpp-app-sub { + font-size: 0.72rem; + color: #64748b; +} + +.btn-icon-wpp { + background: transparent; + border: 1px solid var(--border-color); + color: var(--text-muted); + padding: 0.45rem; + border-radius: 8px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.btn-icon-wpp:hover { + background-color: var(--bg-card-hover); + color: var(--text-primary); + border-color: var(--border-hover); +} + +.wpp-servers-section { + padding: 1rem 0.85rem; + flex: 1; + overflow-y: auto; +} + +.wpp-servers-header { + display: flex; + align-items: center; + justify-content: space-between; + font-size: 0.72rem; + letter-spacing: 0.06em; + font-weight: 700; + color: #64748b; + margin-bottom: 0.75rem; + padding: 0 0.4rem; +} + +.btn-icon-add-server { + background: rgba(16, 185, 129, 0.15); + border: 1px solid rgba(16, 185, 129, 0.3); + color: #34d399; + border-radius: 6px; + padding: 0.25rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.btn-icon-add-server:hover { + background: #10b981; + color: white; +} + +.wpp-servers-list { + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.wpp-server-item { + display: flex; + align-items: center; + gap: 0.65rem; + padding: 0.7rem 0.8rem; + border-radius: 10px; + cursor: pointer; + transition: all 0.2s ease; + border: 1px solid transparent; + background-color: transparent; +} + +.wpp-server-item:hover { + background-color: rgba(255, 255, 255, 0.03); +} + +.wpp-server-active { + background-color: rgba(16, 185, 129, 0.09) !important; + border-color: rgba(16, 185, 129, 0.3) !important; +} + +.wpp-server-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; +} + +.dot-online { + background-color: #10b981; + box-shadow: 0 0 8px #10b981; +} + +.dot-offline { + background-color: #64748b; +} + +.wpp-server-info-col { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; +} + +.wpp-server-name-text { + font-size: 0.875rem; + font-weight: 600; + color: #f8fafc; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.wpp-server-url-text { + font-size: 0.72rem; + color: #64748b; + font-family: var(--font-mono); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.btn-edit-server-mini { + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.25rem; + border-radius: 4px; +} + +.btn-edit-server-mini:hover { + color: var(--text-primary); +} + +.wpp-sidebar-footer { + padding: 0.75rem 1rem; + border-top: 1px solid var(--border-color); + font-size: 0.72rem; + color: #475569; + text-align: center; +} + +/* Main Area */ +.wpp-main-area { + flex: 1; + display: flex; + flex-direction: column; + background-color: var(--bg-card); + min-width: 0; +} + +.wpp-server-view { + display: flex; + flex-direction: column; + height: 100%; +} + +.wpp-server-topbar { + padding: 1.25rem 1.75rem; + border-bottom: 1px solid var(--border-color); + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 1rem; + background-color: rgba(17, 24, 39, 0.4); +} + +.wpp-server-title-box { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.wpp-view-server-name { + font-size: 1.25rem; + font-weight: 700; + color: #f8fafc; +} + +.wpp-view-server-url { + font-size: 0.8rem; + font-family: var(--font-mono); + color: #38bdf8; +} + +.wpp-badge-status { + font-size: 0.7rem; + font-weight: 700; + padding: 0.15rem 0.5rem; + border-radius: 9999px; + text-transform: uppercase; +} + +.badge-online { + background: rgba(16, 185, 129, 0.15); + color: #34d399; + border: 1px solid rgba(16, 185, 129, 0.3); +} + +.badge-offline { + background: rgba(100, 116, 139, 0.15); + color: #94a3b8; + border: 1px solid rgba(100, 116, 139, 0.3); +} + +.wpp-server-actions-group { + display: flex; + align-items: center; + gap: 0.625rem; + flex-wrap: wrap; +} + +.btn-wpp-secondary-top, .btn-wpp-danger-top { + display: inline-flex; + align-items: center; + gap: 0.375rem; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + color: var(--text-secondary); + padding: 0.45rem 0.85rem; + border-radius: 8px; + font-size: 0.825rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-wpp-secondary-top:hover { + background-color: var(--bg-card-hover); + color: var(--text-primary); + border-color: var(--border-hover); +} + +.btn-wpp-danger-top { + color: #fda4af; + border-color: rgba(244, 63, 94, 0.3); +} + +.btn-wpp-danger-top:hover { + background-color: rgba(244, 63, 94, 0.15); + color: #fb7185; +} + +.wpp-sessions-toolbar { + padding: 1rem 1.75rem; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid var(--border-color); + gap: 1rem; + flex-wrap: wrap; +} + +.wpp-search-box { + display: flex; + align-items: center; + gap: 0.5rem; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 0.45rem 0.85rem; + width: 280px; +} + +.wpp-search-input { + background: transparent; + border: none; + color: var(--text-primary); + font-size: 0.85rem; + width: 100%; + outline: none; +} + +.btn-new-session { + display: inline-flex; + align-items: center; + gap: 0.375rem; + background: linear-gradient(135deg, #059669, #10b981); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3); +} + +.btn-new-session:hover { + background: linear-gradient(135deg, #047857, #059669); + transform: translateY(-1px); +} + +.wpp-sessions-grid { + padding: 1.5rem 1.75rem; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); + gap: 1.25rem; + overflow-y: auto; + flex: 1; + align-content: flex-start; +} + +/* Session Card */ +.wpp-session-card { + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 1.15rem; + display: flex; + flex-direction: column; + gap: 0.85rem; + transition: all 0.2s ease; +} + +.wpp-session-card:hover { + border-color: var(--border-hover); + background-color: rgba(22, 30, 49, 0.7); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); +} + +.wpp-session-card-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; +} + +.wpp-session-name { + font-weight: 600; + font-size: 0.95rem; + color: #f8fafc; + font-family: var(--font-mono); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.wpp-status-pill { + font-size: 0.725rem; + font-weight: 600; + padding: 0.15rem 0.55rem; + border-radius: 9999px; + display: inline-flex; + align-items: center; + gap: 0.25rem; + white-space: nowrap; +} + +.status-connected { + background-color: rgba(16, 185, 129, 0.15); + color: #34d399; + border: 1px solid rgba(16, 185, 129, 0.3); +} + +.status-qr { + background-color: rgba(245, 158, 11, 0.15); + color: #fbbf24; + border: 1px solid rgba(245, 158, 11, 0.3); +} + +.status-qr.clickable { + cursor: pointer; + transition: all 0.2s ease; +} + +.status-qr.clickable:hover { + background-color: rgba(245, 158, 11, 0.3); +} + +.status-connecting { + background-color: rgba(14, 165, 233, 0.15); + color: #38bdf8; + border: 1px solid rgba(14, 165, 233, 0.3); +} + +.status-disconnected { + background-color: rgba(100, 116, 139, 0.15); + color: #94a3b8; + border: 1px solid rgba(100, 116, 139, 0.3); +} + +.wpp-session-card-body { + display: flex; + flex-direction: column; + gap: 0.4rem; + font-size: 0.78rem; + color: var(--text-muted); +} + +.wpp-session-meta-item { + display: flex; + align-items: center; + gap: 0.4rem; + color: #94a3b8; +} + +.wpp-session-token-box { + display: flex; + align-items: center; + gap: 0.4rem; + background-color: rgba(0, 0, 0, 0.3); + padding: 0.25rem 0.5rem; + border-radius: 6px; + cursor: pointer; + font-family: var(--font-mono); + color: #7dd3fc; + font-size: 0.725rem; +} + +.wpp-session-token-text { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.wpp-session-card-actions { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + margin-top: auto; + border-top: 1px solid rgba(255, 255, 255, 0.05); + padding-top: 0.75rem; +} + +.btn-wpp-action { + display: inline-flex; + align-items: center; + gap: 0.3rem; + padding: 0.35rem 0.6rem; + border-radius: 6px; + font-size: 0.75rem; + font-weight: 500; + cursor: pointer; + border: 1px solid transparent; + transition: all 0.2s ease; +} + +.btn-wpp-primary { + background-color: rgba(16, 185, 129, 0.15); + border-color: rgba(16, 185, 129, 0.3); + color: #34d399; +} +.btn-wpp-primary:hover { + background-color: #10b981; + color: white; +} + +.btn-wpp-secondary { + background-color: var(--bg-card); + border-color: var(--border-color); + color: var(--text-secondary); +} +.btn-wpp-secondary:hover { + background-color: var(--bg-card-hover); + color: var(--text-primary); +} + +.btn-wpp-warning { + background-color: rgba(245, 158, 11, 0.1); + border-color: rgba(245, 158, 11, 0.25); + color: #fbbf24; +} +.btn-wpp-warning:hover { + background-color: rgba(245, 158, 11, 0.25); +} + +.btn-wpp-danger { + background-color: rgba(244, 63, 94, 0.1); + border-color: rgba(244, 63, 94, 0.25); + color: #fda4af; +} +.btn-wpp-danger:hover { + background-color: rgba(244, 63, 94, 0.25); +} + +/* Empty states */ +.wpp-empty-sessions, .wpp-empty-app { + grid-column: 1 / -1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + padding: 4rem 1.5rem; + gap: 0.75rem; +} + +.wpp-empty-sessions h3, .wpp-empty-app h2 { + color: var(--text-primary); + font-size: 1.15rem; + font-weight: 600; +} + +.wpp-empty-sessions p, .wpp-empty-app p { + color: var(--text-muted); + font-size: 0.85rem; + max-width: 420px; +} + +/* Form label & results */ +.wpp-form-label { + display: block; + font-size: 0.825rem; + font-weight: 500; + color: var(--text-secondary); + margin-bottom: 0.35rem; +} + +.wpp-test-result { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.65rem 0.85rem; + border-radius: 8px; + font-size: 0.8rem; + margin-top: 0.25rem; +} + +.wpp-test-success { + background-color: rgba(16, 185, 129, 0.12); + border: 1px solid rgba(16, 185, 129, 0.3); + color: #34d399; +} + +.wpp-test-error { + background-color: rgba(244, 63, 94, 0.12); + border: 1px solid rgba(244, 63, 94, 0.3); + color: #fb7185; +} + +.wpp-test-loading { + background-color: rgba(14, 165, 233, 0.12); + border: 1px solid rgba(14, 165, 233, 0.3); + color: #38bdf8; +} + +.wpp-qr-box { + background-color: white; + padding: 0.75rem; + border-radius: 12px; + display: inline-block; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); +} + +.wpp-server-session-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.65rem 0.85rem; + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 8px; +} + +.wpp-settings-card { + background-color: var(--bg-input); + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 1.15rem; +} + +/* Toast Container */ +.wpp-toasts-container { + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + z-index: 200; + display: flex; + flex-direction: column; + gap: 0.5rem; + max-width: 380px; +} + +.wpp-toast { + display: flex; + align-items: center; + gap: 0.6rem; + padding: 0.75rem 1rem; + border-radius: 10px; + font-size: 0.85rem; + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4); + backdrop-filter: blur(8px); + animation: slideInRight 0.25s ease; +} + +@keyframes slideInRight { + from { transform: translateX(50px); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} + +.toast-success { + background-color: rgba(6, 78, 59, 0.95); + border: 1px solid #10b981; + color: #a7f3d0; +} + +.toast-error { + background-color: rgba(136, 19, 55, 0.95); + border: 1px solid #f43f5e; + color: #fecdd3; +} + +.toast-warning { + background-color: rgba(120, 53, 15, 0.95); + border: 1px solid #f59e0b; + color: #fde68a; +} + +.toast-info { + background-color: rgba(12, 74, 110, 0.95); + border: 1px solid #0ea5e9; + color: #bae6fd; +} + +/* Modal Confirm */ +.modal-confirm-dialog { + border: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: 0 25px 60px rgba(0, 0, 0, 0.7); +} + +.modal-confirm-icon-box { + padding: 0.45rem; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; +} + +.icon-box-warning { + background-color: rgba(245, 158, 11, 0.15); + border: 1px solid rgba(245, 158, 11, 0.35); + color: #fbbf24; +} + +.icon-box-danger { + background-color: rgba(244, 63, 94, 0.15); + border: 1px solid rgba(244, 63, 94, 0.35); + color: #fb7185; +} + +.modal-confirm-message { + font-size: 1.05rem; + font-weight: 600; + color: #f8fafc; + line-height: 1.45; + margin-bottom: 0.5rem; +} + +.modal-confirm-desc { + font-size: 0.85rem; + color: #94a3b8; + line-height: 1.45; +} + +.btn-modal-cancel { + background-color: var(--bg-card); + border: 1px solid var(--border-color); + color: var(--text-secondary); + padding: 0.55rem 1.15rem; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-modal-cancel:hover { + background-color: var(--bg-card-hover); + color: var(--text-primary); + border-color: var(--border-hover); +} + +.btn-modal-action-confirm { + display: inline-flex; + align-items: center; + gap: 0.45rem; + padding: 0.55rem 1.25rem; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 600; + cursor: pointer; + border: none; + transition: all 0.2s ease; +} + +.btn-confirm-warning { + background: linear-gradient(135deg, #d97706, #f59e0b); + color: #0b0f19; + box-shadow: 0 4px 14px rgba(245, 158, 11, 0.3); +} + +.btn-confirm-warning:hover { + background: linear-gradient(135deg, #b45309, #d97706); + box-shadow: 0 6px 18px rgba(245, 158, 11, 0.45); + transform: translateY(-1px); +} + +.btn-confirm-danger { + background: linear-gradient(135deg, #e11d48, #f43f5e); + color: white; + box-shadow: 0 4px 14px rgba(244, 63, 94, 0.3); +} + +.btn-confirm-danger:hover { + background: linear-gradient(135deg, #be123c, #e11d48); + box-shadow: 0 6px 18px rgba(244, 63, 94, 0.45); + transform: translateY(-1px); +} + + diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 0000000..b9a1a6d --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.jsx' + +createRoot(document.getElementById('root')).render( + + + , +) diff --git a/src/utils/appWppStorage.js b/src/utils/appWppStorage.js new file mode 100644 index 0000000..d232f48 --- /dev/null +++ b/src/utils/appWppStorage.js @@ -0,0 +1,72 @@ +import initialData from './initialWppData.json'; + +const STORAGE_KEY = 'appwpp_servers_data_v1'; +const SUPABASE_KEY = 'appwpp_supabase_config_v1'; + +/** + * Carrega a lista de servidores do localStorage ou usa o arquivo inicial + */ +export function getStoredServers() { + try { + const raw = localStorage.getItem(STORAGE_KEY); + if (raw) { + const parsed = JSON.parse(raw); + if (parsed && Array.isArray(parsed.servers)) { + return parsed.servers; + } + } + } catch (e) { + console.warn('Erro ao carregar do localStorage:', e); + } + + // Fallback para dados iniciais existentes em D:\Flavio\Projetos\AppWPP + if (initialData && Array.isArray(initialData.servers)) { + saveServers(initialData.servers); + return initialData.servers; + } + + return []; +} + +/** + * Salva a lista de servidores no localStorage + */ +export function saveServers(servers) { + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify({ servers }, null, 2)); + } catch (e) { + console.error('Erro ao salvar servidores no localStorage:', e); + } +} + +/** + * Configuração Supabase + */ +export function getSupabaseConfig() { + try { + const raw = localStorage.getItem(SUPABASE_KEY); + return raw ? JSON.parse(raw) : { supabaseUrl: '', supabaseAnonKey: '' }; + } catch { + return { supabaseUrl: '', supabaseAnonKey: '' }; + } +} + +export function saveSupabaseConfig(config) { + localStorage.setItem(SUPABASE_KEY, JSON.stringify(config)); +} + +/** + * Exporta backup em formato JSON compatível com o appwpp-data.json original + */ +export function exportAppWppBackup(servers) { + const data = JSON.stringify({ servers }, null, 2); + const blob = new Blob([data], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `appwpp-data-backup-${new Date().toISOString().slice(0, 10)}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} diff --git a/src/utils/certConverter.js b/src/utils/certConverter.js new file mode 100644 index 0000000..aaad76d --- /dev/null +++ b/src/utils/certConverter.js @@ -0,0 +1,199 @@ +import forge from 'node-forge'; + +/** + * Extrai CPF ou CNPJ de uma string de texto (ex: Common Name ou OUs de certificados ICP-Brasil) + */ +function extractTaxId(text) { + if (!text) return null; + // Procura padrão CNPJ (14 dígitos) ou CPF (11 dígitos) + const cnpjMatch = text.match(/\b\d{2}\.?\d{3}\.?\d{3}\/?\d{4}-?\d{2}\b/) || text.match(/:(\d{14})\b/); + if (cnpjMatch) { + const raw = (cnpjMatch[1] || cnpjMatch[0]).replace(/\D/g, ''); + if (raw.length === 14) { + return { type: 'CNPJ', value: raw.replace(/^(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})$/, '$1.$2.$3/$4-$5') }; + } + } + const cpfMatch = text.match(/\b\d{3}\.?\d{3}\.?\d{3}-?\d{2}\b/) || text.match(/:(\d{11})\b/); + if (cpfMatch) { + const raw = (cpfMatch[1] || cpfMatch[0]).replace(/\D/g, ''); + if (raw.length === 11) { + return { type: 'CPF', value: raw.replace(/^(\d{3})(\d{3})(\d{3})(\d{2})$/, '$1.$2.$3-$4') }; + } + } + return null; +} + +/** + * Converte um arquivo PFX/P12 (ArrayBuffer) para os formatos CRT, PEM e KEY. + * + * Equivalência OpenSSL: + * - PEM: openssl pkcs12 -in [cert].pfx -nokeys -out [cert].pem + * - CRT: openssl pkcs12 -in [cert].pfx -clcerts -nokeys -out [cert].crt + * - KEY: openssl pkcs12 -in [cert].pfx -nocerts -nodes -out [cert].key + * + * @param {ArrayBuffer} arrayBuffer - Conteúdo bruto do arquivo .pfx + * @param {string} password - Senha de importação do arquivo + * @returns {object} Objeto com os conteúdos em formato string e metadados + */ +export function convertPfx(arrayBuffer, password = '') { + try { + const bytes = forge.util.createBuffer(arrayBuffer).getBytes(); + const p12Asn1 = forge.asn1.fromDer(bytes); + const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, password); + + // 1. Extração de Bolsas de Certificados (Cert Bags) + const certBagsObj = p12.getBags({ bagType: forge.pki.oids.certBag }); + const certBags = certBagsObj[forge.pki.oids.certBag] || []; + + // 2. Extração de Bolsas de Chave Privada (Shrouded & Plain) + const shroudedBags = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag })[forge.pki.oids.pkcs8ShroudedKeyBag] || []; + const plainKeyBags = p12.getBags({ bagType: forge.pki.oids.keyBag })[forge.pki.oids.keyBag] || []; + const keyBags = [...shroudedBags, ...plainKeyBags]; + + if (certBags.length === 0 && keyBags.length === 0) { + throw new Error('Nenhum certificado ou chave privada encontrado no arquivo PFX fornecido.'); + } + + const allCerts = certBags.filter(b => b.cert).map(b => b.cert); + + // 3. Obter Chave Privada + let privateKey = null; + let privateKeyBag = null; + if (keyBags.length > 0 && keyBags[0].key) { + privateKeyBag = keyBags[0]; + privateKey = keyBags[0].key; + } + + // 4. Identificar o Certificado Cliente (Leaf Certificate) + // No OpenSSL -clcerts filtra somente o certificado associado à chave privada + let clientCert = null; + if (privateKey) { + // Tentativa 1: Correspondência por localKeyId + const keyLocalId = privateKeyBag?.attributes?.localKeyId?.[0]; + if (keyLocalId) { + const foundBag = certBags.find(b => b.attributes?.localKeyId?.[0] === keyLocalId); + if (foundBag?.cert) clientCert = foundBag.cert; + } + + // Tentativa 2: Correspondência pelo Módulo da Chave Pública (RSA Modulus) + if (!clientCert && privateKey.n) { + const keyModulus = privateKey.n.toString(); + const found = allCerts.find(c => c.publicKey?.n?.toString() === keyModulus); + if (found) clientCert = found; + } + } + + // Se houver apenas 1 certificado ou não foi possível associar, seleciona o primeiro + if (!clientCert && allCerts.length > 0) { + clientCert = allCerts[0]; + } + + // Ordenar certificados da cadeia: Certificado do cliente primeiro, seguido pelos intermediários/raiz + const chainCerts = allCerts.filter(c => c !== clientCert); + const orderedAllCerts = clientCert ? [clientCert, ...chainCerts] : allCerts; + + // 5. Geração dos formatos de saída: + + // .CRT: Apenas o certificado cliente (equivalente a -clcerts -nokeys) + const crt = clientCert ? forge.pki.certificateToPem(clientCert) : ''; + + // .PEM: Todos os certificados da cadeia (equivalente a -nokeys) + const pem = orderedAllCerts.map(c => forge.pki.certificateToPem(c)).join('\n'); + + // .KEY: Chave privada desprotegida (equivalente a -nocerts -nodes) + const key = privateKey ? forge.pki.privateKeyToPem(privateKey) : ''; + + // 6. Extração de Metadados Detalhados para exibição + let metadata = null; + if (clientCert) { + const getAttr = (attrs, name, shortName) => { + const item = attrs.find(a => a.name === name || (shortName && a.shortName === shortName)); + return item ? item.value : null; + }; + + const certDer = forge.asn1.toDer(forge.pki.certificateToAsn1(clientCert)).getBytes(); + const sha1 = forge.md.sha1.create().update(certDer).digest().toHex().match(/.{2}/g).join(':').toUpperCase(); + const sha256 = forge.md.sha256.create().update(certDer).digest().toHex().match(/.{2}/g).join(':').toUpperCase(); + + const now = new Date(); + const notBefore = clientCert.validity.notBefore; + const notAfter = clientCert.validity.notAfter; + const isValid = now >= notBefore && now <= notAfter; + const isExpired = now > notAfter; + const daysRemaining = Math.ceil((notAfter.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)); + + const commonName = getAttr(clientCert.subject.attributes, 'commonName', 'CN') || 'Não identificado'; + const taxId = extractTaxId(commonName) || extractTaxId(JSON.stringify(clientCert.subject.attributes)); + + metadata = { + subject: { + commonName, + organization: getAttr(clientCert.subject.attributes, 'organizationName', 'O') || '', + orgUnits: clientCert.subject.attributes.filter(a => a.name === 'organizationalUnitName' || a.shortName === 'OU').map(a => a.value), + country: getAttr(clientCert.subject.attributes, 'countryName', 'C') || '', + state: getAttr(clientCert.subject.attributes, 'stateOrProvinceName', 'ST') || '', + locality: getAttr(clientCert.subject.attributes, 'localityName', 'L') || '', + }, + issuer: { + commonName: getAttr(clientCert.issuer.attributes, 'commonName', 'CN') || 'Não identificado', + organization: getAttr(clientCert.issuer.attributes, 'organizationName', 'O') || '', + country: getAttr(clientCert.issuer.attributes, 'countryName', 'C') || '', + }, + validity: { + notBefore: notBefore.toISOString(), + notAfter: notAfter.toISOString(), + notBeforeFormatted: notBefore.toLocaleString('pt-BR'), + notAfterFormatted: notAfter.toLocaleString('pt-BR'), + isValid, + isExpired, + daysRemaining + }, + taxId, + serialNumber: clientCert.serialNumber, + fingerprints: { + sha1, + sha256 + }, + keyDetails: privateKey ? { + type: 'RSA', + bits: privateKey.n ? privateKey.n.bitLength() : 2048 + } : null, + totalCerts: allCerts.length, + hasPrivateKey: !!privateKey + }; + } + + return { + success: true, + crt, + pem, + key, + metadata + }; + } catch (err) { + let msg = err.message || 'Erro ao processar o certificado.'; + + if ( + msg.includes('Invalid password') || + msg.includes('PKCS#12 MAC could not be verified') || + msg.includes('MAC verify') || + msg.includes('mac is invalid') + ) { + msg = 'Senha incorreta para o arquivo PFX. Por favor, confira a senha e tente novamente.'; + } else if ( + msg.includes('Too few bytes') || + msg.includes('Cannot read') || + msg.includes('ASN.1') || + msg.includes('Unexpected') + ) { + msg = 'O arquivo selecionado não é um arquivo PKCS#12 / PFX válido ou está corrompido.'; + } else if (msg.includes('PBES2') || msg.includes('algorithm')) { + msg = 'O certificado utiliza uma cifra moderna (PBES2/AES). Tente converter ou recriar no padrão PKCS#12 compatível.'; + } + + return { + success: false, + error: msg + }; + } +} diff --git a/src/utils/downloadHelper.js b/src/utils/downloadHelper.js new file mode 100644 index 0000000..2239f7c --- /dev/null +++ b/src/utils/downloadHelper.js @@ -0,0 +1,93 @@ +import JSZip from 'jszip'; + +/** + * Faz o download de um arquivo de texto no navegador + * @param {string} content - Conteúdo textual do arquivo + * @param {string} filename - Nome do arquivo para download (ex: 'meu_cert.crt') + * @param {string} mimeType - Tipo MIME (default: 'text/plain;charset=utf-8') + */ +export function downloadFile(content, filename, mimeType = 'text/plain;charset=utf-8') { + if (!content) return; + const blob = new Blob([content], { type: mimeType }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} + +/** + * Cria e baixa um arquivo ZIP contendo os arquivos .crt, .pem, .key e um sumário .txt + * @param {object} files - Objeto contendo { crt, pem, key } + * @param {string} baseName - Nome base sem extensão (ex: 'cert_olho') + * @param {object} metadata - Metadados do certificado para inclusão no resumo + */ +export async function downloadAllAsZip(files, baseName = 'certificado', metadata = null) { + const zip = new JSZip(); + + // Adiciona arquivos convertidos + if (files.crt) { + zip.file(`${baseName}.crt`, files.crt); + } + if (files.pem) { + zip.file(`${baseName}.pem`, files.pem); + } + if (files.key) { + zip.file(`${baseName}.key`, files.key); + } + + // Gera arquivo informativo com detalhes + if (metadata) { + const infoText = [ + '=========================================================================', + ' DETALHES DO CERTIFICADO DIGITAL CONVERTIDO ', + '=========================================================================', + `Arquivo Original: ${baseName}.pfx`, + `Data da Conversão: ${new Date().toLocaleString('pt-BR')}`, + '', + '--- TITULAR (SUBJECT) ---', + `Nome Comum (CN): ${metadata.subject?.commonName || '-'}`, + metadata.taxId ? `Documento (${metadata.taxId.type}): ${metadata.taxId.value}` : null, + `Organização (O): ${metadata.subject?.organization || '-'}`, + `Localidade: ${metadata.subject?.locality || '-'}, ${metadata.subject?.state || '-'} - ${metadata.subject?.country || '-'}`, + '', + '--- EMISSOR (ISSUER) ---', + `Autoridade Certificadora: ${metadata.issuer?.commonName || '-'}`, + `Organização Emissora: ${metadata.issuer?.organization || '-'}`, + '', + '--- VALIDADE ---', + `Válido a partir de: ${metadata.validity?.notBeforeFormatted || '-'}`, + `Válido até: ${metadata.validity?.notAfterFormatted || '-'}`, + `Status: ${metadata.validity?.isValid ? 'ATIVO / VÁLIDO' : 'EXPIRADO'} (${metadata.validity?.daysRemaining} dias restantes)`, + '', + '--- CHAVE E CRIPTOGRAFIA ---', + `Chave Privada: ${metadata.keyDetails ? `${metadata.keyDetails.type} ${metadata.keyDetails.bits} bits` : 'Não incluída'}`, + `Número de Série: ${metadata.serialNumber || '-'}`, + `Impressão Digital SHA-1: ${metadata.fingerprints?.sha1 || '-'}`, + `Impressão Digital SHA-256: ${metadata.fingerprints?.sha256 || '-'}`, + '', + '--- ARQUIVOS GERADOS ---', + `1. ${baseName}.crt -> Apenas o certificado cliente (equivalente ao openssl -clcerts -nokeys)`, + `2. ${baseName}.pem -> Cadeia completa de certificados (equivalente ao openssl -nokeys)`, + `3. ${baseName}.key -> Chave privada desprotegida (equivalente ao openssl -nocerts -nodes)`, + '', + '=========================================================================' + ].filter(Boolean).join('\n'); + + zip.file('LEIA-ME-INFO.txt', infoText); + } + + // Gera o blob do ZIP e dispara o download + const blob = await zip.generateAsync({ type: 'blob' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${baseName}_convertido.zip`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} diff --git a/src/utils/initialWppData.json b/src/utils/initialWppData.json new file mode 100644 index 0000000..bd49155 --- /dev/null +++ b/src/utils/initialWppData.json @@ -0,0 +1,89 @@ +{ + "servers": [ + { + "name": "C2 Sistemas", + "baseUrl": "http://www.c2wpp.c2sistemas.com.br:22700", + "secretKey": "c2sistemas", + "online": false, + "id": "1779711825472", + "sessions": [ + { + "name": "admin", + "token": "$2b$10$PXlfG1m8_i1eXV2lFu0N1.SyXi4IAM3VcjbaQxlG0JyALHq0GAti6", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "qr", + "qrCode": "data:image/png;base64,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", + "connectedAt": "25/05/2026, 11:05:44" + }, + { + "name": "sigefweb_renascer_carmopolis", + "token": "$2b$10$UwBef4pfuFK1a_6N4swYPOcSLaJQnngNlTxVG90kLywd1zDFrYFEW", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "connected", + "connectedAt": "24/08/2026, 09:31:23", + "qrCode": "data:image/png;base64,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" + }, + { + "name": "sigefweb_santo_maceio_2", + "token": "$2b$10$m9JEZe_FYQZ97EvYDY8GSu5.KGNI5rFo8YTVW7Qi_34fjdP5lYnpy", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "connected", + "connectedAt": "14/10/2026, 11:50:40", + "qrCode": "data:image/png;base64,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" + }, + { + "name": "sigefweb_pax_corcovado", + "token": "$2b$10$DvCo8kCiUoFordkbLJm4zuJTVvt.WC9LwseGuERBcSTgQc3bkT9o6", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "connected", + "qrCode": "data:image/png;base64,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", + "connectedAt": "30/06/2026, 14:52:33" + }, + { + "name": "sigefweb_dortas", + "token": "$2b$10$lpFTaLCjch_GG6InkXfp9e0LLzqQ35OVDRZtM02_MrGJjBUP7Sga2", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "connected", + "connectedAt": "10/09/2026, 17:24:12", + "qrCode": "data:image/png;base64,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" + }, + { + "name": "reisplan_sigefweb", + "status": "qr", + "connectedAt": "23/07/2026, 17:13:50", + "qrCode": "data:image/png;base64,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" + }, + { + "name": "sigefweb_uniplan", + "token": "$2b$10$QZB.Y.VUzWNlP9BHdN583uw31SV.vA9C_NSd9M2kAk3zAb5zALcPG", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "connected", + "connectedAt": "31/08/2026, 11:23:10", + "qrCode": "data:image/png;base64,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" + }, + { + "name": "clinica_mais_saude", + "token": "$2b$10$BDJtUbkgbxFjEBsMlg5rkuHs8jWSMN1oFhFSwmcJWFfCEClz8WQJm", + "webhook": "", + "waitQrCode": false, + "proxy": null, + "status": "connected", + "qrCode": "data:image/png;base64,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", + "connectedAt": "04/09/2026, 09:25:03" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/utils/wppConnectApi.js b/src/utils/wppConnectApi.js new file mode 100644 index 0000000..5259da3 --- /dev/null +++ b/src/utils/wppConnectApi.js @@ -0,0 +1,217 @@ +/** + * Cliente de API WPPConnect para o AppWPP (React) + */ + +export function normalizeUrl(url) { + if (!url) return ''; + let u = url.trim().replace(/\/+$/, ''); + if (!/^https?:\/\//i.test(u)) u = 'http://' + u; + return u; +} + +export function ensureQRPrefix(qrCode) { + if (!qrCode) return ''; + return qrCode.startsWith('data:') ? qrCode : `data:image/png;base64,${qrCode}`; +} + +export function getSessionAuth(server, session) { + if (!server) return null; + return session?.token || server.secretKey; +} + +/** + * Testa conectividade com o servidor WPPConnect + */ +export async function testServerConnection(baseUrl, secretKey) { + const normUrl = normalizeUrl(baseUrl); + const res = await fetch(`${normUrl}/api/${secretKey}/show-all-sessions`, { + headers: { 'Authorization': `Bearer ${secretKey}` }, + signal: AbortSignal.timeout(8000), + }); + + if (res.ok) { + return { ok: true, message: 'Conexão OK! Servidor respondeu com sucesso.' }; + } else if (res.status === 401) { + return { ok: false, error: 'Token incorreto. Verifique a Secret Key.' }; + } else { + const text = await res.text().catch(() => ''); + return { ok: false, error: `Erro ${res.status}: ${text || 'Resposta inesperada'}` }; + } +} + +/** + * Inicia uma sessão WPPConnect + */ +export async function startSession(server, sessionName, options = {}) { + const baseUrl = normalizeUrl(server.baseUrl); + const session = server.sessions?.find(s => s.name === sessionName); + const authToken = getSessionAuth(server, session); + + const url = `${baseUrl}/api/${sessionName}/start-session`; + const body = { waitQrCode: true }; + if (session?.webhook) body.webhook = session.webhook; + if (session?.proxy) body.proxy = session.proxy; + + const res = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authToken}`, + }, + body: JSON.stringify(body), + }); + + if (!res.ok) { + const errText = await res.text(); + throw new Error(errText || `HTTP ${res.status}`); + } + + return await res.json(); +} + +/** + * Gera token JWT para a sessão + */ +export async function generateToken(server, sessionName) { + const baseUrl = normalizeUrl(server.baseUrl); + const res = await fetch(`${baseUrl}/api/${sessionName}/${server.secretKey}/generate-token`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${server.secretKey}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ session: sessionName }), + }); + + if (res.ok) { + const data = await res.json(); + return data.token || null; + } + return null; +} + +/** + * Consulta status de conexão da sessão + */ +export async function checkSessionStatus(server, sessionName) { + const baseUrl = normalizeUrl(server.baseUrl); + const session = server.sessions?.find(s => s.name === sessionName); + const authToken = getSessionAuth(server, session); + + const res = await fetch(`${baseUrl}/api/${sessionName}/check-connection-session`, { + headers: { 'Authorization': `Bearer ${authToken}` }, + signal: AbortSignal.timeout(6000), + }); + + if (res.ok) { + const data = await res.json(); + return data.status || 'unknown'; + } + return 'error'; +} + +/** + * Busca o QR Code da sessão + */ +export async function fetchQRCode(server, sessionName) { + const baseUrl = normalizeUrl(server.baseUrl); + const session = server.sessions?.find(s => s.name === sessionName); + const authToken = getSessionAuth(server, session); + + const qrRes = await fetch(`${baseUrl}/api/${sessionName}/qrcode-session`, { + headers: { 'Authorization': `Bearer ${authToken}` }, + signal: AbortSignal.timeout(10000), + }); + + if (!qrRes.ok) return null; + + const ct = qrRes.headers.get('content-type') || ''; + if (ct.includes('json')) { + const data = await qrRes.json(); + return data.qrcode ? ensureQRPrefix(data.qrcode) : null; + } else if (ct.includes('image')) { + const buf = await qrRes.arrayBuffer(); + const bytes = new Uint8Array(buf); + let binary = ''; + for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]); + return `data:${ct};base64,${btoa(binary)}`; + } + return null; +} + +/** + * Fecha a sessão + */ +export async function closeSession(server, sessionName) { + const baseUrl = normalizeUrl(server.baseUrl); + const session = server.sessions?.find(s => s.name === sessionName); + let authToken = getSessionAuth(server, session); + + const res = await fetch(`${baseUrl}/api/${sessionName}/close-session`, { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` }, + body: JSON.stringify({ secretkey: server.secretKey }), + }); + + if (!res.ok) { + const errBody = await res.text().catch(() => ''); + throw new Error(errBody || `HTTP ${res.status}`); + } + return true; +} + +/** + * Desconecta a sessão (Logout) + */ +export async function logoutSession(server, sessionName) { + const baseUrl = normalizeUrl(server.baseUrl); + const session = server.sessions?.find(s => s.name === sessionName); + let authToken = getSessionAuth(server, session); + + const res = await fetch(`${baseUrl}/api/${sessionName}/logout-session`, { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${authToken}` }, + body: JSON.stringify({ secretkey: server.secretKey }), + }); + + if (!res.ok) { + const errBody = await res.text().catch(() => ''); + throw new Error(errBody || `HTTP ${res.status}`); + } + return true; +} + +/** + * Limpa arquivos e dados da sessão no servidor + */ +export async function clearSessionData(server, sessionName) { + const baseUrl = normalizeUrl(server.baseUrl); + const res = await fetch(`${baseUrl}/api/${sessionName}/${server.secretKey}/clear-session-data`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${server.secretKey}`, + }, + }); + + if (!res.ok) { + const errBody = await res.text().catch(() => ''); + throw new Error(errBody || `HTTP ${res.status}`); + } + return true; +} + +/** + * Lista todas as sessões registradas no servidor + */ +export async function listAllServerSessions(server) { + const baseUrl = normalizeUrl(server.baseUrl); + const res = await fetch(`${baseUrl}/api/${server.secretKey}/show-all-sessions`, { + headers: { 'Authorization': `Bearer ${server.secretKey}` }, + signal: AbortSignal.timeout(10000), + }); + + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const data = await res.json(); + return data.response || []; +} diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..9982072 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +})