index.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import './index.css';
  2. import React, { lazy, Suspense } from 'react';
  3. import { createRoot } from 'react-dom/client';
  4. import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
  5. import { AuthProvider, useAuth } from './src/contexts/AuthContext';
  6. import { LanguageProvider } from './contexts/LanguageContext';
  7. import { ToastProvider } from './contexts/ToastContext';
  8. import { ConfirmProvider } from './contexts/ConfirmContext';
  9. import Login from './src/pages/auth/Login';
  10. import WorkspaceLayout from './src/components/layouts/WorkspaceLayout';
  11. // Lazy-loaded page components
  12. const ChatPage = lazy(() => import('./src/pages/workspace/ChatPage'));
  13. const AgentsPage = lazy(() => import('./src/pages/workspace/AgentsPage'));
  14. const AssessmentPage = lazy(() => import('./src/pages/workspace/AssessmentPage'));
  15. const PluginsPage = lazy(() => import('./src/pages/workspace/PluginsPage'));
  16. const KnowledgePage = lazy(() => import('./src/pages/workspace/KnowledgePage'));
  17. const NotebooksPage = lazy(() => import('./src/pages/workspace/NotebooksPage'));
  18. const MemosPage = lazy(() => import('./src/pages/workspace/MemosPage'));
  19. const SettingsPage = lazy(() => import('./src/pages/workspace/SettingsPage'));
  20. const PageLoader = () => (
  21. <div className="flex h-full items-center justify-center">
  22. <div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin" />
  23. </div>
  24. );
  25. function ProtectedRoute({ children, allowedRoles }: { children: React.ReactNode, allowedRoles?: string[] }) {
  26. const { user, isLoading } = useAuth();
  27. if (isLoading) {
  28. return (
  29. <div className="flex h-screen items-center justify-center bg-slate-50">
  30. <PageLoader />
  31. </div>
  32. );
  33. }
  34. if (!user) return <Navigate to="/login" replace />;
  35. if (allowedRoles && !allowedRoles.includes(user.role)) return <Navigate to="/" replace />;
  36. return <>{children}</>;
  37. }
  38. function OverviewPage() {
  39. const { user } = useAuth();
  40. return (
  41. <div className="p-8 bg-white rounded-2xl shadow-sm border border-slate-100">
  42. <h1 className="text-2xl font-bold text-slate-900">Welcome back 👋</h1>
  43. <p className="mt-2 text-slate-500">
  44. Signed in as <span className="font-semibold">{user?.username}</span>{' '}
  45. · role <span className="font-semibold text-blue-600">{user?.role?.replace(/_/g, ' ')}</span>
  46. </p>
  47. </div>
  48. );
  49. }
  50. function App() {
  51. return (
  52. <LanguageProvider>
  53. <ToastProvider>
  54. <ConfirmProvider>
  55. <AuthProvider>
  56. <BrowserRouter>
  57. <Suspense
  58. fallback={
  59. <div className="flex h-screen items-center justify-center bg-slate-50">
  60. <PageLoader />
  61. </div>
  62. }
  63. >
  64. <Routes>
  65. {/* Public */}
  66. <Route path="/login" element={<Login />} />
  67. {/* Workspace */}
  68. <Route
  69. path="/*"
  70. element={
  71. <ProtectedRoute>
  72. <WorkspaceLayout />
  73. </ProtectedRoute>
  74. }
  75. >
  76. <Route index element={<OverviewPage />} />
  77. <Route path="chat" element={<ChatPage />} />
  78. <Route path="agents" element={<AgentsPage />} />
  79. <Route path="assessment" element={<AssessmentPage />} />
  80. <Route path="plugins" element={<PluginsPage />} />
  81. <Route path="notebook" element={<MemosPage />} />
  82. <Route path="knowledge/*" element={<KnowledgePage />} />
  83. <Route path="settings" element={<SettingsPage />} />
  84. <Route path="users" element={<SettingsPage initialTab="user" />} />
  85. <Route path="models" element={<SettingsPage initialTab="model" />} />
  86. <Route path="kb-settings" element={<SettingsPage initialTab="knowledge_base" />} />
  87. <Route path="tenants" element={<ProtectedRoute allowedRoles={['SUPER_ADMIN']}><SettingsPage initialTab="tenants" /></ProtectedRoute>} />
  88. </Route>
  89. {/* Remove standalone Admin routes as we integrated Dashboard into Settings */}
  90. </Routes>
  91. </Suspense>
  92. </BrowserRouter>
  93. </AuthProvider>
  94. </ConfirmProvider>
  95. </ToastProvider>
  96. </LanguageProvider>
  97. );
  98. }
  99. // ── Mount ──────────────────────────────────────────────────────────────────────
  100. const container = document.getElementById('root')!;
  101. createRoot(container).render(
  102. <React.StrictMode>
  103. <App />
  104. </React.StrictMode>,
  105. );