Extrahiere Sidebar-Routen-Logik in Composable und entferne toten Counter-Store

Layout.vue trug die Sidebar-Filterlogik (Visibility/Rolle/Pfadabgleich)
inline. Sie liegt jetzt in composables/useSidebarRoutes.ts; Layout.vue
verliert ~85 Zeilen Skript ohne Verhaltensänderung. Der ungenutzte
stores/counter.ts (Vite-Boilerplate) wird entfernt.
This commit is contained in:
Claude
2026-04-28 10:22:32 +00:00
parent 6740038e9a
commit 2c882fce4a
3 changed files with 101 additions and 99 deletions
+3 -87
View File
@@ -5,12 +5,11 @@ import { useDisplay, useTheme } from 'vuetify'
import { useRoute, useRouter } from 'vue-router'
import iconImage from '@/assets/images/icon.svg'
import { Visibility, routes } from '@/plugins/routesLayout'
import { useSidebarRoutes } from '@/composables/useSidebarRoutes'
import { routes } from '@/plugins/routesLayout'
import {
AuthRequestError,
ROLE_ADMIN,
fetchCurrentUser,
hasRole,
logout,
type CurrentUser,
} from '@/services/authSession'
@@ -28,90 +27,7 @@ const isLoggingOut = ref(false)
const appBannersStore = useAppBannersStore()
const { banners } = storeToRefs(appBannersStore)
function normalizeRoutePath(path: string) {
if (!path || path === '/') {
return '/'
}
return path.endsWith('/') ? path.slice(0, -1) : path
}
function isWithinRoutePath(currentPath: string, targetPath: string) {
const normalizedCurrentPath = normalizeRoutePath(currentPath)
const normalizedTargetPath = normalizeRoutePath(targetPath)
if (normalizedTargetPath === '/') {
return normalizedCurrentPath === '/'
}
return (
normalizedCurrentPath === normalizedTargetPath ||
normalizedCurrentPath.startsWith(`${normalizedTargetPath}/`)
)
}
function resolveVisibilityRoutes(path: string, visibilityRoute?: string | string[]) {
if (Array.isArray(visibilityRoute)) {
return visibilityRoute.map((entry) => entry.trim()).filter((entry) => entry.length > 0)
}
const normalizedVisibilityRoute = visibilityRoute?.trim()
if (normalizedVisibilityRoute && normalizedVisibilityRoute.length > 0) {
return [normalizedVisibilityRoute]
}
return [path]
}
const sidebarRoutes = computed(() =>
routes.filter((item) => {
if (item.visible === Visibility.Public) {
return true
}
if (item.visible === Visibility.Authenticated) {
return currentUser.value !== null
}
if (item.visible === Visibility.Unauthenticated) {
return currentUser.value === null
}
if (item.visible === Visibility.Authorized) {
if (!currentUser.value) {
return false
}
if (!item.requiredRoles || item.requiredRoles.length === 0) {
return true
}
return item.requiredRoles.every((role) => hasRole(currentUser.value, role))
}
if (item.visible !== Visibility.Route) {
return false
}
return resolveVisibilityRoutes(item.path, item.visibilityRoute).some((targetPath) =>
isWithinRoutePath(route.path, targetPath),
)
}),
)
const adminSidebarRoutes = computed(() =>
sidebarRoutes.value.filter(
(item) =>
item.visible === Visibility.Authorized &&
Array.isArray(item.requiredRoles) &&
item.requiredRoles.some((role) => role.trim().toLowerCase() === ROLE_ADMIN),
),
)
const primarySidebarRoutes = computed(() =>
sidebarRoutes.value.filter(
(item) => !adminSidebarRoutes.value.some((adminItem) => adminItem.path === item.path),
),
)
const footerRoutes = computed(() => routes.filter((x) => x.visible === Visibility.Footer))
const { adminSidebarRoutes, primarySidebarRoutes, footerRoutes } = useSidebarRoutes(currentUser)
const activeRoute = computed(() => {
const byName = routes.find((x) => x.meta?.name === route.name)