Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 45s
This commit updates the deploy-production.sh script to remove tracked public/data CSV files from the Git index and ensures that backup files are restored correctly, with size verification for integrity. Additionally, it modifies the Navigation.vue component to allow access to the gallery for users with newsletter permissions, enhancing user experience and access control.
1006 lines
42 KiB
Vue
1006 lines
42 KiB
Vue
<template>
|
|
<nav
|
|
class="fixed top-0 left-0 right-0 z-50 bg-gradient-to-r from-gray-900 via-primary-900 to-gray-900 shadow-xl h-20"
|
|
>
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-full">
|
|
<div class="flex flex-col justify-between h-full py-2">
|
|
<!-- Hauptmenü -->
|
|
<div class="flex justify-between items-center">
|
|
<!-- Logo -->
|
|
<NuxtLink
|
|
to="/"
|
|
class="flex items-center space-x-3 hover:scale-105 transition-transform"
|
|
>
|
|
<img
|
|
src="~/assets/images/logos/Harheimer TC.svg"
|
|
alt="Harheimer TC Logo"
|
|
class="w-12 h-12"
|
|
>
|
|
<div class="hidden sm:block">
|
|
<span class="text-xl font-display font-bold text-white">Harheimer <span
|
|
class="text-primary-400"
|
|
>TC</span></span>
|
|
</div>
|
|
</NuxtLink>
|
|
|
|
<div style="display:flex;flex-direction:column;">
|
|
<!-- Desktop Navigation -->
|
|
<div class="hidden lg:flex items-center space-x-1">
|
|
<NuxtLink
|
|
to="/"
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Start
|
|
</NuxtLink>
|
|
|
|
<button
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
:class="(route.path.startsWith('/verein/') || route.path.startsWith('/vorstand') || route.path.startsWith('/vereinsmeisterschaften') || currentSubmenu === 'verein') ? 'text-white bg-primary-600' : ''"
|
|
@click="toggleSubmenu('verein')"
|
|
>
|
|
Verein
|
|
</button>
|
|
|
|
<button
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
:class="(route.path.startsWith('/mannschaften') || route.path.startsWith('/spielsysteme') || currentSubmenu === 'mannschaften') ? 'text-white bg-primary-600' : ''"
|
|
@click="toggleSubmenu('mannschaften')"
|
|
>
|
|
Mannschaften
|
|
</button>
|
|
|
|
<button
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
:class="(route.path.startsWith('/training') || route.path.startsWith('/tt-regeln') || currentSubmenu === 'training') ? 'text-white bg-primary-600' : ''"
|
|
@click="toggleSubmenu('training')"
|
|
>
|
|
Training
|
|
</button>
|
|
|
|
<NuxtLink
|
|
to="/mitgliedschaft"
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Mitgliedschaft
|
|
</NuxtLink>
|
|
|
|
<NuxtLink
|
|
to="/termine"
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
active-class="text-white bg-primary-600"
|
|
@click="currentSubmenu = null"
|
|
>
|
|
Termine
|
|
</NuxtLink>
|
|
|
|
<NuxtLink
|
|
v-if="hasGalleryImages || canAccessNewsletter"
|
|
to="/verein/galerie"
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
active-class="text-white bg-primary-600"
|
|
@click="currentSubmenu = null"
|
|
>
|
|
Galerie
|
|
</NuxtLink>
|
|
|
|
<button
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
:class="(route.path.startsWith('/newsletter') || currentSubmenu === 'newsletter') ? 'text-white bg-primary-600' : ''"
|
|
@click="toggleSubmenu('newsletter')"
|
|
>
|
|
Newsletter
|
|
</button>
|
|
|
|
<button
|
|
v-if="isLoggedIn"
|
|
class="px-4 py-2 text-gray-300 hover:text-white font-medium transition-all rounded-lg hover:bg-primary-700/50"
|
|
:class="(route.path.startsWith('/mitgliederbereich') || route.path.startsWith('/cms') || currentSubmenu === 'intern') ? 'text-white bg-primary-600' : ''"
|
|
@click="toggleSubmenu('intern')"
|
|
>
|
|
Intern
|
|
</button>
|
|
|
|
<NuxtLink
|
|
to="/kontakt"
|
|
class="px-4 py-2 bg-primary-600 hover:bg-primary-700 text-white font-semibold transition-all rounded-lg shadow-lg"
|
|
@click="currentSubmenu = null"
|
|
>
|
|
Kontakt
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<div class="hidden lg:flex items-center h-6 border-t border-primary-700/20">
|
|
<div
|
|
v-if="currentSubmenu"
|
|
class="flex items-center space-x-1"
|
|
>
|
|
<!-- Newsletter Submenu -->
|
|
<template v-if="currentSubmenu === 'newsletter'">
|
|
<NuxtLink
|
|
to="/newsletter/subscribe"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Abonnieren
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/newsletter/unsubscribe"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Abmelden
|
|
</NuxtLink>
|
|
</template>
|
|
<!-- Verein Submenu -->
|
|
<template v-if="currentSubmenu === 'verein'">
|
|
<NuxtLink
|
|
to="/verein/ueber-uns"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Über uns
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/vorstand"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Vorstand
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/verein/geschichte"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Geschichte
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/verein/satzung"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Satzung
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/vereinsmeisterschaften"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Vereinsmeisterschaften
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/verein/galerie"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Galerie
|
|
</NuxtLink>
|
|
</template>
|
|
|
|
<!-- Mannschaften Submenu -->
|
|
<template v-if="currentSubmenu === 'mannschaften'">
|
|
<NuxtLink
|
|
to="/mannschaften"
|
|
class="px-2.5 py-1 text-xs font-semibold text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="bg-primary-600"
|
|
>
|
|
Übersicht
|
|
</NuxtLink>
|
|
<div class="h-3 w-px bg-primary-700" />
|
|
<template
|
|
v-for="mannschaft in mannschaften"
|
|
:key="mannschaft.slug"
|
|
>
|
|
<NuxtLink
|
|
:to="`/mannschaften/${mannschaft.slug}`"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
{{ mannschaft.mannschaft }}
|
|
</NuxtLink>
|
|
</template>
|
|
<div class="h-3 w-px bg-primary-700" />
|
|
<NuxtLink
|
|
to="/mannschaften/spielplaene"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Spielpläne
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/spielsysteme"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Spielsysteme
|
|
</NuxtLink>
|
|
</template>
|
|
|
|
<!-- Training Submenu -->
|
|
<template v-if="currentSubmenu === 'training'">
|
|
<NuxtLink
|
|
to="/training"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Trainingszeiten
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/training/trainer"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Trainer
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/training/anfaenger"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Anfänger
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/tt-regeln"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
TT-Regeln
|
|
</NuxtLink>
|
|
</template>
|
|
|
|
<!-- Intern Submenu -->
|
|
<template v-if="currentSubmenu === 'intern'">
|
|
<NuxtLink
|
|
to="/mitgliederbereich"
|
|
class="px-2.5 py-1 text-xs font-semibold text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="bg-primary-600"
|
|
>
|
|
Übersicht
|
|
</NuxtLink>
|
|
<div class="h-3 w-px bg-primary-700" />
|
|
<NuxtLink
|
|
to="/mitgliederbereich/mitglieder"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Mitgliederliste
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/news"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
News
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/profil"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Mein Profil
|
|
</NuxtLink>
|
|
<div class="h-3 w-px bg-primary-700" />
|
|
<NuxtLink
|
|
to="/mitgliederbereich/api"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
API-Dokumentation
|
|
</NuxtLink>
|
|
<template v-if="canAccessNewsletter">
|
|
<div class="h-3 w-px bg-primary-700" />
|
|
<NuxtLink
|
|
to="/cms/newsletter"
|
|
class="px-2.5 py-1 text-xs text-gray-300 hover:text-white hover:bg-primary-700/50 rounded transition-all"
|
|
active-class="text-white bg-primary-600"
|
|
>
|
|
Newsletter
|
|
</NuxtLink>
|
|
</template>
|
|
<template v-if="isAdmin">
|
|
<div class="h-3 w-px bg-primary-700" />
|
|
<div class="relative inline-block">
|
|
<button
|
|
class="px-2.5 py-1 text-xs text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded transition-all flex items-center"
|
|
:class="route.path.startsWith('/cms') ? 'text-white bg-primary-600' : ''"
|
|
@click.stop="toggleCmsDropdown"
|
|
>
|
|
CMS
|
|
<ChevronDown
|
|
:size="12"
|
|
class="ml-1"
|
|
:class="['transition-transform', showCmsDropdown ? 'rotate-180' : '']"
|
|
/>
|
|
</button>
|
|
|
|
<!-- CMS Dropdown -->
|
|
<div
|
|
v-if="showCmsDropdown"
|
|
class="absolute left-0 top-full mt-1 w-48 bg-gray-800 border border-gray-700 rounded-lg shadow-xl overflow-hidden z-50"
|
|
>
|
|
<NuxtLink
|
|
to="/cms"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Übersicht
|
|
</NuxtLink>
|
|
<div class="border-t border-gray-700 my-1" />
|
|
<NuxtLink
|
|
to="/cms/ueber-uns"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Über uns
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/geschichte"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Geschichte
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/tt-regeln"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
TT-Regeln
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/satzung"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Satzung
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/vereinsmeisterschaften"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Vereinsmeisterschaften
|
|
</NuxtLink>
|
|
<div class="border-t border-gray-700 my-1" />
|
|
<NuxtLink
|
|
to="/mitgliederbereich/news"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
News
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/termine"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Termine
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/spielplaene"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Spielpläne
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/mitglieder"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Mitglieder
|
|
</NuxtLink>
|
|
<div class="border-t border-gray-700 my-1" />
|
|
<NuxtLink
|
|
to="/cms/einstellungen"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Einstellungen
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/mitgliedschaftsantraege"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Mitgliedschaftsanträge
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/benutzer"
|
|
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
|
@click="showCmsDropdown = false"
|
|
>
|
|
Benutzerverwaltung
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Menu Button -->
|
|
<button
|
|
class="lg:hidden p-2 rounded-lg hover:bg-primary-700/50 transition-colors"
|
|
aria-label="Toggle menu"
|
|
@click="isMobileMenuOpen = !isMobileMenuOpen"
|
|
>
|
|
<X
|
|
v-if="isMobileMenuOpen"
|
|
:size="24"
|
|
class="text-white"
|
|
/>
|
|
<Menu
|
|
v-else
|
|
:size="24"
|
|
class="text-white"
|
|
/>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Untermenü (Desktop) - im gleichen Block, immer gleiche Höhe -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Menu -->
|
|
<Transition
|
|
enter-active-class="transition duration-200 ease-out"
|
|
enter-from-class="opacity-0 transform -translate-y-2"
|
|
enter-to-class="opacity-100 transform translate-y-0"
|
|
leave-active-class="transition duration-150 ease-in"
|
|
leave-from-class="opacity-100 transform translate-y-0"
|
|
leave-to-class="opacity-0 transform -translate-y-2"
|
|
>
|
|
<div
|
|
v-if="isMobileMenuOpen"
|
|
class="lg:hidden bg-gray-800 border-t border-primary-700/30 max-h-[80vh] overflow-y-auto"
|
|
>
|
|
<div class="px-4 py-4 space-y-2">
|
|
<NuxtLink
|
|
to="/"
|
|
class="block px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Start
|
|
</NuxtLink>
|
|
|
|
<!-- Verein Mobile -->
|
|
<div>
|
|
<button
|
|
class="w-full flex items-center justify-between px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="toggleMobileSubmenu('verein')"
|
|
>
|
|
Verein
|
|
<ChevronDown
|
|
:size="16"
|
|
:class="['transition-transform', mobileSubmenu === 'verein' ? 'rotate-180' : '']"
|
|
/>
|
|
</button>
|
|
<div
|
|
v-if="mobileSubmenu === 'verein'"
|
|
class="pl-4 space-y-1 mt-1 bg-primary-900/30 rounded-lg p-2"
|
|
>
|
|
<NuxtLink
|
|
to="/verein/ueber-uns"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Über uns
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/vorstand"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Vorstand
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/verein/geschichte"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Geschichte
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/verein/satzung"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Satzung
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/vereinsmeisterschaften"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Vereinsmeisterschaften
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/verein/galerie"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Galerie
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/newsletter/subscribe"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Newsletter abonnieren
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/newsletter/unsubscribe"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Newsletter abmelden
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mannschaften Mobile -->
|
|
<div>
|
|
<button
|
|
class="w-full flex items-center justify-between px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="toggleMobileSubmenu('mannschaften')"
|
|
>
|
|
Mannschaften
|
|
<ChevronDown
|
|
:size="16"
|
|
:class="['transition-transform', mobileSubmenu === 'mannschaften' ? 'rotate-180' : '']"
|
|
/>
|
|
</button>
|
|
<div
|
|
v-if="mobileSubmenu === 'mannschaften'"
|
|
class="pl-4 space-y-1 mt-1 bg-primary-900/30 rounded-lg p-2"
|
|
>
|
|
<NuxtLink
|
|
to="/mannschaften"
|
|
class="block px-4 py-2 text-sm font-semibold text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Übersicht
|
|
</NuxtLink>
|
|
<template
|
|
v-for="mannschaft in mannschaften"
|
|
:key="mannschaft.slug"
|
|
>
|
|
<NuxtLink
|
|
:to="`/mannschaften/${mannschaft.slug}`"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
{{ mannschaft.mannschaft }}
|
|
</NuxtLink>
|
|
</template>
|
|
<div class="border-t border-primary-700/20 my-2" />
|
|
<NuxtLink
|
|
to="/mannschaften/spielplaene"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Spielpläne
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/spielsysteme"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Spielsysteme
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Training Mobile -->
|
|
<div>
|
|
<button
|
|
class="w-full flex items-center justify-between px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="toggleMobileSubmenu('training')"
|
|
>
|
|
Training
|
|
<ChevronDown
|
|
:size="16"
|
|
:class="['transition-transform', mobileSubmenu === 'training' ? 'rotate-180' : '']"
|
|
/>
|
|
</button>
|
|
<div
|
|
v-if="mobileSubmenu === 'training'"
|
|
class="pl-4 space-y-1 mt-1 bg-primary-900/30 rounded-lg p-2"
|
|
>
|
|
<NuxtLink
|
|
to="/training"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Trainingszeiten
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/training/trainer"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Trainer
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/training/anfaenger"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Anfänger
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/tt-regeln"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
TT-Regeln
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
|
|
<NuxtLink
|
|
to="/mitgliedschaft"
|
|
class="block px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Mitgliedschaft
|
|
</NuxtLink>
|
|
|
|
<NuxtLink
|
|
to="/termine"
|
|
class="block px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Termine
|
|
</NuxtLink>
|
|
|
|
<NuxtLink
|
|
v-if="hasGalleryImages || canAccessNewsletter"
|
|
to="/verein/galerie"
|
|
class="block px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Galerie
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/newsletter/subscribe"
|
|
class="block px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Newsletter abonnieren
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/newsletter/unsubscribe"
|
|
class="block px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Newsletter abmelden
|
|
</NuxtLink>
|
|
|
|
<!-- Intern Mobile -->
|
|
<div v-if="isLoggedIn">
|
|
<button
|
|
class="w-full flex items-center justify-between px-4 py-3 text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg font-medium transition-colors"
|
|
@click="toggleMobileSubmenu('intern')"
|
|
>
|
|
Intern
|
|
<ChevronDown
|
|
:size="16"
|
|
:class="['transition-transform', mobileSubmenu === 'intern' ? 'rotate-180' : '']"
|
|
/>
|
|
</button>
|
|
<div
|
|
v-if="mobileSubmenu === 'intern'"
|
|
class="pl-4 space-y-1 mt-1 bg-primary-900/30 rounded-lg p-2"
|
|
>
|
|
<NuxtLink
|
|
to="/mitgliederbereich"
|
|
class="block px-4 py-2 text-sm font-semibold text-gray-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Übersicht
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/mitglieder"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Mitgliederliste
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/news"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
News
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/profil"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Mein Profil
|
|
</NuxtLink>
|
|
<template v-if="canAccessNewsletter">
|
|
<div class="border-t border-primary-700/20 my-2" />
|
|
<NuxtLink
|
|
to="/cms/newsletter"
|
|
class="block px-4 py-2 text-sm text-gray-400 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Newsletter
|
|
</NuxtLink>
|
|
</template>
|
|
<template v-if="isAdmin">
|
|
<div class="border-t border-primary-700/20 my-2" />
|
|
<NuxtLink
|
|
to="/cms"
|
|
class="block px-4 py-2 text-sm font-semibold text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
CMS Übersicht
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/news"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
News
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/termine"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Termine
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/spielplaene"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Spielpläne
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/mitgliederbereich/mitglieder"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Mitglieder
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/ueber-uns"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Über uns
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/geschichte"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Geschichte
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/tt-regeln"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
TT-Regeln
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/satzung"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Satzung
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/vereinsmeisterschaften"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Vereinsmeisterschaften
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/einstellungen"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Einstellungen
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/mitgliedschaftsantraege"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Mitgliedschaftsanträge
|
|
</NuxtLink>
|
|
<NuxtLink
|
|
to="/cms/benutzer"
|
|
class="block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Benutzerverwaltung
|
|
</NuxtLink>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<NuxtLink
|
|
to="/kontakt"
|
|
class="block px-4 py-3 bg-primary-600 hover:bg-primary-700 text-white rounded-lg font-semibold transition-colors"
|
|
@click="isMobileMenuOpen = false"
|
|
>
|
|
Kontakt
|
|
</NuxtLink>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</nav>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
import { Menu, X, ChevronDown } from 'lucide-vue-next'
|
|
|
|
const route = useRoute()
|
|
const isMobileMenuOpen = ref(false)
|
|
const mobileSubmenu = ref(null)
|
|
const mannschaften = ref([])
|
|
const hasGalleryImages = ref(false)
|
|
const showCmsDropdown = ref(false)
|
|
|
|
// Lazy store access to avoid Pinia initialization issues
|
|
const getAuthStore = () => {
|
|
try {
|
|
return useAuthStore()
|
|
} catch (e) {
|
|
// Fallback if Pinia is not yet initialized
|
|
return null
|
|
}
|
|
}
|
|
|
|
// Reactive auth state from store (lazy)
|
|
const isLoggedIn = computed(() => {
|
|
const store = getAuthStore()
|
|
return store?.isLoggedIn ?? false
|
|
})
|
|
const isAdmin = computed(() => {
|
|
const store = getAuthStore()
|
|
return store?.isAdmin ?? false
|
|
})
|
|
const canAccessNewsletter = computed(() => {
|
|
const store = getAuthStore()
|
|
return store?.hasAnyRole('admin', 'vorstand', 'newsletter') ?? false
|
|
})
|
|
|
|
// Automatisches Setzen des Submenus basierend auf der Route
|
|
const currentSubmenu = computed(() => {
|
|
const path = route.path
|
|
if (path.startsWith('/verein/') || path.startsWith('/vorstand') ||
|
|
path.startsWith('/vereinsmeisterschaften')) {
|
|
return 'verein'
|
|
}
|
|
if (path.startsWith('/mannschaften') || path.startsWith('/spielsysteme')) {
|
|
return 'mannschaften'
|
|
}
|
|
if (path.startsWith('/training') || path.startsWith('/tt-regeln')) {
|
|
return 'training'
|
|
}
|
|
if (path.startsWith('/mitgliederbereich') || path.startsWith('/cms')) {
|
|
return 'intern'
|
|
}
|
|
if (path.startsWith('/newsletter')) {
|
|
return 'newsletter'
|
|
}
|
|
return null
|
|
})
|
|
|
|
const toggleMobileSubmenu = (menu) => {
|
|
mobileSubmenu.value = mobileSubmenu.value === menu ? null : menu
|
|
}
|
|
|
|
const loadMannschaften = async () => {
|
|
try {
|
|
const response = await fetch('/data/mannschaften.csv')
|
|
if (!response.ok) return
|
|
|
|
const csv = await response.text()
|
|
const lines = csv.split('\n').filter(line => line.trim() !== '')
|
|
|
|
if (lines.length < 2) return
|
|
|
|
mannschaften.value = lines.slice(1).map(line => {
|
|
// Besserer CSV-Parser: Respektiert Anführungszeichen
|
|
const values = []
|
|
let current = ''
|
|
let inQuotes = false
|
|
|
|
for (let i = 0; i < line.length; i++) {
|
|
const char = line[i]
|
|
|
|
if (char === '"') {
|
|
inQuotes = !inQuotes
|
|
} else if (char === ',' && !inQuotes) {
|
|
values.push(current.trim())
|
|
current = ''
|
|
} else {
|
|
current += char
|
|
}
|
|
}
|
|
values.push(current.trim())
|
|
|
|
if (!values[0]) return null
|
|
|
|
return {
|
|
mannschaft: values[0].trim(),
|
|
slug: values[0].trim().toLowerCase().replace(/\s+/g, '-')
|
|
}
|
|
}).filter(mannschaft => mannschaft !== null)
|
|
} catch (error) {
|
|
console.error('Fehler beim Laden der Mannschaften:', error)
|
|
}
|
|
}
|
|
|
|
const checkGalleryImages = async () => {
|
|
try {
|
|
const response = await $fetch('/api/galerie')
|
|
hasGalleryImages.value = response && response.length > 0
|
|
} catch (error) {
|
|
console.error('Fehler beim Prüfen der Galerie-Bilder:', error)
|
|
hasGalleryImages.value = false
|
|
}
|
|
}
|
|
|
|
const toggleCmsDropdown = () => {
|
|
showCmsDropdown.value = !showCmsDropdown.value
|
|
}
|
|
|
|
const handleDocumentClick = (e) => {
|
|
if (!e.target.closest('.relative.inline-block')) {
|
|
showCmsDropdown.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadMannschaften()
|
|
checkGalleryImages()
|
|
const store = getAuthStore()
|
|
if (store) {
|
|
store.checkAuth()
|
|
}
|
|
|
|
// Close CMS dropdown when clicking outside
|
|
document.addEventListener('click', handleDocumentClick)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
document.removeEventListener('click', handleDocumentClick)
|
|
})
|
|
|
|
const toggleSubmenu = (menu) => {
|
|
// Wenn wir schon im richtigen Bereich sind, nichts tun (Submenu bleibt offen)
|
|
// Wenn nicht, zur Hauptseite navigieren
|
|
const path = route.path
|
|
|
|
if (menu === 'newsletter' && !path.startsWith('/newsletter')) {
|
|
navigateTo('/newsletter/subscribe')
|
|
} else if (menu === 'verein' && !path.startsWith('/verein/') && !path.startsWith('/vorstand') && !path.startsWith('/vereinsmeisterschaften')) {
|
|
navigateTo('/verein/ueber-uns')
|
|
} else if (menu === 'mannschaften' && !path.startsWith('/mannschaften') && !path.startsWith('/spielsysteme')) {
|
|
navigateTo('/mannschaften')
|
|
} else if (menu === 'training' && !path.startsWith('/training') && !path.startsWith('/tt-regeln')) {
|
|
navigateTo('/training')
|
|
} else if (menu === 'intern' && !path.startsWith('/mitgliederbereich') && !path.startsWith('/cms')) {
|
|
navigateTo('/mitgliederbereich')
|
|
}
|
|
}
|
|
</script>
|