send
This commit is contained in:
@@ -6,13 +6,13 @@ $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https'
|
|||||||
$host = $_SERVER['HTTP_HOST'] ?? 'usbcheck.it';
|
$host = $_SERVER['HTTP_HOST'] ?? 'usbcheck.it';
|
||||||
$baseUrl = $scheme . '://' . $host;
|
$baseUrl = $scheme . '://' . $host;
|
||||||
|
|
||||||
// Wenn $navAnchors NICHT gesetzt ist → leeres Array
|
// Falls navAnchors nicht gesetzt sind → leeres Array
|
||||||
if (!isset($navAnchors) || !is_array($navAnchors)) {
|
if (!isset($navAnchors) || !is_array($navAnchors)) {
|
||||||
$navAnchors = [];
|
$navAnchors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session sollte in config/fileload.php bereits gestartet sein.
|
// Session sollte in config/fileload.php bereits gestartet sein.
|
||||||
// Falls nicht, hier Fallback:
|
// Fallback:
|
||||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
@session_start();
|
@session_start();
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ if ($isLoggedIn) {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Navigation + Controls -->
|
<!-- Navigation / Controls -->
|
||||||
<div class="flex items-center gap-6">
|
<div class="flex items-center gap-6">
|
||||||
|
|
||||||
<!-- Hauptnavigation -->
|
<!-- Hauptnavigation -->
|
||||||
@@ -119,19 +119,18 @@ if ($isLoggedIn) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Login Button / Avatar -->
|
<!-- Login / Avatar -->
|
||||||
<?php if (!$isLoggedIn): ?>
|
<div class="relative">
|
||||||
<!-- Nicht eingeloggt: Login-Button anzeigen -->
|
<?php if (!$isLoggedIn): ?>
|
||||||
<button id="loginButton"
|
<!-- Nicht eingeloggt: Login-Button -->
|
||||||
class="relative inline-flex items-center justify-center rounded-full bg-brand-primary px-4 py-1.5 text-xs font-semibold uppercase tracking-[0.18em] text-brand-bg shadow-soft hover:bg-cyan-400 transition-colors"
|
<button id="loginButton"
|
||||||
data-i18n="header_btn_login">
|
class="relative inline-flex items-center justify-center rounded-full bg-brand-primary px-4 py-1.5 text-xs font-semibold uppercase tracking-[0.18em] text-brand-bg shadow-soft hover:bg-cyan-400 transition-colors"
|
||||||
Login
|
data-i18n="header_btn_login">
|
||||||
</button>
|
Login
|
||||||
<?php else: ?>
|
</button>
|
||||||
<!-- Eingeloggt: Avatar + User-Menü -->
|
<?php else: ?>
|
||||||
<div class="relative">
|
<!-- Eingeloggt: Avatar + Menü -->
|
||||||
<button id="userAvatar"
|
<button id="userAvatar"
|
||||||
type="button"
|
|
||||||
class="h-9 w-9 rounded-full border border-brand-border bg-brand-surface flex items-center justify-center text-xs font-semibold text-brand-text shadow-soft hover:border-brand-primary transition"
|
class="h-9 w-9 rounded-full border border-brand-border bg-brand-surface flex items-center justify-center text-xs font-semibold text-brand-text shadow-soft hover:border-brand-primary transition"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
@@ -140,19 +139,23 @@ if ($isLoggedIn) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div id="userMenu"
|
<div id="userMenu"
|
||||||
class="hidden absolute right-0 mt-2 w-40 rounded-xl bg-brand-surface border border-brand-border shadow-lg py-1 text-xs text-brand-muted">
|
class="hidden absolute right-0 mt-2 w-44 rounded-xl bg-brand-surface border border-brand-border shadow-lg py-1 text-xs">
|
||||||
<a href="/dashboard/?lang=<?= urlencode($lang) ?>"
|
<a href="/dashboard/?lang=<?= urlencode($lang) ?>"
|
||||||
class="flex items-center gap-2 px-3 py-1.5 hover:bg-brand-bg/60 hover:text-brand-primary transition-colors">
|
class="flex items-center justify-between px-3 py-2 hover:bg-brand-bg/60 text-brand-muted hover:text-brand-primary transition-colors"
|
||||||
|
data-i18n="header_menu_dashboard">
|
||||||
<span>Dashboard</span>
|
<span>Dashboard</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/auth/logout?lang=<?= urlencode($lang) ?>"
|
|
||||||
id="userMenuLogout"
|
<button type="button"
|
||||||
class="flex items-center gap-2 px-3 py-1.5 hover:bg-brand-bg/60 hover:text-red-300 transition-colors">
|
data-logout-link="true"
|
||||||
|
data-logout-href="/auth/logout?lang=<?= urlencode($lang) ?>"
|
||||||
|
class="flex w-full items-center justify-between px-3 py-2 hover:bg-red-500/10 text-brand-muted hover:text-red-400 transition-colors"
|
||||||
|
data-i18n="header_menu_logout">
|
||||||
<span>Logout</span>
|
<span>Logout</span>
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -47,6 +47,34 @@ foreach ($GLOBALS['page_footer_scripts'] as $script) {
|
|||||||
|
|
||||||
<!-- Globale JS-Dateien -->
|
<!-- Globale JS-Dateien -->
|
||||||
<script src="/assets/js/lang.js"></script>
|
<script src="/assets/js/lang.js"></script>
|
||||||
|
<!-- Logout-Modal -->
|
||||||
|
<div id="logoutModalBackdrop"
|
||||||
|
class="hidden fixed inset-0 z-50 bg-black/60 backdrop-blur-sm">
|
||||||
|
<div class="min-h-full flex items-center justify-center p-4">
|
||||||
|
<div class="w-full max-w-sm rounded-2xl border border-brand-border bg-brand-surface shadow-soft p-6 space-y-4">
|
||||||
|
<h2 class="font-heading text-lg font-semibold text-white" data-i18n="logout_modal_title">
|
||||||
|
Wirklich ausloggen?
|
||||||
|
</h2>
|
||||||
|
<p class="text-sm text-brand-muted" data-i18n="logout_modal_text">
|
||||||
|
Wenn du dich abmeldest, werden deine Sitzung und alle nicht gespeicherten Aktionen beendet. Du kannst dich jederzeit wieder einloggen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex justify-end gap-3 pt-2">
|
||||||
|
<button type="button"
|
||||||
|
id="logoutCancel"
|
||||||
|
class="inline-flex items-center justify-center rounded-full border border-brand-border px-4 py-1.5 text-xs font-semibold uppercase tracking-[0.18em] text-brand-muted hover:border-brand-primary hover:text-brand-primary transition-colors"
|
||||||
|
data-i18n="logout_modal_cancel">
|
||||||
|
Abbrechen
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
id="logoutConfirm"
|
||||||
|
class="inline-flex items-center justify-center rounded-full bg-red-500/90 px-4 py-1.5 text-xs font-semibold uppercase tracking-[0.18em] text-white shadow-soft hover:bg-red-400 transition-colors"
|
||||||
|
data-i18n="logout_modal_confirm">
|
||||||
|
Ja, ausloggen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ if (!isset($pageTitle) || !is_string($pageTitle) || $pageTitle === '') {
|
|||||||
if (!isset($pageDescription) || !is_string($pageDescription)) {
|
if (!isset($pageDescription) || !is_string($pageDescription)) {
|
||||||
$pageDescription = '';
|
$pageDescription = '';
|
||||||
}
|
}
|
||||||
|
if (function_exists('tpl_add_script')) {
|
||||||
tpl_add_script('/assets/js/header-user-menu.js', 'footer', true, false, '', null);
|
tpl_add_script('/assets/js/header-user-menu.js', 'footer', true, false, '', null);
|
||||||
|
tpl_add_script('/assets/js/header.js', 'footer', true, false, '', null);
|
||||||
|
}
|
||||||
|
|
||||||
// Kann später genutzt werden, falls du host-spezifische Sachen brauchst
|
// Kann später genutzt werden, falls du host-spezifische Sachen brauchst
|
||||||
$host = $_SERVER['HTTP_HOST'] ?? '';
|
$host = $_SERVER['HTTP_HOST'] ?? '';
|
||||||
|
|||||||
108
public/assets/js/header.js
Normal file
108
public/assets/js/header.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// public/assets/js/header.js
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
// -------------------------
|
||||||
|
// Avatar-Menü ein-/ausblenden
|
||||||
|
// -------------------------
|
||||||
|
const avatarBtn = document.getElementById('userAvatar');
|
||||||
|
const userMenu = document.getElementById('userMenu');
|
||||||
|
|
||||||
|
if (avatarBtn && userMenu) {
|
||||||
|
avatarBtn.addEventListener('click', function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
userMenu.classList.toggle('hidden');
|
||||||
|
|
||||||
|
const expanded = avatarBtn.getAttribute('aria-expanded') === 'true';
|
||||||
|
avatarBtn.setAttribute('aria-expanded', expanded ? 'false' : 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Klick außerhalb schließt Menü
|
||||||
|
document.addEventListener('click', function (event) {
|
||||||
|
if (!userMenu.classList.contains('hidden')) {
|
||||||
|
const clickedInsideMenu = userMenu.contains(event.target);
|
||||||
|
const clickedAvatarButton = avatarBtn.contains(event.target);
|
||||||
|
|
||||||
|
if (!clickedInsideMenu && !clickedAvatarButton) {
|
||||||
|
userMenu.classList.add('hidden');
|
||||||
|
avatarBtn.setAttribute('aria-expanded', 'false');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Logout-Modal
|
||||||
|
// -------------------------
|
||||||
|
const logoutButtons = document.querySelectorAll('[data-logout-link="true"]');
|
||||||
|
const backdrop = document.getElementById('logoutModalBackdrop');
|
||||||
|
const btnConfirm = document.getElementById('logoutConfirm');
|
||||||
|
const btnCancel = document.getElementById('logoutCancel');
|
||||||
|
|
||||||
|
let logoutTarget = null;
|
||||||
|
|
||||||
|
function showLogoutModal(targetHref) {
|
||||||
|
logoutTarget = targetHref || null;
|
||||||
|
if (!backdrop) return;
|
||||||
|
|
||||||
|
backdrop.classList.remove('hidden');
|
||||||
|
// kleine Fokushilfe: Escape schließt, Klick auf Hintergrund auch
|
||||||
|
document.body.classList.add('overflow-hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideLogoutModal() {
|
||||||
|
if (!backdrop) return;
|
||||||
|
backdrop.classList.add('hidden');
|
||||||
|
document.body.classList.remove('overflow-hidden');
|
||||||
|
logoutTarget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logout-Link(s) abfangen
|
||||||
|
if (logoutButtons.length && backdrop && btnConfirm && btnCancel) {
|
||||||
|
logoutButtons.forEach(function (btn) {
|
||||||
|
btn.addEventListener('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const href = btn.getAttribute('data-logout-href') || btn.getAttribute('href') || '/auth/logout';
|
||||||
|
showLogoutModal(href);
|
||||||
|
|
||||||
|
// Avatar-Menü beim Öffnen des Modals schließen
|
||||||
|
if (userMenu && !userMenu.classList.contains('hidden')) {
|
||||||
|
userMenu.classList.add('hidden');
|
||||||
|
if (avatarBtn) {
|
||||||
|
avatarBtn.setAttribute('aria-expanded', 'false');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bestätigen → weiter zur Logout-URL
|
||||||
|
btnConfirm.addEventListener('click', function () {
|
||||||
|
if (logoutTarget) {
|
||||||
|
window.location.href = logoutTarget;
|
||||||
|
} else {
|
||||||
|
window.location.href = '/auth/logout';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Abbrechen → Modal schließen
|
||||||
|
btnCancel.addEventListener('click', function () {
|
||||||
|
hideLogoutModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Klick auf Hintergrund (außerhalb der Card) schließt ebenfalls
|
||||||
|
backdrop.addEventListener('click', function (event) {
|
||||||
|
const card = backdrop.querySelector('div.w-full.max-w-sm');
|
||||||
|
if (card && !card.contains(event.target)) {
|
||||||
|
hideLogoutModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ESC-Taste schließt Modal
|
||||||
|
document.addEventListener('keydown', function (event) {
|
||||||
|
if (event.key === 'Escape' && !backdrop.classList.contains('hidden')) {
|
||||||
|
hideLogoutModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user