feat(layout): context-switcher for multi-role users
Adds components/shared/ContextSwitcher.vue — a Vuetify menu-button that renders only when useAuthStore.showContextSwitcher is true (i.e. the user has both portal and organizer contexts available). Click calls useAuthStore.setLastContext + resolveLandingRoute and pushes the new route. Wired into both layouts: - PortalLayout.vue: navbar right section, before UserAvatarMenu - DefaultLayoutWithVerticalNav.vue (organizer navbar host): before NavbarThemeSwitcher (OrganizerLayout.vue itself is a 10-line wrapper around DefaultLayoutWithVerticalNav, so the component wires into the actual navbar host). Boundaries matrix update: components-shared now allows `stores` so canonical shared chrome (ContextSwitcher, future global indicators) can read useAuthStore directly without re-homing to components/layout/. stores-portal stays disallowed for components- shared by design — portal-specific state has no place in shared chrome. Adds 3 vitest specs covering: visibility gated by showContextSwitcher, click invokes setLastContext + router.push. Test count 189 → 192. Frontend lint + typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type AppLoadingIndicator from '@/components/AppLoadingIndicator.vue'
|
||||
import ContextSwitcher from '@/components/shared/ContextSwitcher.vue'
|
||||
import UserAvatarMenu from '@/components/portal/UserAvatarMenu.vue'
|
||||
import { useAuthStore } from '@/stores/useAuthStore'
|
||||
import { usePortalStore } from '@/stores/portal/usePortalStore'
|
||||
@@ -138,8 +139,9 @@ async function logout() {
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<!-- Right section: Avatar menu (desktop) -->
|
||||
<!-- Right section: context switcher + avatar menu (desktop) -->
|
||||
<div class="d-none d-md-flex align-center">
|
||||
<ContextSwitcher class="me-2" />
|
||||
<UserAvatarMenu />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import NavSearchBar from '@/layouts/components/NavSearchBar.vue'
|
||||
import NavbarShortcuts from '@/layouts/components/NavbarShortcuts.vue'
|
||||
import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue'
|
||||
import UserProfile from '@/layouts/components/UserProfile.vue'
|
||||
import ContextSwitcher from '@/components/shared/ContextSwitcher.vue'
|
||||
import OrganisationSwitcher from '@/components/layout/OrganisationSwitcher.vue'
|
||||
|
||||
// @layouts plugin
|
||||
@@ -76,6 +77,7 @@ const navItems = computed(() => {
|
||||
|
||||
<NavSearchBar class="flex-grow-1 ms-lg-n3 min-w-0" />
|
||||
|
||||
<ContextSwitcher class="flex-shrink-0 me-2" />
|
||||
<NavbarThemeSwitcher class="flex-shrink-0 me-2" />
|
||||
<NavbarShortcuts class="flex-shrink-0" />
|
||||
<NavBarNotifications class="flex-shrink-0 me-1" />
|
||||
|
||||
Reference in New Issue
Block a user