Files
harheimertc/components/Footer.vue
Torsten Schulz (local) 5c3d78245f
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 2m10s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped
feat: add Datenschutzerklärung and Konto löschen pages
- Created datenschutz.vue for the privacy policy with sections on data protection, responsible entity, data processing, rights, and contact information.
- Created konto-loeschen.vue for account deletion requests, detailing the process, affected data, and processing time.
- Added anonymize-playstore-screenshot.sh script for image anonymization using ImageMagick.
- Introduced playstore-assets.mjs for generating Play Store assets, including icons and feature graphics, using sharp.
- Added playstore-assets.sh script to execute the asset generation script.
2026-05-29 16:51:36 +02:00

172 lines
5.3 KiB
Vue

<template>
<footer class="fixed bottom-0 left-0 right-0 z-40 bg-gray-900 border-t border-gray-800 shadow-2xl">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-3">
<div class="flex flex-col sm:flex-row justify-between items-center space-y-2 sm:space-y-0">
<p class="text-sm text-gray-400">
© {{ currentYear }} Harheimer TC 1954 e.V.
</p>
<div class="flex items-center space-x-6 text-sm relative">
<span
v-if="isLoggedIn && appVersion"
class="text-xs text-gray-600"
title="Version"
>
v{{ appVersion }}
</span>
<NuxtLink
to="/impressum"
class="text-gray-400 hover:text-primary-400 transition-colors"
>
Impressum
</NuxtLink>
<NuxtLink
to="/datenschutz"
class="text-gray-400 hover:text-primary-400 transition-colors"
>
Datenschutz
</NuxtLink>
<NuxtLink
to="/konto-loeschen"
class="text-gray-400 hover:text-primary-400 transition-colors"
>
Konto loeschen
</NuxtLink>
<NuxtLink
to="/kontakt"
class="text-gray-400 hover:text-primary-400 transition-colors"
>
Kontakt
</NuxtLink>
<!-- Login/Logout -->
<template v-if="isLoggedIn">
<button
class="flex items-center space-x-1 text-gray-400 hover:text-primary-400 transition-colors"
@click="handleLogout"
>
<User :size="16" />
<span>Abmelden</span>
</button>
</template>
<div
v-else
class="relative"
>
<button
class="flex items-center space-x-1 text-gray-400 hover:text-primary-400 transition-colors"
@click="toggleMemberMenu"
>
<User :size="16" />
<span>Mitglieder</span>
<ChevronUp
:size="14"
:class="['transition-transform', isMemberMenuOpen ? 'rotate-0' : 'rotate-180']"
/>
</button>
<!-- Dropdown Menu (appears above) - Only when NOT logged in -->
<Transition
enter-active-class="transition duration-200 ease-out"
enter-from-class="transform translate-y-2 opacity-0"
enter-to-class="transform translate-y-0 opacity-100"
leave-active-class="transition duration-150 ease-in"
leave-from-class="transform translate-y-0 opacity-100"
leave-to-class="transform translate-y-2 opacity-0"
>
<div
v-if="isMemberMenuOpen"
class="absolute bottom-full right-0 mb-2 w-48 bg-gray-800 border border-gray-700 rounded-lg shadow-xl overflow-hidden"
>
<NuxtLink
to="/login"
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
@click="isMemberMenuOpen = false"
>
Anmelden
</NuxtLink>
<NuxtLink
to="/registrieren"
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
@click="isMemberMenuOpen = false"
>
Registrieren
</NuxtLink>
<NuxtLink
to="/passwort-vergessen"
class="block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
@click="isMemberMenuOpen = false"
>
Passwort vergessen
</NuxtLink>
</div>
</Transition>
</div>
</div>
</div>
</div>
</footer>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { User, ChevronUp } from 'lucide-vue-next'
const router = useRouter()
const authStore = useAuthStore()
const currentYear = new Date().getFullYear()
const isMemberMenuOpen = ref(false)
const appVersion = ref('')
// Reactive auth state from store
const isLoggedIn = computed(() => authStore.isLoggedIn)
// const isAdmin = computed(() => authStore.isAdmin)
const loadAppVersion = async () => {
if (!isLoggedIn.value) {
appVersion.value = ''
return
}
try {
const response = await $fetch('/api/app/version')
appVersion.value = response.version || ''
} catch (_error) {
appVersion.value = ''
}
}
const toggleMemberMenu = () => {
isMemberMenuOpen.value = !isMemberMenuOpen.value
}
const handleLogout = async () => {
await authStore.logout()
router.push('/')
}
// Check auth status on mount
onMounted(() => {
authStore.checkAuth()
})
watch(isLoggedIn, () => {
loadAppVersion()
}, { immediate: true })
// Close menu when clicking outside
const handleClickOutside = (event) => {
if (!event.target.closest('.relative')) {
isMemberMenuOpen.value = false
}
}
onMounted(() => {
document.addEventListener('click', handleClickOutside)
})
onUnmounted(() => {
document.removeEventListener('click', handleClickOutside)
})
</script>