@ -56,12 +56,21 @@ const areas: ProductArea[] = [
route : '/experimenta' ,
roleVisibility : 'all' ,
} ,
{
id : 'pedagogical-offers' ,
label : 'Pädagogische Angebote' ,
icon : GraduationCap ,
enabled : true ,
visible : true ,
route : '/experimenta' ,
roleVisibility : [ 'educator' ] ,
} ,
{
id : 'labs' ,
label : 'Labore' ,
icon : FlaskConical ,
enabled : false ,
visible : false ,
visible : tru e,
badge : 'Demnächst' ,
route : '/labs' ,
roleVisibility : [ 'educator' , 'company' ] ,
@ -107,7 +116,7 @@ const currentArea = computed(() => {
/ / T r a c k p r e v i o u s a r e a I D s f o r a n i m a t i o n d e t e c t i o n
const previousAreaIds = ref < string [ ] > ( [ ] )
const newlyAddedAreaId = ref < string | null > ( null )
const newlyAddedAreaIds = ref < string [ ] > ( [ ] )
const tabRefs = ref < Record < string , HTMLElement > > ( { } )
/ / W a t c h f o r c h a n g e s i n v i s i b l e a r e a s t o t r i g g e r a n i m a t i o n s
@ -115,25 +124,40 @@ watch(visibleAreas, (newAreas, oldAreas) => {
const newAreaIds = newAreas . map ( a => a . id )
const oldAreaIds = oldAreas ? . map ( a => a . id ) || [ ]
/ / C h e c k i f c u r r e n t r o u t e i s s t i l l a c c e s s i b l e w i t h n e w v i s i b l e a r e a s
const currentPath = route . path
if ( currentPath !== '/' ) {
const isCurrentRouteStillVisible = newAreas . some ( area =>
area . route !== '/' && currentPath . startsWith ( area . route )
)
if ( ! isCurrentRouteStillVisible ) {
/ / D e l a y n a v i g a t i o n u n t i l f a d e - o u t a n i m a t i o n c o m p l e t e s ( 3 0 0 m s + 5 0 m s b u f f e r )
setTimeout ( ( ) => {
navigateTo ( '/' )
} , 350 )
}
}
/ / F i n d n e w l y a d d e d a r e a s
const addedIds = newAreaIds . filter ( id => ! oldAreaIds . includes ( id ) )
if ( addedIds . length > 0 ) {
/ / M a r k a s n e w l y a d d e d f o r h i g h l i g h t a n i m a t i o n
newlyAddedAreaId . value = addedIds [ 0 ]
/ / M a r k A L L n e w l y a d d e d t a b s f o r h i g h l i g h t a n i m a t i o n
newlyAddedAreaIds . value = addedIds
/ / T r i g g e r c o n f e t t i a f t e r a s m a l l d e l a y ( s o e l e m e n t i s r e n d e r e d )
/ / T r i g g e r c o n f e t t i f o r e a c h n e w t a b w i t h s t a g g e r e d d e l a y ( w a v e e f f e c t )
addedIds . forEach ( ( areaId , index ) => {
setTimeout ( ( ) => {
const areaId = addedIds [ 0 ]
const element = tabRefs . value [ areaId ]
if ( element ) {
triggerConfetti ( element )
}
} , 300 )
} , 300 + ( index * 150 ) ) / / S t a g g e r : 3 0 0 m s , 4 5 0 m s , 6 0 0 m s , . . .
} )
/ / C l e a r h i g h l i g h t a f t e r a n i m a t i o n
/ / C l e a r a l l h i g h l i g h t s a f t e r a n i m a t i o n
setTimeout ( ( ) => {
newlyAddedAreaId . value = null
newlyAddedAreaIds . value = [ ]
} , 2000 )
}
@ -189,7 +213,7 @@ function setTabRef(areaId: string, el: any) {
: value = "area.id" : disabled = "!area.enabled" : class = " [
'gap-2 py-3 md:py-4 data-[state=active]:bg-accent data-[state=active]:text-white data-[state=active]:shadow-md transition-all duration-300' ,
! area . enabled && 'opacity-50 cursor-not-allowed' ,
newlyAddedAreaId === area . id && 'tab-highlight' ,
newlyAddedAreaIds . includes ( area . id ) && 'tab-highlight' ,
] " @click=" navigateToArea ( area ) " >
< component :is ="area.icon" class = "h-4 w-4" / >
< span > { { area . label } } < / span >
@ -217,7 +241,7 @@ function setTabRef(areaId: string, el: any) {
? 'bg-accent text-white shadow-md'
: 'text-white/70 hover:text-white' ,
! area . enabled && 'opacity-50 cursor-not-allowed' ,
newlyAddedAreaId === area . id && 'tab-highlight' ,
newlyAddedAreaIds . includes ( area . id ) && 'tab-highlight' ,
] " @click=" navigateToArea ( area ) " >
< component :is ="area.icon" class = "h-4 w-4" / >
< span > { { area . label } } < / span >