Files
my2/app/components/navigation/AreaTabs.vue
Bastian Masanek 4a3ef037ab Update AreaTabs and experimenta page for educator annual pass visibility
- Disabled the educator tab in AreaTabs and added a 'Demnächst' badge for future visibility.
- Updated the experimenta page header to singular form for consistency and improved layout of ProductCard components for better readability.

These changes enhance the user experience by clarifying product availability and improving the overall presentation of the educator annual pass.
2025-11-03 14:17:58 +01:00

128 lines
3.7 KiB
Vue

<script setup lang="ts">
import { Wrench, FlaskConical, Ticket, Sparkles, GraduationCap } from 'lucide-vue-next'
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Badge } from '@/components/ui/badge'
interface ProductArea {
id: string
label: string
icon: any
enabled: boolean
visible: boolean
badge?: string
route: string
}
const areas: ProductArea[] = [
{
id: 'makerspace',
label: 'Makerspace Jahreskarte',
icon: Wrench,
enabled: true,
visible: true,
route: '/products',
},
{
id: 'educator',
label: 'Pädagogen Jahreskarte',
icon: GraduationCap,
enabled: false,
visible: true,
badge: 'Demnächst',
route: '/educator',
},
{
id: 'experimenta',
label: 'experimenta Jahreskarte',
icon: Sparkles,
enabled: true,
visible: true,
badge: 'Demnächst',
route: '/experimenta',
},
{
id: 'labs',
label: 'Labore',
icon: FlaskConical,
enabled: false,
visible: false,
badge: 'Demnächst',
route: '/labs',
},
]
const route = useRoute()
const currentArea = computed(() => {
// Determine current area based on route
if (route.path.startsWith('/products') || route.path === '/') {
return 'makerspace'
} else if (route.path.startsWith('/educator')) {
return 'educator'
} else if (route.path.startsWith('/labs')) {
return 'labs'
} else if (route.path.startsWith('/experimenta')) {
return 'experimenta'
}
return 'makerspace'
})
function navigateToArea(area: ProductArea) {
if (area.enabled) {
navigateTo(area.route)
}
}
</script>
<template>
<div class="w-full">
<!-- Desktop: Tabs -->
<Tabs :model-value="currentArea" class="hidden md:block">
<TabsList class="h-auto p-1.5 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',
!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">
{{ area.badge }}
</Badge>
</TabsTrigger>
</TabsList>
</Tabs>
<!-- 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">
<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',
currentArea === area.id
? 'bg-accent text-white shadow-md'
: 'text-white/70 hover:text-white',
!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">
{{ area.badge }}
</Badge>
</button>
</div>
</div>
</div>
</template>
<style scoped>
/* Hide scrollbar but keep functionality */
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>