Files
xxx-sphere-web/bin/main/static/js/sidebar.js
Mario 4f2048bdc8
Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
Weiter gebaut
2026-04-25 16:56:35 +02:00

276 lines
13 KiB
JavaScript

(function () {
const path = window.location.pathname;
const I = window.IC || function() { return ''; };
const groups = [
{
label: 'Chastity Game',
icon: I('CHASTITY'),
items: [
{ href: '/games/chastity/neulock.html', icon: I('NEW_LOCK'), label: 'Neues Lock', id: 'navChastityNeu' },
{ href: '#', icon: I('ACTIVE_LOCK'), label: 'Aktives Lock', id: 'navChastityAktiv' },
{ href: '/games/chastity/communityvotes.html', icon: I('VOTES'), label: 'Community Votes' },
{ href: '/games/chastity/meine-locks.html', icon: I('LOCK'), label: 'Meine Vorlagen' },
{ href: '/games/chastity/entdecken-vorlagen.html', icon: I('DISCOVER'), label: 'Entdecken' },
{ href: '/games/chastity/keyholder-finden.html', icon: I('FRIENDS'), label: 'Keyholder finden' },
{ href: '/games/chastity/keyholder.html', icon: I('KEY'), label: 'Keyholder' },
{ href: '/games/chastity/unlock-history.html', icon: I('HISTORY'), label: 'Code-Historie' },
]
},
{
label: 'Aufgabenverwaltung',
icon: I('CHECK'),
items: [
{ href: '/games/aufgaben/aufgaben.html', icon: I('CHECK'), label: 'Aufgaben' },
{ href: '/games/aufgaben/toys.html', icon: I('TOYS'), label: 'Toys' },
{ href: '/games/aufgaben/entdecken.html',icon: I('DISCOVER'), label: 'Entdecken' },
]
},
];
const vanillaCls = path.startsWith('/games/vanilla/') ? ' class="active"' : '';
const bdsmCls = path.startsWith('/games/bdsm/') ? ' class="active"' : '';
const vanillaLink = `<li><a href="/games/vanilla/neuvanilla.html" id="navVanillaGame"${vanillaCls}><span class="icon">${I('VANILLA') || '⚪'}</span> Vanilla Game</a></li>`;
const bdsmLink = `<li><a href="/games/bdsm/neubdsm.html" id="navBdsmGame"${bdsmCls}><span class="icon">${I('BDSM') || '⛓️'}</span> BDSM Game</a></li>`;
// ── Hilfsfunktion: einzelner Nav-Link ──
function navLink({ href, icon, label, badgeId }) {
const cls = path === href ? ' class="active"' : '';
const badge = badgeId ? `<span class="social-badge" id="${badgeId}" style="display:none;"></span>` : '';
return `<li><a href="${href}"${cls}><span class="icon">${icon}</span> ${label}${badge}</a></li>`;
}
const sep = `<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;"></li>`;
const catLabel = label => `<li class="sidebar-cat-label">${label}</li>`;
// Home
const homeNav = navLink({ href: '/userhome.html', icon: I('HOME') || '⌂', label: 'Home' });
const searchNav = navLink({ href: '/search.html', icon: I('SEARCH') || '🔍', label: 'Suche' });
// Kommunikation
const commLinks = [
{ href: '/community/nachrichten.html', icon: I('MESSAGES'), label: 'Nachrichten' },
{ href: '/community/benachrichtigungen.html', icon: I('NOTIFICATIONS'), label: 'Benachrichtigungen' },
{ href: '/games/common/einladungen.html', icon: I('INVITATIONS'), label: 'Einladungen' },
];
// Social
const socialLinks = [
{ href: '/community/feed.html', icon: I('FEED'), label: 'Feed' },
{ href: '/community/freunde.html', icon: I('FRIENDS'), label: 'Freunde', badgeId: 'socialFriendsBadge' },
{ href: '/community/gruppen.html', icon: I('GROUPS'), label: 'Gruppen', badgeId: 'socialGruppenBadge' },
{ href: '/community/locations.html', icon: I('LOCATION') || '📍', label: 'Locations' },
{ href: '/community/events.html', icon: I('EVENT') || '🗓', label: 'Veranstaltungen' },
];
const socialNav = [
homeNav,
searchNav,
sep,
...commLinks.map(navLink),
sep,
...socialLinks.map(navLink),
].join('');
const datingLinks = [
{ href: '/dating/dating.html', icon: I('DATING') || '♥', label: 'Dating', id: 'navDating' },
{ href: '/dating/besucher.html', icon: '👀', label: 'Besucher' },
{ href: '/dating/likes.html', icon: '❤️', label: 'Likes' },
{ href: '/dating/matches.html', icon: '💕', label: 'Matches' },
];
const datingItem = datingLinks.map(({ href, icon, label, id }) => {
const cls = path === href ? ' class="active"' : '';
const idAttr = id ? ` id="${id}"` : '';
return `<li${idAttr}><a href="${href}"${cls}><span class="icon">${icon}</span> ${label}</a></li>`;
}).join('');
const fullHref = path + window.location.search;
const nav = groups.map(({ label, icon, items }) => {
const isOpen = items.some(item => item.href === path || item.href === fullHref);
const openCls = isOpen ? ' open' : '';
const subItems = items.map(({ href, icon: iIcon, label: iLabel, id: iId }) => {
const cls = (href === path || href === fullHref) ? ' class="active"' : '';
const idAt = iId ? ` id="${iId}"` : '';
return `<li${idAt}><a href="${href}"${cls}><span class="icon">${iIcon}</span> ${iLabel}</a></li>`;
}).join('');
return `
<li class="sidebar-group${openCls}">
<a class="sidebar-group-toggle"><span class="icon">${icon}</span> ${label}<span class="sidebar-arrow">${I('ARROW')}</span></a>
<ul class="sidebar-sub">
${subItems}
</ul>
</li>`;
}).join('');
const adminCls = path === '/admin/admin.html' ? ' class="active"' : '';
const adminItem = `<li id="navAdminLink" style="display:none"><a href="/admin/admin.html"${adminCls}><span class="icon">${I('ADMIN') || '⚙'}</span> Administration</a></li>`;
const footerLinks = [
{ href: '/help/kontakt.html', icon: '✉️', label: 'Kontakt & Feedback' },
{ href: '/help/impressum.html', icon: '📄', label: 'Impressum' },
];
const footerNav = footerLinks.map(({ href, icon, label }) => {
const cls = path === href ? ' class="active"' : '';
return `<li><a href="${href}"${cls}><span class="icon">${icon}</span> ${label}</a></li>`;
}).join('');
document.body.insertAdjacentHTML('afterbegin', `
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<button class="burger" id="burgerBtn" aria-label="Menü öffnen">
<span class="burger-icon"><span></span><span></span><span></span></span>
</button>
<div class="sidebar-wrapper" id="sidebar">
<aside class="sidebar">
<div class="sidebar-scroll-area">
<ul>
${socialNav}
${sep}
${datingItem}
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;"></li>
${vanillaLink}
${bdsmLink}
${nav}
<li><hr style="border:none;border-top:1px solid var(--color-secondary);margin:0.4rem 1rem;" id="navAdminDivider" style="display:none"></li>
${adminItem}
</ul>
</div>
</aside>
<div class="sidebar-footer">
<ul>${footerNav}</ul>
</div>
</div>
`);
// Sidebar und .main in einen zentrierten App-Wrapper verschieben
const appWrapper = document.createElement('div');
appWrapper.className = 'app-wrapper';
const sidebarEl = document.getElementById('sidebar');
const mainEl = document.querySelector('.main');
document.body.insertBefore(appWrapper, sidebarEl);
appWrapper.appendChild(sidebarEl);
if (mainEl) appWrapper.appendChild(mainEl);
// Group toggle
document.querySelectorAll('.sidebar-group-toggle').forEach(toggle => {
toggle.addEventListener('click', e => {
e.preventDefault();
const href = toggle.getAttribute('href');
if (href && href !== '#') {
window.location.href = href;
return;
}
toggle.closest('.sidebar-group').classList.toggle('open');
});
});
// "Aktives Lock" standardmäßig ausblenden; wird nach Session-Check ggf. wieder eingeblendet
const navCAktiv = document.getElementById('navChastityAktiv');
if (navCAktiv) navCAktiv.style.display = 'none';
// Session-Status prüfen
fetch('/login/me')
.then(r => r.ok ? r.json() : null)
.then(async user => {
if (!user) return;
// BDSM Session-Status
try {
const aktivRes = await fetch('/bdsm/einladung/meine-aktive');
if (aktivRes.ok) {
const aktiv = await aktivRes.json();
const el = document.getElementById('navBdsmGame');
if (el) el.href = aktiv.sessionId ? '/games/bdsm/bdsmingame.html' : '/games/bdsm/neubdsm.html';
} else {
const sessionRes = await fetch(`/bdsm?userId=${user.userId}`);
if (sessionRes.status === 200) {
const el = document.getElementById('navBdsmGame');
if (el) el.href = '/games/bdsm/bdsmingame.html';
}
}
} catch (_) {}
// Vanilla Session-Status
try {
const vAktivRes = await fetch('/vanilla/einladung/meine-aktive');
if (vAktivRes.ok) {
const vAktiv = await vAktivRes.json();
const el = document.getElementById('navVanillaGame');
if (el) el.href = vAktiv.sessionId ? '/games/vanilla/vanillaingame.html' : '/games/vanilla/neuvanilla.html';
} else {
const vSessionRes = await fetch(`/vanilla?userId=${user.userId}`);
if (vSessionRes.status === 200) {
const el = document.getElementById('navVanillaGame');
if (el) el.href = '/games/vanilla/vanillaingame.html';
}
}
} catch (_) {}
// Chastity Lock-Status
try {
const lockRes = await fetch('/keyholder/mylock');
if (lockRes.ok) {
const lockData = await lockRes.json();
if (navCAktiv) {
navCAktiv.style.display = '';
navCAktiv.querySelector('a').href = '/games/chastity/activelock.html?lockId=' + lockData.lockId;
}
}
} catch (_) {}
// Dating-Link
const navDating = document.getElementById('navDating');
if (navDating) {
navDating.querySelector('a').href = user.datingAktiv
? '/dating/dating.html'
: '/konto/einstellungen.html#sec-dating';
}
// Admin-Link
if (user.admin) {
const navAdminLink = document.getElementById('navAdminLink');
const navAdminDivider = document.getElementById('navAdminDivider');
if (navAdminLink) navAdminLink.style.display = '';
if (navAdminDivider) navAdminDivider.style.display = '';
}
})
.catch(() => {});
const sidebar = document.getElementById('sidebar');
const burgerBtn = document.getElementById('burgerBtn');
const overlay = document.getElementById('sidebarOverlay');
function openMenu() {
sidebar.classList.add('open');
overlay.classList.add('visible');
burgerBtn.classList.add('open');
burgerBtn.setAttribute('aria-label', 'Menü schließen');
}
function closeMenu() {
sidebar.classList.remove('open');
overlay.classList.remove('visible');
burgerBtn.classList.remove('open');
burgerBtn.setAttribute('aria-label', 'Menü öffnen');
}
burgerBtn.addEventListener('click', () =>
sidebar.classList.contains('open') ? closeMenu() : openMenu()
);
overlay.addEventListener('click', closeMenu);
sidebar.querySelectorAll('a:not(.sidebar-group-toggle)').forEach(l =>
l.addEventListener('click', () => {
if (window.innerWidth <= (parseInt(getComputedStyle(document.documentElement).getPropertyValue('--breakpoint-mobile').trim()) || 768))
closeMenu();
})
);
// Topbar und Social-Sidebar nachladen
function loadScript(src) {
const s = document.createElement('script');
s.src = src;
document.head.appendChild(s);
}
loadScript('/js/topbar.js');
loadScript('/js/social-sidebar.js');
})();