Files
ridebus-admin/frontend/src/App.jsx
Zakhar Timoshenko d13cc92d82 feat: implement multi-city support with city management features
- Added a new cities table to the database to manage multiple cities independently.
- Created a middleware to resolve city context based on X-City-Id header.
- Updated routes and services to handle city-specific data for routes, stops, and alerts.
- Implemented a CityContext in the frontend to manage active city state and provide city data across the application.
- Added a CitySelector component for users to switch between cities.
- Created a CitiesPage for admins to manage cities, including adding new cities with validation.
- Updated various components and pages to reflect the active city context, ensuring data is displayed correctly based on the selected city.
- Enhanced the schedule import functionality to restrict imports based on the active city.
2026-09-17 19:41:17 +03:00

89 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { BrowserRouter as Router, Routes, Route, useLocation, Navigate } from 'react-router-dom';
import { AuthProvider, useAuth } from './contexts/AuthContext';
import { ProtectedRoute } from './components/ProtectedRoute';
import AppLayout from './components/AppLayout';
import { PageLoader } from './components/AnimatedComponents';
import { CityProvider, useCity } from './contexts/CityContext';
// Pages
import LoginPage from './pages/LoginPage';
import Dashboard from './pages/Dashboard';
import RoutesPage from './pages/RoutesPage';
import RouteEditorPage from './pages/RouteEditorPage';
import StopsPage from './pages/StopsPage';
import SchedulesPage from './pages/SchedulesPage';
import ScheduleImportPage from './pages/ScheduleImportPage';
import QualityPage from './pages/QualityPage';
import HolidaysPage from './pages/HolidaysPage';
import AlertsPage from './pages/AlertsPage';
import UsersPage from './pages/UsersPage';
import ProfilePage from './pages/ProfilePage';
import CitiesPage from './pages/CitiesPage';
function App() {
return (
<Router>
<AuthProvider>
<AppContent />
</AuthProvider>
</Router>
);
}
function AppContent() {
const { isAuthenticated, loading } = useAuth();
if (loading) return <PageLoader />;
if (!isAuthenticated) {
return (
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="*" element={<Navigate to="/login" replace />} />
</Routes>
);
}
return <CityProvider><CityWorkspace /></CityProvider>;
}
function CityWorkspace() {
const { loading, error, activeCity } = useCity();
if (loading) return <PageLoader />;
if (error || !activeCity) return <main className="login-surface"><div className="login-card max-w-md"><h1 className="text-xl font-semibold">Города недоступны</h1><p className="mt-2 text-gray-600">{error || 'В системе нет активных городов.'}</p></div></main>;
return <AppLayout>
<AnimatedRoutes cityId={activeCity.id} />
</AppLayout>;
}
function AnimatedRoutes({ cityId }) {
const location = useLocation();
const { isAdmin } = useAuth();
return (
<div key={`${cityId}:${location.pathname}`} className="page-transition">
<Routes location={location}>
<Route path="/" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
<Route path="/routes" element={<ProtectedRoute><RoutesPage /></ProtectedRoute>} />
<Route path="/routes/:id/edit" element={<ProtectedRoute><RouteEditorPage /></ProtectedRoute>} />
<Route path="/stops" element={<ProtectedRoute><StopsPage /></ProtectedRoute>} />
<Route path="/schedules" element={<ProtectedRoute><SchedulesPage /></ProtectedRoute>} />
<Route path="/schedule-import" element={<ProtectedRoute requireAdmin><ScheduleImportPage /></ProtectedRoute>} />
<Route path="/quality" element={<ProtectedRoute requireAdmin><QualityPage /></ProtectedRoute>} />
<Route path="/holidays" element={<ProtectedRoute><HolidaysPage /></ProtectedRoute>} />
<Route path="/alerts" element={<ProtectedRoute><AlertsPage /></ProtectedRoute>} />
<Route path="/profile" element={<ProtectedRoute><ProfilePage /></ProtectedRoute>} />
{isAdmin && <Route path="/cities" element={<ProtectedRoute requireAdmin><CitiesPage /></ProtectedRoute>} />}
{isAdmin && (
<Route path="/users" element={<ProtectedRoute requireAdmin><UsersPage /></ProtectedRoute>} />
)}
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</div>
);
}
export default App;