Files
CC-Manager/web/src/App.tsx
T
Harlekin 6c50d32d2b Rollen neu geschnitten, Seitenzahl korrigiert, frühere Konten
Der Forums-Abgleich las von 25 Archivseiten nur zwei. WoltLab verlinkt in der
Blätterleiste nur die Nachbarseiten und führt die Gesamtzahl in einem eigenen
Element; ausgewertet wurden aber die Links. Alles jenseits von Seite zwei war
damit unsichtbar - etwa ein Antrag auf Seite vier, der deshalb nie ankam.

Die Rollen verlaufen jetzt zwischen erfassen und gewähren statt zwischen
Alltag und Verwaltung: Editoren erfassen Käufe und führen Datei-Import,
GExtension- und Forums-Abgleich samt Entscheidung über Anträge durch. Kulanz
zu vergeben bleibt Administratoren, ebenso das Auflösen unklarer Pakete, weil
dabei Kulanz entstehen kann.

Dazu lassen sich frühere Steam- und Forumskonten am Spieler hinterlegen.
Abgleich und Import prüfen sie mit, sodass ein Kontowechsel die Zuordnung
nicht abreißen lässt. Steam-Kennungen werden dabei auf dieselbe Form gebracht
wie die Hauptangabe, und eine Kennung kann nicht zwei Spielern gehören.
2026-09-18 20:07:56 +02:00

110 lines
2.5 KiB
TypeScript

import { Navigate, Route, Routes } from 'react-router-dom';
import Layout from './components/Layout';
import { useSession } from './lib/session';
import type { Role } from './lib/types';
import Account from './pages/Account';
import Admin from './pages/Admin';
import Dashboard from './pages/Dashboard';
import Forum from './pages/Forum';
import Import from './pages/Import';
import Login from './pages/Login';
import PlayerDetail from './pages/PlayerDetail';
function Protected({ children, minimum }: { children: React.ReactNode; minimum?: Role }) {
const { user, loading, can } = useSession();
if (loading) return <div className="boot">Lade …</div>;
if (!user) return <Navigate to="/login" replace />;
// Ein frisch angelegtes Konto muss zuerst sein Passwort wechseln.
if (user.mustChangePassword) return <Navigate to="/account" replace />;
if (minimum && !can(minimum)) return <Navigate to="/" replace />;
return <>{children}</>;
}
export default function App() {
const { user, loading } = useSession();
return (
<Routes>
<Route
path="/login"
element={loading ? <div className="boot">Lade …</div> : user ? <Navigate to="/" replace /> : <Login />}
/>
<Route
path="/account"
element={
loading ? (
<div className="boot">Lade …</div>
) : !user ? (
<Navigate to="/login" replace />
) : (
<Layout>
<Account />
</Layout>
)
}
/>
<Route
path="/"
element={
<Protected>
<Layout>
<Dashboard />
</Layout>
</Protected>
}
/>
<Route
path="/players/:id"
element={
<Protected>
<Layout>
<PlayerDetail />
</Layout>
</Protected>
}
/>
<Route
path="/forum"
element={
<Protected>
<Layout>
<Forum />
</Layout>
</Protected>
}
/>
<Route
path="/import"
element={
<Protected minimum="EDITOR">
<Layout>
<Import />
</Layout>
</Protected>
}
/>
<Route
path="/admin"
element={
<Protected minimum="ADMIN">
<Layout>
<Admin />
</Layout>
</Protected>
}
/>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
);
}