7ffaead255
- .gitea/workflows/build.yml: push->build rx-scoreodonto:<sha> no registry; tag->promote+deploy - docker-compose.prod.yml: image do registry, APP_VERSION/GIT_COMMIT em runtime - deploy-prod.sh: VPS1 pull + up --no-build (antigo vira deploy-prod-legado-webhook.sh) - /api/health usa APP_VERSION (tag) com fallback version.txt; badge no canto - webhook 9003 aposentado (gatilho agora e CI/tag) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
169 lines
5.4 KiB
React
169 lines
5.4 KiB
React
import { useState, useEffect } from 'react';
|
|
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
|
import { AuthProvider } from './contexts/AuthContext';
|
|
import { SocketProvider } from './contexts/SocketContext';
|
|
import { ToastProvider } from './contexts/ToastContext';
|
|
import { ProtectedRoute, AdminRoute } from './components/ProtectedRoute';
|
|
|
|
import LoginPage from './pages/LoginPage';
|
|
import InstallPage from './pages/InstallPage';
|
|
import DashboardPage from './pages/DashboardPage';
|
|
import ClientsPage from './pages/ClientsPage';
|
|
import AdminClinicsPage from './pages/AdminClinicsPage';
|
|
import ResetPage from './pages/ResetPage';
|
|
import DownloadPage from './pages/DownloadPage';
|
|
import PatientsPage from './pages/PatientsPage';
|
|
import CreatePatientPage from './pages/CreatePatientPage';
|
|
import PatientDetailsPage from './pages/PatientDetailsPage';
|
|
import SettingsPage from './pages/SettingsPage';
|
|
import GtosPage from './pages/GtosPage';
|
|
import CreateGtoPage from './pages/CreateGtoPage';
|
|
import GtoDetailsPage from './pages/GtoDetailsPage';
|
|
import ImageDetailsPage from './pages/ImageDetailsPage';
|
|
import UsersPage from './pages/UsersPage';
|
|
import SyncPage from './pages/SyncPage';
|
|
import ApiDocsPage from './pages/ApiDocsPage';
|
|
|
|
// Versão fixa no canto inferior direito (padrão da stack — lê /api/health; não bloqueia cliques).
|
|
function VersionBadge() {
|
|
const [ver, setVer] = useState('');
|
|
useEffect(() => {
|
|
fetch('/api/health').then(r => (r.ok ? r.json() : null))
|
|
.then(v => { if (v && v.version) setVer(v.version); }).catch(() => {});
|
|
}, []);
|
|
if (!ver) return null;
|
|
return (
|
|
<div style={{ position: 'fixed', bottom: 6, right: 8, zIndex: 40, pointerEvents: 'none', userSelect: 'none', fontSize: 10, fontFamily: 'monospace', color: 'rgba(120,120,120,0.7)' }}>
|
|
v{ver}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function App() {
|
|
return (
|
|
<>
|
|
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
|
|
<AuthProvider>
|
|
<ToastProvider>
|
|
<SocketProvider>
|
|
<Routes>
|
|
{/* Rotas públicas */}
|
|
<Route path="/login" element={<LoginPage />} />
|
|
<Route path="/install" element={<InstallPage />} />
|
|
|
|
{/* Rotas protegidas (usuário autenticado) */}
|
|
<Route path="/" element={
|
|
<ProtectedRoute>
|
|
<DashboardPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/:patientName" element={
|
|
<ProtectedRoute>
|
|
<DashboardPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
{/* Rotas de administrador */}
|
|
<Route path="/clients" element={
|
|
<AdminRoute>
|
|
<ClientsPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/admin-clinics" element={
|
|
<AdminRoute>
|
|
<AdminClinicsPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/api-docs" element={
|
|
<AdminRoute>
|
|
<ApiDocsPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/users" element={
|
|
<AdminRoute>
|
|
<UsersPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/reset" element={
|
|
<AdminRoute>
|
|
<ResetPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/download" element={
|
|
<AdminRoute>
|
|
<DownloadPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/patients" element={
|
|
<ProtectedRoute>
|
|
<PatientsPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/patients/new" element={
|
|
<ProtectedRoute>
|
|
<CreatePatientPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/patients/:id" element={
|
|
<ProtectedRoute>
|
|
<PatientDetailsPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/sync" element={
|
|
<ProtectedRoute>
|
|
<SyncPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/settings" element={
|
|
<AdminRoute>
|
|
<SettingsPage />
|
|
</AdminRoute>
|
|
} />
|
|
|
|
<Route path="/gtos" element={
|
|
<ProtectedRoute>
|
|
<GtosPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/gtos/new" element={
|
|
<ProtectedRoute>
|
|
<CreateGtoPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/gtos/:id" element={
|
|
<ProtectedRoute>
|
|
<GtoDetailsPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route path="/:patientName/:imageId" element={
|
|
<ProtectedRoute>
|
|
<ImageDetailsPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
{/* Catch-all: redireciona para home */}
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
</Routes>
|
|
</SocketProvider>
|
|
</ToastProvider>
|
|
</AuthProvider>
|
|
</BrowserRouter>
|
|
<VersionBadge />
|
|
</>
|
|
);
|
|
}
|