339 lines
7.1 KiB
Vue
339 lines
7.1 KiB
Vue
<script setup lang="ts">
|
||
import { useAuth } from '../../composables/useAuth'
|
||
import { watch, ref } from 'vue'
|
||
|
||
const props = defineProps<{
|
||
currentTheme: string
|
||
isNatUnlocked: boolean
|
||
t: (key: string) => string
|
||
}>()
|
||
|
||
const emit = defineEmits(['update:theme', 'open:game'])
|
||
|
||
const themes = ['classic', 'dark', 'nat']
|
||
|
||
const { user, login, logout, error } = useAuth()
|
||
const showSettings = ref(false)
|
||
|
||
watch(user, (u) => {
|
||
console.log("👤 Header: User changed:", u ? u.email : "null")
|
||
})
|
||
</script>
|
||
|
||
|
||
<template>
|
||
<header class="fancy-glass header-top">
|
||
<div class="container top-content">
|
||
|
||
<!-- Logo & Status Area -->
|
||
<div class="branding-area">
|
||
<div class="logo-text">HAUMDAUCHER</div>
|
||
<div v-if="user" class="status-message">
|
||
<span class="desktop-msg">{{ isNatUnlocked ? 'Du bist a Haumdaucher 🫵 🍻' : 'Vielleicht... bist du a Haumdaucher' }}</span>
|
||
<span class="mobile-msg">{{ isNatUnlocked ? 'Haumdaucher! 🫵' : 'Vielleicht... 🤔' }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="controls">
|
||
|
||
<!-- Mobile Settings Toggle -->
|
||
<button class="settings-toggle" @click="showSettings = !showSettings">
|
||
⚙️
|
||
</button>
|
||
|
||
<!-- Auth Control (Always Visible) -->
|
||
<div class="auth-control">
|
||
<div v-if="error" class="auth-error" :title="error">⚠️</div>
|
||
<button v-if="!user" @click="login" class="login-btn">
|
||
Login
|
||
</button>
|
||
<div v-else class="user-menu">
|
||
<button @click="logout" class="logout-btn">Exit</button>
|
||
<img :src="user.photoURL || ''" class="avatar" :title="user.displayName || ''" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Theme switch -->
|
||
<div class="control-wrapper" :class="{ 'show-mobile': showSettings }">
|
||
<div class="switch-group">
|
||
<template v-for="th in themes">
|
||
<button
|
||
v-if="th !== 'nat' || isNatUnlocked"
|
||
:key="th"
|
||
:class="{ active: currentTheme === th }"
|
||
@click="emit('update:theme', th)"
|
||
class="theme-btn"
|
||
:title="t('themes.' + th)"
|
||
>
|
||
<span v-if="th === 'classic'">☀️</span>
|
||
<span v-if="th === 'dark'">🌙</span>
|
||
<span v-if="th === 'nat'">🐗</span>
|
||
</button>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Mobile Bottom Nav -->
|
||
<nav class="fancy-glass mobile-nav">
|
||
<a href="#home" class="nav-item">🏠<span>{{ t('nav.home') }}</span></a>
|
||
<a href="#spirit" class="nav-item">✨<span>{{ t('nav.spirit') }}</span></a>
|
||
<button class="nav-item game-btn" @click="emit('open:game')">🕹️<span>{{ t('nav.game') }}</span></button>
|
||
<a href="#impressum" class="nav-item">⚖️<span>Impressum</span></a>
|
||
</nav>
|
||
|
||
<!-- Desktop Side Nav / Links -->
|
||
<nav class="desktop-links">
|
||
<div class="container">
|
||
<a href="#spirit">{{ t('nav.spirit') }}</a>
|
||
<a href="#impressum">Impressum</a>
|
||
<a href="#datenschutz">Datenschutz</a>
|
||
<button class="game-nav-btn" @click="emit('open:game')">{{ t('nav.game') }}</button>
|
||
</div>
|
||
</nav>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.header-top {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 1000;
|
||
padding: 10px 0;
|
||
}
|
||
|
||
.top-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 10px;
|
||
}
|
||
|
||
.logo-text {
|
||
font-weight: 900;
|
||
letter-spacing: 1px;
|
||
font-size: 0.9rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Base Layout */
|
||
.branding-area {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.controls {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
flex: 1;
|
||
}
|
||
|
||
.control-wrapper {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
}
|
||
|
||
.status-message {
|
||
font-size: 0.8rem;
|
||
font-weight: bold;
|
||
margin-left: 15px;
|
||
color: #555;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.mobile-msg { display: none; }
|
||
.settings-toggle { display: none; } /* Hidden on desktop */
|
||
|
||
/* Mobile adjustments */
|
||
@media (max-width: 480px) {
|
||
.branding-area {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.status-message {
|
||
margin-left: 0;
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.desktop-msg { display: none; }
|
||
.mobile-msg { display: inline; }
|
||
|
||
/* Settings Toggle Logic */
|
||
.control-wrapper {
|
||
display: none; /* Hidden by default on mobile */
|
||
position: absolute;
|
||
top: 60px;
|
||
right: 10px;
|
||
background: var(--header-bg);
|
||
padding: 10px;
|
||
border-radius: 12px;
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
border: 1px solid var(--glass-border);
|
||
backdrop-filter: blur(10px);
|
||
}
|
||
|
||
.control-wrapper.show-mobile {
|
||
display: flex;
|
||
}
|
||
|
||
.settings-toggle {
|
||
display: block;
|
||
font-size: 1.2rem;
|
||
padding: 5px;
|
||
margin-left: 5px;
|
||
}
|
||
}
|
||
|
||
.switch-group {
|
||
display: flex;
|
||
background: rgba(0,0,0,0.05);
|
||
padding: 2px;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
button {
|
||
background: none;
|
||
border: none;
|
||
padding: 4px 8px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-weight: bold;
|
||
font-size: 0.7rem;
|
||
color: inherit;
|
||
opacity: 0.5;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
button.active {
|
||
background: var(--primary-color);
|
||
color: #fff;
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Mobile Nav Styles */
|
||
.mobile-nav {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 65px;
|
||
z-index: 1000;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
padding-bottom: var(--safe-area-bottom);
|
||
border-radius: 20px 20px 0 0;
|
||
}
|
||
|
||
.nav-item {
|
||
text-decoration: none;
|
||
color: inherit;
|
||
font-size: 1.2rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 2px;
|
||
background: none;
|
||
border: none;
|
||
}
|
||
|
||
.nav-item span {
|
||
font-size: 0.6rem;
|
||
font-weight: 500;
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.desktop-links {
|
||
display: none;
|
||
}
|
||
|
||
/* Desktop Overrides */
|
||
@media (min-width: 768px) {
|
||
.logo-text { font-size: 1.2rem; }
|
||
.mobile-nav { display: none; }
|
||
.desktop-links {
|
||
display: block;
|
||
position: fixed;
|
||
top: 60px;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 999;
|
||
background: transparent;
|
||
padding: 10px 0;
|
||
text-align: center;
|
||
}
|
||
.desktop-links div {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 30px;
|
||
align-items: center;
|
||
}
|
||
.desktop-links a {
|
||
text-decoration: none;
|
||
color: inherit;
|
||
font-weight: 500;
|
||
opacity: 0.8;
|
||
}
|
||
.desktop-links a:hover { opacity: 1; }
|
||
}
|
||
|
||
.game-nav-btn {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
cursor: pointer;
|
||
font-weight: bold;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.auth-control {
|
||
margin-right: 15px;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.login-btn {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
color: inherit;
|
||
font-weight: bold;
|
||
padding: 6px 12px;
|
||
border-radius: 20px;
|
||
border: 1px solid rgba(255,255,255,0.1);
|
||
}
|
||
|
||
.user-menu {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.avatar {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 50%;
|
||
border: 2px solid var(--primary-color);
|
||
}
|
||
|
||
.logout-btn {
|
||
font-size: 0.7rem;
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.auth-error {
|
||
color: #ff4444;
|
||
margin-right: 8px;
|
||
cursor: help;
|
||
font-size: 1.2rem;
|
||
}
|
||
</style>
|