From d8500cf433816f742ed79b03347217353d5fc476 Mon Sep 17 00:00:00 2001 From: fpereirasilv Date: Thu, 15 Oct 2026 14:41:15 -0300 Subject: [PATCH] feat: show commit hash in footer and implement auto server health check for AppWPP --- src/App.jsx | 8 +++- src/components/wpp/AppWPP.jsx | 81 ++++++++++++++++++++++++++++++++--- src/index.css | 54 +++++++++++++++++++++++ vite.config.js | 18 +++++++- 4 files changed, 154 insertions(+), 7 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 7259984..83525c3 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -8,7 +8,8 @@ import { Lock, Loader2, MessageSquare, - Bookmark + Bookmark, + GitCommit } from 'lucide-react'; import Header from './components/Header'; import SecurityBadge from './components/SecurityBadge'; @@ -251,6 +252,11 @@ export default function App() { 100% no cliente (Executa em qualquer navegador) + • + + + Commit: {typeof __COMMIT_HASH__ !== 'undefined' ? __COMMIT_HASH__ : 'dev'} + diff --git a/src/components/wpp/AppWPP.jsx b/src/components/wpp/AppWPP.jsx index ce7722c..2bef1f2 100644 --- a/src/components/wpp/AppWPP.jsx +++ b/src/components/wpp/AppWPP.jsx @@ -14,7 +14,8 @@ import { AlertCircle, CheckCircle2, Info, - Edit2 + Edit2, + RefreshCw } from 'lucide-react'; import { getStoredServers, saveServers } from '../../utils/appWppStorage'; import { @@ -24,7 +25,9 @@ import { checkSessionStatus, clearSessionData, generateToken, - ensureQRPrefix + ensureQRPrefix, + testServerConnection, + listAllServerSessions } from '../../utils/wppConnectApi'; import WppSessionCard from './WppSessionCard'; import ModalServer from './ModalServer'; @@ -91,6 +94,63 @@ export default function AppWPP() { }; const activeServer = servers.find((s) => s.id === activeServerId) || null; + const [isCheckingServer, setIsCheckingServer] = useState(false); + + const checkServerOnlineStatus = async (serverToCheck) => { + const srv = serverToCheck || servers.find((s) => s.id === activeServerId) || activeServer; + if (!srv || !srv.baseUrl || !srv.secretKey) return; + + setIsCheckingServer(true); + try { + const res = await testServerConnection(srv.baseUrl, srv.secretKey); + const isOnline = res.ok === true; + updateServersState((prevServers) => + prevServers.map((s) => (s.id === srv.id ? { ...s, online: isOnline } : s)) + ); + + // Se estiver online, sincroniza o status das sessões já ativas no servidor + if (isOnline) { + try { + const sessionsOnServer = await listAllServerSessions(srv); + if (Array.isArray(sessionsOnServer)) { + updateServersState((prevServers) => + prevServers.map((s) => { + if (s.id !== srv.id) return s; + const updatedSessions = (s.sessions || []).map((sess) => { + const match = sessionsOnServer.find((x) => + x === sess.name || x?.name === sess.name || x?.session === sess.name + ); + if (match) { + const statusStr = typeof match === 'string' ? 'connected' : (match.status || 'connected'); + const isConn = statusStr === 'CONNECTED' || statusStr === 'connected' || statusStr === true; + return { ...sess, status: isConn ? 'connected' : sess.status }; + } + return sess; + }); + return { ...s, sessions: updatedSessions }; + }) + ); + } + } catch (e) {} + } + } catch (e) { + updateServersState((prevServers) => + prevServers.map((s) => (s.id === srv.id ? { ...s, online: false } : s)) + ); + } finally { + setIsCheckingServer(false); + } + }; + + // Checa automaticamente o status do servidor ativo na inicialização e ao alternar + useEffect(() => { + if (activeServerId && servers.length > 0) { + const srv = servers.find((s) => s.id === activeServerId); + if (srv) { + checkServerOnlineStatus(srv); + } + } + }, [activeServerId, servers.length]); // Servidor CRUD const handleSaveServer = (serverData) => { @@ -415,9 +475,20 @@ export default function AppWPP() {

{activeServer.name}

- - {activeServer.online ? 'Online' : 'Offline'} - +
+ + {isCheckingServer ? 'Verificando...' : (activeServer.online ? 'Online' : 'Offline')} + + +
{activeServer.baseUrl}
diff --git a/src/index.css b/src/index.css index 072084a..54cc222 100644 --- a/src/index.css +++ b/src/index.css @@ -1262,6 +1262,24 @@ body { color: #34d399; } +.footer-commit { + display: inline-flex; + align-items: center; + gap: 0.35rem; + color: var(--text-secondary); +} + +.commit-hash-pill { + font-family: var(--font-mono); + background: rgba(14, 165, 233, 0.12); + border: 1px solid rgba(14, 165, 233, 0.25); + color: #38bdf8; + padding: 0.1rem 0.45rem; + border-radius: 4px; + font-size: 0.75rem; + font-weight: 600; +} + /* Utilities */ .text-cyan { color: var(--accent-cyan); } .text-emerald { color: var(--accent-emerald); } @@ -1640,6 +1658,42 @@ body { border: 1px solid rgba(100, 116, 139, 0.3); } +.badge-checking { + background: rgba(234, 179, 8, 0.15); + color: #facc15; + border: 1px solid rgba(234, 179, 8, 0.3); +} + +.wpp-status-wrapper { + display: inline-flex; + align-items: center; + gap: 0.4rem; +} + +.btn-refresh-status { + background: rgba(255, 255, 255, 0.05); + border: 1px solid var(--border-color); + color: var(--text-muted); + border-radius: 6px; + padding: 0.2rem 0.35rem; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.btn-refresh-status:hover:not(:disabled) { + color: #38bdf8; + border-color: rgba(56, 189, 248, 0.4); + background: rgba(56, 189, 248, 0.1); +} + +.btn-refresh-status:disabled { + opacity: 0.6; + cursor: not-allowed; +} + .wpp-server-actions-group { display: flex; align-items: center; diff --git a/vite.config.js b/vite.config.js index b7550b3..6e128aa 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,9 +1,25 @@ -import react from '@vitejs/plugin-react' import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import { execSync } from 'child_process' + +let commitHash = process.env.COMMIT_REF + ? process.env.COMMIT_REF.slice(0, 7) + : ''; + +if (!commitHash) { + try { + commitHash = execSync('git rev-parse --short HEAD').toString().trim(); + } catch (e) { + commitHash = 'dev'; + } +} // https://vite.dev/config/ export default defineConfig({ plugins: [react()], + define: { + __COMMIT_HASH__: JSON.stringify(commitHash) + }, server: { proxy: { '/api-wpp': {