Files
polskalokalnie/frontend/src/ProtectedRoute.tsx
T
pascal f072ed0115 Dodaj react-router-dom, mape tras i ProtectedRoute
Fundament migracji z useState(view) na prawdziwy routing:
- react-router-dom 7 w zaleznosciach
- BrowserRouter w main.tsx (nginx ma juz try_files, wiec czyste sciezki dzialaja)
- routes.ts: centralna mapa adresow + helpery listingPath/mapPath/adminTabPath
- ProtectedRoute z obsluga stanu loading z AuthProvider

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 23:24:22 +02:00

38 lines
1.3 KiB
TypeScript

import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { useAuth } from './auth';
import { ROUTES } from './routes';
/**
* Bramka dostępu dla tras wymagających zalogowania (i opcjonalnie roli ADMIN).
*
* Uwaga na `loading`: po odświeżeniu strony token jest w localStorage, ale profil
* dociąga się asynchronicznie z /auth/me. Bez tego warunku bezpośrednie wejście na
* /konto wyrzucałoby zalogowanego użytkownika na logowanie, zanim profil dotrze.
*
* To zabezpieczenie interfejsu, nie kontrola dostępu do danych — autoryzację
* egzekwuje backend przy każdym endpoincie.
*/
export function ProtectedRoute({ requireAdmin = false }: { requireAdmin?: boolean }) {
const { user, loading } = useAuth();
const location = useLocation();
if (loading) {
return (
<div className="route-loading" role="status" aria-live="polite">
Wczytywanie
</div>
);
}
if (!user) {
// Zapamiętujemy cel, żeby po zalogowaniu wrócić dokładnie tam, gdzie użytkownik zmierzał.
return <Navigate to={ROUTES.login} state={{ from: `${location.pathname}${location.search}` }} replace />;
}
if (requireAdmin && user.role !== 'ADMIN') {
return <Navigate to={ROUTES.account} replace />;
}
return <Outlet />;
}