Files
server/core/src/router/index.ts
2025-12-21 10:09:54 -05:00

117 lines
3.5 KiB
TypeScript

import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
import { useUserStore } from '@KTXC/stores/userStore';
import { useLayoutStore } from '@KTXC/stores/layoutStore';
import BlankLayout from '@KTXC/layouts/blank/BlankLayout.vue';
import PrivateLayout from '@KTXC/views/PrivateLayout.vue';
import { usePreferencesStore } from '@KTXC/stores/preferencesStore';
import { useIntegrationStore } from '@KTXC/stores/integrationStore';
const routes: RouteRecordRaw[] = [
// Public login route
{
name: 'login',
path: '/login',
meta: { requiresAuth: false },
component: BlankLayout,
children: [
{
path: '',
component: () => import('@KTXC/views/authentication/LoginPage.vue')
}
]
},
// Logout performs action then redirects
{
name: 'logout',
path: '/logout',
meta: { requiresAuth: true },
component: BlankLayout,
beforeEnter: async () => {
const userStore = useUserStore();
await userStore.logout();
return false;
}
},
// Private area (shell layout). Module routes under /m/{namespace} are added at runtime.
{
name: 'private',
path: '/',
component: PrivateLayout,
meta: { requiresAuth: true },
children: [
// Index redirects to the first available module route (if any)
{
name: 'home',
path: '',
meta: { requiresAuth: true },
component: BlankLayout,
beforeEnter: (to, from, next) => {
const integrationStore = useIntegrationStore();
const preferences = usePreferencesStore();
// Treat preference as a route name (e.g., "samples.overview")
const preferredRouteName = preferences.preferences.default_module;
if (preferredRouteName) {
// If a route with this name exists, go there
try {
// using router variable at runtime:
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const exists = router.getRoutes().some(r => r.name === preferredRouteName);
if (exists) return next({ name: preferredRouteName });
} catch {}
}
// Get first available menu item from app_menu
const entries = integrationStore.getPoint('app_menu');
for (const entry of entries) {
// Check if it's a group with items
if ('items' in entry && entry.items.length > 0) {
const first = entry.items[0]?.to;
if (first) return next(first);
}
// Or a standalone item
if ('to' in entry && entry.to) {
return next(entry.to);
}
}
return next();
}
}
]
}
];
export const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
});
router.beforeEach(async (to, from, next) => {
const userStore = useUserStore();
const authRequired = to.matched.some((record) => record.meta?.requiresAuth);
if (authRequired && !userStore.user && to.path !== '/login') {
userStore.returnUrl = to.fullPath;
return next('/login');
}
if (userStore.user && to.path === '/login') {
const dest = userStore.returnUrl && userStore.returnUrl !== '/' ? userStore.returnUrl : '/';
return next(dest);
}
return next();
});
router.beforeEach(() => {
const layoutStore = useLayoutStore();
layoutStore.isLoading = true;
});
router.afterEach(() => {
const layoutStore = useLayoutStore();
layoutStore.isLoading = false;
});
export default router