feat(ui): Dashboard als Startseite für Verantwortliche + einstellbar
Root-Route "/" und Catch-all landeten bisher immer auf /objekte, Login-Weiterleitung (Verantwortliche -> Dashboard) war der einzige Pfad dorthin. Jetzt zentrale startseitenPfad()-Logik überall genutzt, zusätzlich per Dropdown in der Sidebar einstellbar (automatisch/ Dashboard/Objekte), Präferenz in localStorage. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -11,6 +11,7 @@ import { KontrollPage } from "./pages/KontrollPage";
|
||||
import { LoginPage } from "./pages/LoginPage";
|
||||
import { MangelListePage } from "./pages/MangelListePage";
|
||||
import { ObjektListPage } from "./pages/ObjektListPage";
|
||||
import { startseitenPfad } from "./settings/startseite";
|
||||
|
||||
function GeschuetzteRoute({ children }: { children: ReactNode }) {
|
||||
const { eingeloggt } = useAuth();
|
||||
@@ -20,6 +21,12 @@ function GeschuetzteRoute({ children }: { children: ReactNode }) {
|
||||
return <AppShell>{children}</AppShell>;
|
||||
}
|
||||
|
||||
function Startseite() {
|
||||
const { eingeloggt, istVerantwortlich } = useAuth();
|
||||
if (!eingeloggt) return <Navigate to="/login" replace />;
|
||||
return <Navigate to={startseitenPfad(istVerantwortlich)} replace />;
|
||||
}
|
||||
|
||||
function AdminRoute({ children }: { children: ReactNode }) {
|
||||
const { eingeloggt, istVerantwortlich } = useAuth();
|
||||
if (!eingeloggt) {
|
||||
@@ -39,6 +46,7 @@ export default function App() {
|
||||
<AuthProvider>
|
||||
<Routes>
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="/" element={<Startseite />} />
|
||||
<Route
|
||||
path="/objekte"
|
||||
element={
|
||||
@@ -95,7 +103,7 @@ export default function App() {
|
||||
</AdminRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="*" element={<Navigate to="/objekte" replace />} />
|
||||
<Route path="*" element={<Startseite />} />
|
||||
</Routes>
|
||||
</AuthProvider>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NavLink, useNavigate } from "react-router-dom";
|
||||
|
||||
import { useAuth } from "../auth/AuthContext";
|
||||
import { CommandPalette } from "./CommandPalette";
|
||||
import { StartseiteAuswahl } from "./StartseiteAuswahl";
|
||||
import { SyncStatus } from "./status/SyncStatus";
|
||||
import { ThemeToggle } from "./ThemeToggle";
|
||||
|
||||
@@ -48,6 +49,7 @@ export function AppShell({ children }: { children: ReactNode }) {
|
||||
{istAdmin ? "Administration" : "Verwaltung"}
|
||||
</NavLink>
|
||||
)}
|
||||
{istVerantwortlich && <StartseiteAuswahl />}
|
||||
<SyncStatus />
|
||||
<button className="btn btn-secondary" onClick={paletteOeffnen} title="Globale Suche (Strg/⌘+K)">
|
||||
🔍 Suche
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import type { StartseitePraeferenz } from "../settings/startseite";
|
||||
import { gespeichertePraeferenz, praeferenzSpeichern } from "../settings/startseite";
|
||||
|
||||
/** Nur relevant für Verantwortliche - Mitarbeiter haben ohnehin nur "Objekte". */
|
||||
export function StartseiteAuswahl() {
|
||||
const [praeferenz, setPraeferenz] = useState<StartseitePraeferenz>(() => gespeichertePraeferenz());
|
||||
|
||||
function aendern(neu: StartseitePraeferenz) {
|
||||
setPraeferenz(neu);
|
||||
praeferenzSpeichern(neu);
|
||||
}
|
||||
|
||||
return (
|
||||
<select
|
||||
className="input"
|
||||
style={{ width: "auto" }}
|
||||
value={praeferenz}
|
||||
onChange={(e) => aendern(e.target.value as StartseitePraeferenz)}
|
||||
title="Startseite nach Login"
|
||||
aria-label="Startseite nach Login"
|
||||
>
|
||||
<option value="auto">Startseite: automatisch</option>
|
||||
<option value="dashboard">Startseite: Dashboard</option>
|
||||
<option value="objekte">Startseite: Objekte</option>
|
||||
</select>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import { apiRequest } from "../api/client";
|
||||
import { useAuth } from "../auth/AuthContext";
|
||||
import type { Me } from "../api/types";
|
||||
import { startseitenPfad } from "../settings/startseite";
|
||||
|
||||
const VERANTWORTLICH_ROLLEN = ["administration", "materialverantwortlicher", "leitungsverantwortlicher"];
|
||||
|
||||
@@ -26,7 +27,7 @@ export function LoginPage() {
|
||||
// selbst /auth/me abfragen statt auf den Context zu warten.
|
||||
const me = await apiRequest<Me>("/auth/me");
|
||||
const istVerantwortlich = me.rollen.some((r) => VERANTWORTLICH_ROLLEN.includes(r));
|
||||
navigate(istVerantwortlich ? "/dashboard" : "/objekte");
|
||||
navigate(startseitenPfad(istVerantwortlich));
|
||||
} catch {
|
||||
setFehler("Login oder Passwort falsch");
|
||||
} finally {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
export type StartseitePraeferenz = "auto" | "dashboard" | "objekte";
|
||||
|
||||
const SPEICHER_KEY = "mabea-startseite";
|
||||
|
||||
export function gespeichertePraeferenz(): StartseitePraeferenz {
|
||||
try {
|
||||
const wert = localStorage.getItem(SPEICHER_KEY);
|
||||
if (wert === "dashboard" || wert === "objekte") return wert;
|
||||
} catch {
|
||||
// localStorage evtl. blockiert - "auto" als Fallback
|
||||
}
|
||||
return "auto";
|
||||
}
|
||||
|
||||
export function praeferenzSpeichern(praeferenz: StartseitePraeferenz): void {
|
||||
try {
|
||||
if (praeferenz === "auto") localStorage.removeItem(SPEICHER_KEY);
|
||||
else localStorage.setItem(SPEICHER_KEY, praeferenz);
|
||||
} catch {
|
||||
// Speichern optional
|
||||
}
|
||||
}
|
||||
|
||||
/** "auto" = bisheriges Verhalten (Verantwortliche -> Dashboard, sonst Objekte). */
|
||||
export function startseitenPfad(istVerantwortlich: boolean): string {
|
||||
const praeferenz = gespeichertePraeferenz();
|
||||
if (praeferenz === "dashboard" && istVerantwortlich) return "/dashboard";
|
||||
if (praeferenz === "objekte") return "/objekte";
|
||||
return istVerantwortlich ? "/dashboard" : "/objekte";
|
||||
}
|
||||
Reference in New Issue
Block a user