You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.8 KiB
118 lines
3.8 KiB
<script setup lang="ts">
|
|
import { User, LogOut, Package } from 'lucide-vue-next'
|
|
import {
|
|
Avatar,
|
|
AvatarFallback,
|
|
AvatarImage,
|
|
} from './ui/avatar'
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from './ui/dropdown-menu'
|
|
|
|
const { user, loggedIn, logout } = useAuth()
|
|
|
|
/**
|
|
* Get user initials for Avatar fallback
|
|
* Example: "Bastian Masanek" → "BM"
|
|
*/
|
|
const userInitials = computed(() => {
|
|
if (!user.value) return '?'
|
|
|
|
const first = user.value.firstName?.charAt(0)?.toUpperCase() || ''
|
|
const last = user.value.lastName?.charAt(0)?.toUpperCase() || ''
|
|
|
|
return first + last || user.value.email?.charAt(0)?.toUpperCase() || '?'
|
|
})
|
|
|
|
/**
|
|
* Handle logout click
|
|
*/
|
|
async function handleLogout() {
|
|
try {
|
|
await logout()
|
|
} catch (error) {
|
|
console.error('Logout error:', error)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<!-- Not logged in: Show login prompt -->
|
|
<NuxtLink
|
|
v-if="!loggedIn"
|
|
to="/auth"
|
|
class="flex items-center gap-2 px-4 py-2 rounded-2xl border-2 border-dashed border-muted-foreground/30 hover:border-experimenta-accent hover:bg-experimenta-accent/10 transition-all"
|
|
aria-label="Anmelden oder Registrieren"
|
|
>
|
|
<Avatar class="h-10 w-10 border-2 border-muted-foreground/30 rounded-2xl">
|
|
<AvatarFallback class="bg-muted text-muted-foreground rounded-2xl">
|
|
<User class="h-5 w-5" />
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<span class="text-sm font-medium hidden sm:inline">Anmelden</span>
|
|
</NuxtLink>
|
|
|
|
<!-- Logged in: Show user menu -->
|
|
<DropdownMenu v-else>
|
|
<DropdownMenuTrigger as-child>
|
|
<button
|
|
class="flex items-center gap-3 rounded-2xl px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-experimenta-accent focus:ring-offset-2 transition-all hover:bg-white/10"
|
|
aria-label="Benutzermenü öffnen"
|
|
>
|
|
<!-- Greeting text (Desktop only) -->
|
|
<span class="hidden md:inline text-sm font-medium text-white">
|
|
Hallo, {{ user?.firstName }}
|
|
</span>
|
|
|
|
<!-- Avatar with status ring (logged in indicator) -->
|
|
<Avatar class="h-10 w-10 md:h-12 md:w-12 border-3 border-experimenta-purple shadow-lg bg-experimenta-accent ring-2 ring-experimenta-accent ring-offset-2 ring-offset-white dark:ring-offset-zinc-950">
|
|
<AvatarImage :src="undefined" :alt="user?.firstName" />
|
|
<AvatarFallback class="bg-experimenta-accent text-white font-bold text-sm md:text-base flex items-center justify-center w-full h-full">
|
|
{{ userInitials }}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
</button>
|
|
</DropdownMenuTrigger>
|
|
|
|
<DropdownMenuContent align="end" class="w-64 z-[200]">
|
|
<!-- User info header -->
|
|
<DropdownMenuLabel class="font-normal py-3">
|
|
<div class="flex flex-col space-y-1.5">
|
|
<p class="text-base font-semibold leading-none">
|
|
{{ user?.firstName }} {{ user?.lastName }}
|
|
</p>
|
|
<p class="text-sm leading-none text-muted-foreground">
|
|
{{ user?.email }}
|
|
</p>
|
|
</div>
|
|
</DropdownMenuLabel>
|
|
|
|
<DropdownMenuSeparator />
|
|
|
|
<!-- My Orders (Phase 5+ feature) -->
|
|
<DropdownMenuItem disabled class="py-2.5">
|
|
<Package class="mr-3 h-5 w-5" />
|
|
<span class="text-sm">Meine Bestellungen</span>
|
|
</DropdownMenuItem>
|
|
|
|
<!-- Profile (disabled for now, placeholder for Phase 2+) -->
|
|
<DropdownMenuItem disabled class="py-2.5">
|
|
<User class="mr-3 h-5 w-5" />
|
|
<span class="text-sm">Profil bearbeiten</span>
|
|
</DropdownMenuItem>
|
|
|
|
<DropdownMenuSeparator />
|
|
|
|
<!-- Logout -->
|
|
<DropdownMenuItem @click="handleLogout" class="py-2.5">
|
|
<LogOut class="mr-3 h-5 w-5" />
|
|
<span class="text-sm">Abmelden</span>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</template>
|
|
|