Unifi-Voucher-Tool/includes/admin_nav.php
Friederich Loheide 8facc71455
Some checks are pending
CI / PHP Lint (pull_request) Waiting to run
CI / PHP Lint-1 (pull_request) Waiting to run
CI / Unit Tests & Static Analysis (pull_request) Waiting to run
CI / PHP Lint (push) Waiting to run
CI / PHP Lint-1 (push) Waiting to run
CI / Unit Tests & Static Analysis (push) Waiting to run
Release-Workflow: ZIP bei jedem Merge nach main
.github/workflows/release.yml baut bei jedem Push auf main (also auch
nach jedem gemergten Pull Request) ein installierbares Paket und hängt es
an das rollende Vorab-Release "latest-main". Der Download-Link bleibt
damit stabil und zeigt immer auf den aktuellen Stand. Ein Tag v* erzeugt
mit derselben Mechanik ein reguläres Release.

Details:
- das ZIP entsteht per `git archive`, die Auswahl steuert .gitattributes
  (export-ignore) – docs/, tests/, tools/ und CI bleiben draußen, das
  Paket ist rund 1,4 MB groß
- eine Prüfschritt kontrolliert, dass Kerndateien wirklich enthalten sind,
  dazu gibt es eine .sha256-Datei
- zusätzlich als Build-Artefakt abgelegt (optional, bricht nicht ab, wenn
  der Artefakt-Speicher fehlt)
- Release-API wird über den automatisch bereitgestellten Token
  angesprochen, FORGEJO_TOKEN dient als Ausweichweg; ohne Token wird der
  Schritt übersprungen statt fehlzuschlagen

Neu ist die Datei VERSION als einzige Quelle der Versionsnummer: sie
benennt das Paket und erscheint über Ui::version() unten in der
Admin-Seitenleiste ("v2.6.0 · Entwickelt von Loheide.eu").

Geprüft: Paket lokal gebaut, entpackt und die Anwendung daraus gestartet –
alle Seiten antworten mit 200, keine fehlenden Dateien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 14:50:10 +00:00

124 lines
5.6 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Shared admin navigation/header snippet.
* Expects $currentPage (string), $appTitle (string), $auth, $db to be set before include.
* Expects I18n to be initialized.
*/
require_once __DIR__ . '/Ui.php';
$currentPage = $currentPage ?? '';
$currentUser = isset($auth) ? $auth->getCurrentUser() : null;
$lang = I18n::getLanguage();
$base = $adminBase ?? ''; // Prefix bis zum admin/-Ordner
$rootBase = $base === '' ? '../' : ''; // Prefix bis zum Projekt-Root
/** Navigation als Datenstruktur Reihenfolge = Darstellung. */
$navGroups = [
'nav_group_overview' => [
['dashboard', 'index.php', 'fa-chart-pie', 'nav_dashboard'],
['reports', 'reports.php', 'fa-chart-line', 'nav_reports'],
['audit_log', 'audit_log.php', 'fa-clock-rotate-left','nav_audit_log'],
],
'nav_group_manage' => [
['vouchers', 'vouchers.php', 'fa-ticket', 'nav_vouchers'],
['templates', 'templates.php', 'fa-layer-group', 'nav_templates'],
['import', 'import.php', 'fa-file-arrow-up', 'nav_import'],
['sites', 'sites.php', 'fa-location-dot', 'nav_sites'],
['users', 'users.php', 'fa-users', 'nav_users'],
],
'nav_group_system' => [
['settings', 'settings.php', 'fa-sliders', 'nav_settings'],
['integrations', 'integrations.php', 'fa-plug', 'nav_integrations'],
['api_keys', 'api_keys.php', 'fa-key', 'nav_api_keys'],
['security', 'security.php', 'fa-shield-halved','nav_security'],
['backup', 'backup.php', 'fa-database', 'nav_backup'],
['update', 'update.php', 'fa-rotate', 'nav_update'],
],
];
/** Aktuellen Seitentitel für die Breadcrumb finden. */
$currentLabel = __('nav_dashboard');
foreach ($navGroups as $items) {
foreach ($items as $item) {
if ($item[0] === $currentPage) { $currentLabel = __($item[3]); }
}
}
?>
<?= Ui::head($db ?? null, $rootBase) ?>
</head>
<body>
<a class="skip-link" href="#main-content"><?= __('a11y_skip') ?></a>
<div class="sidebar-overlay" onclick="closeMobileSidebar()"></div>
<aside class="sidebar" id="adminSidebar" aria-label="<?= __('nav_administration') ?>">
<a href="<?= $rootBase ?>index.php" class="sidebar-brand">
<span class="brand-mark"><i class="fas fa-wifi" aria-hidden="true"></i></span>
<span class="brand-text">
<span class="brand-name"><?= htmlspecialchars($appTitle ?? 'Voucher Tool') ?></span>
<span class="brand-sub"><?= __('nav_administration') ?></span>
</span>
</a>
<nav>
<?php foreach ($navGroups as $groupKey => $items): ?>
<div class="sidebar-section"><?= __($groupKey) ?></div>
<ul class="sidebar-nav">
<?php foreach ($items as [$key, $href, $icon, $labelKey]): ?>
<li>
<a href="<?= $base . $href ?>" class="<?= $currentPage === $key ? 'active' : '' ?>"
<?= $currentPage === $key ? 'aria-current="page"' : '' ?>>
<i class="fas <?= $icon ?>" aria-hidden="true"></i> <?= __($labelKey) ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
</nav>
<div class="sidebar-foot">
<?php if ($currentUser): ?>
<div class="user-menu" style="width:100%;justify-content:flex-start;">
<div class="user-avatar"><?= strtoupper(mb_substr($currentUser['name'], 0, 1)) ?></div>
<div style="min-width:0;flex:1;">
<div class="user-name" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"><?= htmlspecialchars($currentUser['name']) ?></div>
<div class="user-role"><?= htmlspecialchars($currentUser['role'] ?? '') ?></div>
</div>
<a href="<?= $rootBase ?>logout.php" class="icon-btn" title="<?= __('btn_logout') ?>" aria-label="<?= __('btn_logout') ?>" style="width:30px;height:30px;font-size:12px;">
<i class="fas fa-arrow-right-from-bracket" aria-hidden="true"></i>
</a>
</div>
<?php endif; ?>
<?= Ui::credit(true) ?>
</div>
</aside>
<header class="topbar">
<div class="header-left">
<button class="mobile-menu-btn" onclick="toggleMobileSidebar()" aria-label="<?= __('a11y_menu') ?>" title="<?= __('a11y_menu') ?>">
<i class="fas fa-bars" aria-hidden="true"></i>
</button>
<div class="breadcrumb">
<span><?= __('nav_administration') ?></span>
<span class="sep">/</span>
<span class="current"><?= htmlspecialchars($currentLabel) ?></span>
</div>
</div>
<div class="header-right">
<div class="lang-switcher" role="group" aria-label="<?= __('a11y_language') ?>">
<?php foreach (I18n::getAvailable() as $code => $label): ?>
<button class="lang-btn <?= $lang === $code ? 'active' : '' ?>"
onclick="switchLanguage('<?= $code ?>')"><?= strtoupper($code) ?></button>
<?php endforeach; ?>
</div>
<button id="darkModeBtn" class="dark-mode-toggle" onclick="toggleDarkMode()" aria-label="<?= __('a11y_theme') ?>" title="<?= __('a11y_theme') ?>">
<i class="fas fa-moon" aria-hidden="true"></i>
</button>
<a href="<?= $rootBase ?>index.php" class="btn btn-secondary">
<i class="fas fa-arrow-left" aria-hidden="true"></i>
<span class="hide-mobile"><?= __('nav_back') ?></span>
</a>
</div>
</header>
<main class="main-content" id="main-content">