Die Marke oben in der Seitenleiste trägt jetzt das Coinstack-Symbol aus den Altdaten und den zweifarbigen Schriftzug Finanz|manager – wie die sidebar-brand im Steuerkram. Sie ist zugleich der Schalter: Ein Klick schiebt die Leiste von 232 px auf 64 px zusammen, ein Klick auf das Symbol klappt sie wieder auf. Die Menüpunkte behalten dabei Ziel und Symbol. Der Zustand steht in einem Cookie und nicht im localStorage: So rendert der Server die Leiste schon in der richtigen Breite, statt sie bei jedem Seitenwechsel kurz breit aufblitzen zu lassen. Die Beschriftungen wandern eingeklappt per clip-path aus dem Bild statt per display:none – sonst verlören die Verweise ihren Namen für Vorleseprogramme. Nebenbei: Die Marke hieß bisher .marke, wie die kleine Statusmarke weiter unten im Stilblatt, deren Regeln sie überschrieben. Sie heißt jetzt .seitenleisten-marke. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
99 lines
4.8 KiB
PHP
99 lines
4.8 KiB
PHP
<?php
|
||
|
||
use Finanzmanager\View;
|
||
|
||
/** @var string $titel */
|
||
/** @var array $flash */
|
||
/** @var string|null $aktuellerPfad */
|
||
/** @var array|null $benutzer */
|
||
|
||
$navigation = [
|
||
['pfad' => '/', 'name' => 'Cockpit', 'icon' => '⌂'],
|
||
['pfad' => '/konten', 'name' => 'Kontenübersicht', 'icon' => '▤'],
|
||
['pfad' => '/banking', 'name' => 'Online-Banking', 'icon' => '⇊'],
|
||
['pfad' => '/zahlungsverkehr', 'name' => 'Zahlungsverkehr', 'icon' => '⇄'],
|
||
['pfad' => '/auswertungen', 'name' => 'Auswertungen', 'icon' => '◱'],
|
||
['pfad' => '/planung', 'name' => 'Planung', 'icon' => '◷'],
|
||
['pfad' => '/wertpapiere', 'name' => 'Wertpapiere', 'icon' => '↗'],
|
||
// Termine und Verträge haben keinen eigenen Menüpunkt mehr, sind aber weiter
|
||
// erreichbar – deshalb leuchtet für sie die Verwaltung, unter der sie hängen.
|
||
['pfad' => '/verwaltung', 'name' => 'Verwaltung', 'icon' => '⚙', 'auch' => ['/termine', '/vertraege']],
|
||
];
|
||
|
||
// Ob die Seitenleiste eingeklappt ist, merkt sich ein Cookie. Das Skript
|
||
// setzt es beim Umschalten; hier entscheidet es schon beim Rendern, damit die
|
||
// breite Leiste nicht bei jedem Seitenwechsel kurz aufblitzt.
|
||
$eingeklappt = ($_COOKIE['seitenleiste'] ?? '') === 'eingeklappt';
|
||
|
||
/** @param list<string> $auch */
|
||
$istAktiv = static function (string $pfad, array $auch = []) use ($aktuellerPfad): bool {
|
||
if (!is_string($aktuellerPfad)) {
|
||
return false;
|
||
}
|
||
if ($pfad === '/') {
|
||
return $aktuellerPfad === '/' || $aktuellerPfad === '';
|
||
}
|
||
foreach ([$pfad, ...$auch] as $kandidat) {
|
||
if (str_starts_with($aktuellerPfad, $kandidat)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="de"<?= ($thema = View::thema()) !== '' ? ' data-thema="' . View::h($thema) . '"' : '' ?>>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title><?= View::h($titel ?? 'Finanzmanager') ?> – Finanzmanager</title>
|
||
<link rel="stylesheet" href="/static/app.css">
|
||
<!-- Nur hier eingebunden: Ein zweites Mal im Fuß ließe jeden Handler doppelt
|
||
laufen – Rückfragen kämen zweimal, Menüs entstünden zweimal. -->
|
||
<script src="/static/app.js" defer></script>
|
||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><text y='13' font-size='13'>€</text></svg>">
|
||
</head>
|
||
<body>
|
||
<?php include __DIR__ . '/meldungen.php'; ?>
|
||
<div class="rahmen<?= $eingeklappt ? ' eingeklappt' : '' ?>">
|
||
<nav class="seitenleiste" id="seitenleiste" aria-label="Hauptnavigation">
|
||
<!-- Die Marke ist zugleich der Schalter: Ein Klick schiebt die
|
||
Seitenleiste auf Symbolbreite zusammen und wieder auf. -->
|
||
<button type="button" class="seitenleisten-marke" data-seitenleiste-schalter
|
||
aria-controls="seitenleiste" aria-expanded="<?= $eingeklappt ? 'false' : 'true' ?>"
|
||
title="<?= $eingeklappt ? 'Seitenleiste ausklappen' : 'Seitenleiste einklappen' ?>">
|
||
<img src="/static/coinstack.png" alt="" class="marken-symbol">
|
||
<span class="marken-text">Finanz<span>manager</span></span>
|
||
</button>
|
||
<ul>
|
||
<?php foreach ($navigation as $eintrag): ?>
|
||
<li>
|
||
<?php /* title bleibt hinten: Der Navigationstest prüft href und
|
||
class in dieser Reihenfolge unmittelbar hintereinander. */ ?>
|
||
<a href="<?= View::h($eintrag['pfad']) ?>"
|
||
class="<?= $istAktiv($eintrag['pfad'], $eintrag['auch'] ?? []) ? 'aktiv' : '' ?>"
|
||
title="<?= View::h($eintrag['name']) ?>">
|
||
<span class="icon" aria-hidden="true"><?= $eintrag['icon'] ?></span>
|
||
<span class="beschriftung"><?= View::h($eintrag['name']) ?></span>
|
||
</a>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</nav>
|
||
|
||
<div class="hauptbereich">
|
||
<header class="werkzeugleiste">
|
||
<h1><?= View::h($titel ?? 'Finanzmanager') ?></h1>
|
||
<div class="werkzeuge">
|
||
<a href="/einstellungen" class="werkzeug" title="Einstellungen">⚙ Einstellungen</a>
|
||
<?php if (!empty($benutzer)): ?>
|
||
<span class="benutzer"><?= View::h($benutzer['anzeigename'] ?: $benutzer['benutzername']) ?></span>
|
||
<form method="post" action="/logout" class="inline">
|
||
<input type="hidden" name="csrf_token" value="<?= View::h($csrfToken ?? '') ?>">
|
||
<button type="submit" class="werkzeug">Abmelden</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="inhalt">
|