Seitenleiste: die vier Bestandslisten klappen zusammen
Lebensmittel, Gegenstaende, Einzelstuecke und Chargen stehen jetzt unter einer Gruppe "Listen". Sie ist der laengste Block der Leiste und wird im Alltag selten gebraucht - wer einlagert, nimmt die Knoepfe darueber. Vorgabe ist zugeklappt, der Zustand bleibt im Browser (wie die Spalteneinstellungen der Tabellen). Steht man auf einer dieser Seiten, klappt die Gruppe auf, ohne den gemerkten Zustand zu ueberschreiben - sonst saehe man nicht, wo man ist. Die Eintraege bleiben dabei im Dokument und werden nur per Klasse verborgen: Auf schmalen Bildschirmen wird die Leiste waagerecht, dort gibt es keine Abschnitte und kein Platzproblem, also blendet die CSS sie wieder ein und die Gruppe selbst aus. Waeren sie ausgehaengt, waeren sie dort weg. Die Mobil-Regeln brauchen `.sidebar` davor: Ein Media-Query erhoeht die Spezifitaet nicht, und die Grundregeln stehen weiter unten in der Datei - ohne das gewinnt die spaetere Regel und die Ausnahme greift nie. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
afacf01f11
commit
a182037153
+50
-4
@@ -34,6 +34,17 @@ import Konto from "./pages/Konto";
|
||||
|
||||
const navClass = ({ isActive }) => (isActive ? "nav-link active" : "nav-link");
|
||||
|
||||
// Die vier Bestandslisten stehen unter einer zuklappbaren Gruppe. Sie sind der
|
||||
// laengste Block der Leiste und wird im Alltag selten gebraucht – wer einlagert,
|
||||
// nutzt die Knoepfe darueber.
|
||||
const LISTEN = [
|
||||
{ to: "/lebensmittel", icon: "food", label: "Lebensmittel" },
|
||||
{ to: "/gegenstaende", icon: "package", label: "Gegenstände" },
|
||||
{ to: "/items", icon: "tag", label: "Einzelstücke" },
|
||||
{ to: "/chargen", icon: "box", label: "Chargen" },
|
||||
];
|
||||
const LISTEN_OFFEN_KEY = "nav:listen-offen";
|
||||
|
||||
function NavItem({ to, icon, label, end }) {
|
||||
return (
|
||||
<NavLink to={to} end={end} className={navClass}>
|
||||
@@ -46,7 +57,24 @@ function NavItem({ to, icon, label, end }) {
|
||||
function Sidebar() {
|
||||
const { user, isAdmin, logout } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
const [dashboards, setDashboards] = useState([]);
|
||||
// Zugeklappt als Vorgabe; der Zustand bleibt im Browser, wie die
|
||||
// Spalteneinstellungen der Tabellen.
|
||||
const [listenOffen, setListenOffen] = useState(
|
||||
() => localStorage.getItem(LISTEN_OFFEN_KEY) === "1",
|
||||
);
|
||||
// Steht man auf einer dieser Seiten, ist die Gruppe offen – ohne den
|
||||
// gemerkten Zustand zu ueberschreiben. Sonst saehe man nicht, wo man ist.
|
||||
const aufEinerListe = LISTEN.some((e) => pathname.startsWith(e.to));
|
||||
|
||||
function klappeListen() {
|
||||
setListenOffen((alt) => {
|
||||
const neu = !alt;
|
||||
localStorage.setItem(LISTEN_OFFEN_KEY, neu ? "1" : "0");
|
||||
return neu;
|
||||
});
|
||||
}
|
||||
|
||||
// Die Dashboards des Benutzers stehen als eigene Eintraege in der Leiste.
|
||||
// Sie aendern sich beim Anlegen und Loeschen, deshalb horcht die Leiste auf
|
||||
@@ -82,10 +110,28 @@ function Sidebar() {
|
||||
))}
|
||||
<NavItem to="/checkin" icon="checkin" label="Einlagern" />
|
||||
<NavItem to="/checkout" icon="checkout" label="Auslagern" />
|
||||
<NavItem to="/lebensmittel" icon="food" label="Lebensmittel" />
|
||||
<NavItem to="/gegenstaende" icon="package" label="Gegenstände" />
|
||||
<NavItem to="/items" icon="tag" label="Einzelstücke" />
|
||||
<NavItem to="/chargen" icon="box" label="Chargen" />
|
||||
{/* Auf schmalen Bildschirmen wird die Leiste waagerecht; dort gibt es
|
||||
keine Abschnitte (styles.css) und die Eintraege stehen flach
|
||||
nebeneinander – zuklappen loest dort kein Platzproblem. */}
|
||||
<button type="button" className="nav-group" onClick={klappeListen}
|
||||
aria-expanded={listenOffen || aufEinerListe}>
|
||||
<Icon name="chevron" size={14}
|
||||
className={listenOffen || aufEinerListe ? "" : "rot-90"} />
|
||||
<span>Listen</span>
|
||||
</button>
|
||||
{LISTEN.map((e) => (
|
||||
<NavLink key={e.to} to={e.to}
|
||||
className={({ isActive }) => [
|
||||
"nav-link nav-child",
|
||||
isActive ? "active" : "",
|
||||
// Nicht ausgehaengt, nur verborgen: auf schmalen Bildschirmen
|
||||
// blendet die CSS sie wieder ein, dort gibt es keine Gruppe.
|
||||
listenOffen || aufEinerListe ? "" : "nav-zu",
|
||||
].filter(Boolean).join(" ")}>
|
||||
<Icon name={e.icon} size={16} />
|
||||
<span className="label">{e.label}</span>
|
||||
</NavLink>
|
||||
))}
|
||||
<NavItem to="/shopping" icon="cart" label="Einkaufsliste" />
|
||||
<NavItem to="/mindestbestaende" icon="check" label="Mindestbestände" />
|
||||
<NavItem to="/verliehen" icon="loan" label="Verliehen" />
|
||||
|
||||
Reference in New Issue
Block a user