Refactor UserMenu and navigation components for improved user experience

- Enhanced UserMenu.vue by implementing an extended user type for better user data handling and updated user initials logic.
- Adjusted AppHeader.vue and AreaTabs.vue for improved layout and spacing, ensuring a more cohesive design.
- Updated CartButton.vue and Tabs components for consistent styling and better responsiveness.

These changes aim to enhance the overall usability and visual appeal of the application, providing a smoother user experience.
This commit is contained in:
Bastian Masanek
2025-11-03 18:28:27 +01:00
parent 860cd3ec9d
commit 37a1d234a7
6 changed files with 51 additions and 34 deletions

View File

@@ -10,12 +10,11 @@ const { loggedIn } = useAuth()
<template>
<header class="sticky top-0 z-50 w-full">
<!-- Main header bar -->
<div class="container flex h-24 items-center justify-between px-4 md:px-6 lg:px-8">
<div class="container flex items-end justify-between px-4 md:px-6 lg:px-8 py-6 md:py-7">
<!-- Left: Logo + Role Switcher -->
<div class="flex items-center gap-6 md:gap-8">
<div class="flex items-end gap-6 md:gap-8">
<NuxtLink to="/" class="flex-shrink-0 transition-transform hover:scale-105">
<img src="/img/experimenta-logo-white.svg" alt="experimenta Logo"
class="h-14 w-auto md:h-16 drop-shadow-lg" />
<img src="/img/experimenta-logo-white.svg" alt="experimenta Logo" class="h-16 w-auto md:h-20 lg:h-22" />
</NuxtLink>
<!-- Role Switcher (Desktop only) -->
@@ -25,7 +24,7 @@ const { loggedIn } = useAuth()
</div>
<!-- Right: Cart + User Menu -->
<div class="flex items-center gap-3 md:gap-6">
<div class="flex items-end gap-3 md:gap-6">
<!-- Cart Button (only visible when logged in) -->
<CartButton v-if="loggedIn" />

View File

@@ -24,7 +24,7 @@ const areas: ProductArea[] = [
},
{
id: 'makerspace',
label: 'Makerspace Jahreskarte',
label: 'Makerspace',
icon: Wrench,
enabled: true,
visible: true,
@@ -32,7 +32,7 @@ const areas: ProductArea[] = [
},
{
id: 'educator',
label: 'Pädagogen Jahreskarte',
label: 'Bildung',
icon: GraduationCap,
enabled: false,
visible: true,
@@ -41,7 +41,7 @@ const areas: ProductArea[] = [
},
{
id: 'experimenta',
label: 'experimenta Jahreskarte',
label: 'experimenta',
icon: Sparkles,
enabled: true,
visible: true,
@@ -89,15 +89,21 @@ function navigateToArea(area: ProductArea) {
<div class="w-full">
<!-- Desktop: Tabs -->
<Tabs :model-value="currentArea" class="hidden md:block">
<TabsList class="h-auto p-1.5 bg-white/5">
<TabsList class="h-auto p-2 bg-white/5">
<TabsTrigger v-for="area in areas.filter(area => area.visible)" :key="area.id" :value="area.id"
:disabled="!area.enabled" :class="[
'gap-2 data-[state=active]:bg-accent data-[state=active]:text-white data-[state=active]:shadow-md',
'gap-2 py-3 md:py-4 data-[state=active]:bg-accent data-[state=active]:text-white data-[state=active]:shadow-md',
!area.enabled && 'opacity-50 cursor-not-allowed',
]" @click="navigateToArea(area)">
<component :is="area.icon" class="h-4 w-4" />
<span>{{ area.label }}</span>
<Badge v-if="area.badge" variant="secondary" class="ml-1 text-[10px] px-1.5 py-0">
<Badge v-if="area.badge"
:class="[
'ml-1 text-[10px] px-1.5 py-0.5 transition-colors',
currentArea === area.id
? 'bg-white/90 text-purple-950 border-white/50'
: 'bg-experimenta-accent/20 text-experimenta-accent border-experimenta-accent/30 hover:bg-experimenta-accent/30'
]">
{{ area.badge }}
</Badge>
</TabsTrigger>
@@ -106,9 +112,9 @@ function navigateToArea(area: ProductArea) {
<!-- Mobile: Horizontal scroll with cards (matching desktop styling) -->
<div class="md:hidden overflow-x-auto scrollbar-hide">
<div class="inline-flex h-auto items-center justify-center rounded-[35px] bg-white/5 p-1.5 min-w-max">
<div class="inline-flex h-auto items-center justify-center rounded-[35px] bg-white/5 p-2 min-w-max">
<button v-for="area in areas.filter(area => area.visible)" :key="area.id" :disabled="!area.enabled" :class="[
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[25px] px-4 py-[10px] text-lg font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-0',
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[25px] px-4 py-3 text-lg font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-0',
currentArea === area.id
? 'bg-accent text-white shadow-md'
: 'text-white/70 hover:text-white',
@@ -116,7 +122,13 @@ function navigateToArea(area: ProductArea) {
]" @click="navigateToArea(area)">
<component :is="area.icon" class="h-4 w-4" />
<span>{{ area.label }}</span>
<Badge v-if="area.badge" variant="secondary" class="ml-1 text-[10px] px-1.5 py-0">
<Badge v-if="area.badge"
:class="[
'ml-1 text-[10px] px-1.5 py-0.5 transition-colors',
currentArea === area.id
? 'bg-white/90 text-purple-950 border-white/50'
: 'bg-experimenta-accent/20 text-experimenta-accent border-experimenta-accent/30 hover:bg-experimenta-accent/30'
]">
{{ area.badge }}
</Badge>
</button>

View File

@@ -26,11 +26,11 @@ function handleClick(e: Event) {
<!-- Desktop cart button (visible only on lg and up) -->
<button
@click="handleClick"
class="relative hidden lg:flex items-center gap-5 rounded-[25px] px-[30px] py-[10px] transition-all hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-experimenta-accent focus:ring-offset-2 focus:ring-offset-transparent"
class="relative hidden lg:flex items-center gap-4 rounded-[35px] px-6 py-1.5 transition-all hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-experimenta-accent focus:ring-offset-2 focus:ring-offset-transparent"
aria-label="Warenkorb öffnen"
>
<!-- Cart icon with item count badge -->
<div class="relative inline-flex items-center justify-center">
<div class="relative inline-flex items-center justify-center h-12 w-12">
<ShoppingCart class="h-6 w-6 text-white" strokeWidth="2" />
<!-- Item count badge -->
@@ -44,7 +44,7 @@ function handleClick(e: Event) {
>
<Badge
v-if="hasItems"
class="absolute -top-2.5 -right-3.5 h-5.5 min-w-[22px] px-1.5 flex items-center justify-center bg-experimenta-accent text-white text-xs font-bold border-2 border-purple-darkest shadow-lg"
class="absolute -top-1 -right-1 h-5.5 min-w-[22px] px-1.5 flex items-center justify-center bg-experimenta-accent text-white text-xs font-bold border-2 border-purple-darkest shadow-lg"
>
{{ itemCount > 99 ? '99+' : itemCount }}
</Badge>
@@ -58,7 +58,7 @@ function handleClick(e: Event) {
<!-- Static background -->
<span
class="absolute inset-0 rounded-[25px] bg-white/10"
class="absolute inset-0 rounded-[35px] bg-white/10"
aria-hidden="true"
/>
</button>