haumdaucher_de/src/components/layout/Header.vue

352 lines
7.6 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
const props = defineProps<{
currentTheme: string
currentLang: string
isNatUnlocked: boolean
t: (key: string) => string
}>()
const emit = defineEmits(['update:theme', 'update:lang', 'open:game'])
const themes = ['classic', 'unicorn', 'luxury', 'win95', 'nat']
import { useAuth } from '../../composables/useAuth'
import { watch, ref } from 'vue'
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 || isAllowed ? 'Du bist a Haumdaucher 🫵 🍻' : 'Vielleicht... bist du a Haumdaucher' }}</span>
<span class="mobile-msg">{{ isNatUnlocked || isAllowed ? '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>
<!-- Combined switch for better mobile spacing -->
<div class="control-wrapper" :class="{ 'show-mobile': showSettings }">
<div class="switch-group">
<button
v-for="l in ['de', 'bar']"
:key="l"
:class="{ active: currentLang === l }"
@click="emit('update:lang', l)"
>
{{ l.toUpperCase() }}
</button>
</div>
<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="th"
>
<span v-if="th === 'classic'">⚫</span>
<span v-if="th === 'unicorn'">🦄</span>
<span v-if="th === 'luxury'">👑</span>
<span v-if="th === 'win95'">💾</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;
flex-wrap: wrap;
justify-content: flex-end;
}
.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: rgba(255, 255, 255, 0.95);
padding: 10px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
flex-direction: column;
align-items: flex-end;
}
.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: white;
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>