forked from BRETT/BRETT
136 lines
5.0 KiB
Vue
136 lines
5.0 KiB
Vue
<script setup lang="ts">
|
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
|
import { Button } from '@/components/ui/button'
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from '@/components/ui/dropdown-menu'
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
|
|
|
const { user, can, logout } = useAuth()
|
|
const { uniform, toggle: toggleGridMode } = useGridMode()
|
|
const { open: paletteOpen } = useCommandPalette()
|
|
const route = useRoute()
|
|
|
|
async function onLogoClick(e: MouseEvent) {
|
|
if (route.path !== '/') return
|
|
e.preventDefault()
|
|
await refreshNuxtData()
|
|
}
|
|
|
|
const initials = computed(() => user.value?.name.slice(0, 2).toUpperCase() ?? '')
|
|
|
|
async function onLogout() {
|
|
await logout()
|
|
await navigateTo('/')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<header class="sticky top-0 z-10 flex h-(--header-height) shrink-0 items-center gap-2 border-b bg-background">
|
|
<div class="flex w-full items-center gap-1 px-4 lg:gap-2 lg:px-6">
|
|
<NuxtLink
|
|
to="/"
|
|
class="mr-2 font-logo text-[2.4rem] leading-none tracking-tight transition-colors hover:text-accent"
|
|
@click="onLogoClick"
|
|
>
|
|
BRETT
|
|
</NuxtLink>
|
|
<UploadPopover />
|
|
<Button variant="ghost" as-child>
|
|
<NuxtLink to="/users" class="flex items-center gap-1.5">
|
|
<Icon name="ph:users-fill" class="size-4" />
|
|
Benutzer
|
|
</NuxtLink>
|
|
</Button>
|
|
<Button v-if="can('admin.access')" variant="ghost" as-child>
|
|
<NuxtLink to="/admin" class="flex items-center gap-1.5">
|
|
<Icon name="ph:shield-fill" class="size-4" />
|
|
Admin
|
|
</NuxtLink>
|
|
</Button>
|
|
<button
|
|
type="button"
|
|
class="ml-auto flex h-9 cursor-pointer items-center gap-2 rounded-md border bg-muted/40 px-3 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
|
|
aria-label="Schnellsuche öffnen (Strg+K)"
|
|
@click="paletteOpen = true"
|
|
>
|
|
<Icon name="ph:magnifying-glass-fill" class="size-4" />
|
|
<span class="hidden text-left sm:inline">Suchen…</span>
|
|
<kbd class="hidden rounded-sm border bg-background px-1.5 text-xs sm:inline">Strg K</kbd>
|
|
</button>
|
|
<div class="flex items-center gap-3">
|
|
<Tooltip>
|
|
<TooltipTrigger as-child>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
@click="toggleGridMode"
|
|
>
|
|
<Icon name="ph:grid-nine-fill" v-if="uniform" class="size-5" />
|
|
<Icon name="ph:squares-four-fill" v-else class="size-5" />
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent>{{ uniform ? 'Bento-Layout' : 'Einheitliche Größe' }}</TooltipContent>
|
|
</Tooltip>
|
|
<ThemeSelector />
|
|
<template v-if="user">
|
|
<NotificationBell />
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger class="flex cursor-pointer items-center gap-2 rounded-md px-1 py-0.5 outline-none hover:bg-accent">
|
|
<Avatar class="size-8">
|
|
<AvatarImage v-if="user.avatarUrl" :src="user.avatarUrl" :alt="user.name" />
|
|
<AvatarFallback
|
|
class="text-xs"
|
|
:style="user.color ? { backgroundColor: user.color, color: '#fff' } : undefined"
|
|
>
|
|
{{ initials }}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<span
|
|
class="text-sm font-medium"
|
|
:style="user.color ? { color: user.color } : undefined"
|
|
>{{ user.name }}</span>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" class="w-44">
|
|
<DropdownMenuLabel class="truncate">
|
|
{{ user.name }}
|
|
</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem as-child>
|
|
<NuxtLink :to="`/user/${user.id}`" class="flex items-center gap-2">
|
|
<Icon name="ph:user-fill" class="size-4" />
|
|
Profil
|
|
</NuxtLink>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem as-child>
|
|
<NuxtLink to="/settings" class="flex items-center gap-2">
|
|
<Icon name="ph:gear-fill" class="size-4" />
|
|
Einstellungen
|
|
</NuxtLink>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem variant="destructive" class="flex items-center gap-2" @click="onLogout">
|
|
<Icon name="ph:sign-out-fill" class="size-4" />
|
|
Ausloggen
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</template>
|
|
<template v-else>
|
|
<Button variant="ghost" as-child>
|
|
<NuxtLink to="/login">Login</NuxtLink>
|
|
</Button>
|
|
<Button as-child>
|
|
<NuxtLink to="/register">Registrieren</NuxtLink>
|
|
</Button>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
</template>
|