import { createRouter, createWebHistory, type RouteLocationNormalized } from 'vue-router' import { useAuthStore } from '@/stores/authStore' import type { AuthPermissionCode } from '@/types/auth' import { resolveAuthenticatedEntryPath, resolveLoginRedirectPath } from '@/utils/authNavigation' type AuthStore = ReturnType type AppRouteMeta = { public?: boolean layout?: 'plain' | 'app' permission?: AuthPermissionCode } export const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', name: 'home', component: { name: 'HomeRedirectView', render: () => null, }, }, { path: '/login', name: 'login', component: () => import('@/views/auth/LoginView.vue'), meta: { public: true, layout: 'plain', titleKey: 'auth.loginTitle', }, }, { path: '/unauthorized', name: 'unauthorized', component: () => import('@/views/auth/UnauthorizedView.vue'), meta: { titleKey: 'auth.unauthorizedTitle', }, }, { path: '/reservation/workbench', redirect: '/reservation/orders', }, { path: '/reservation/orders', name: 'reservation-order-list', component: () => import('@/views/reservation/ReservationOrderListView.vue'), meta: { titleKey: 'nav.orders', permission: 'RESERVATION_ORDER_READ', }, }, { path: '/reservation/tasks', name: 'reservation-task-list', component: () => import('@/views/reservation/ReservationTaskListView.vue'), meta: { titleKey: 'nav.taskQueue', permission: 'RESERVATION_TASK_READ', }, }, { path: '/reservation/orders/:orderId', name: 'reservation-order-detail', component: () => import('@/views/reservation/ReservationOrderDetailView.vue'), meta: { titleKey: 'nav.orderDetail', permission: 'RESERVATION_ORDER_READ', }, }, { path: '/reservation/tasks/:taskId', name: 'reservation-task-detail', component: () => import('@/views/reservation/ReservationTaskDetailView.vue'), meta: { titleKey: 'nav.taskDetail', permission: 'RESERVATION_TASK_READ', }, }, { path: '/reservation/source-messages/:sourceMessageId/conversation', name: 'reservation-source-message-conversation', component: () => import('@/views/reservation/ReservationSourceMessageConversationView.vue'), meta: { titleKey: 'nav.sourceMessageConversation', permission: 'SOURCE_MESSAGE_ORIGINAL_READ', }, }, { path: '/debug/eml-superagent', name: 'debug-eml-superagent', component: () => import('@/views/debug/DebugEmlSuperAgentRunView.vue'), meta: { titleKey: 'debugEml.title', permission: 'SYSTEM_DEBUG_EML_RUN', }, }, { path: '/system', component: () => import('@/views/system/SystemAdminLayoutView.vue'), meta: { titleKey: 'nav.systemSettings', permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS', }, children: [ { path: 'users', name: 'system-users', component: () => import('@/views/system/SystemUsersView.vue'), meta: { titleKey: 'nav.systemUsers', permission: 'SYSTEM_USER_MANAGE', }, }, { path: 'roles', name: 'system-roles', component: () => import('@/views/system/SystemRolesView.vue'), meta: { titleKey: 'nav.systemRoles', permission: 'SYSTEM_ROLE_MANAGE', }, }, { path: 'menus', name: 'system-menus', component: () => import('@/views/system/SystemMenusView.vue'), meta: { titleKey: 'nav.systemMenus', permission: 'SYSTEM_MENU_MANAGE', }, }, { path: 'hotels', name: 'system-hotels', component: () => import('@/views/system/SystemHotelsView.vue'), meta: { titleKey: 'nav.systemHotels', permission: 'HOTEL_MANAGE', }, }, { path: 'audits', name: 'system-audits', component: () => import('@/views/system/SystemAuditsView.vue'), meta: { titleKey: 'nav.systemAudits', permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS', }, }, ], }, { path: '/:pathMatch(.*)*', name: 'not-found', component: () => import('@/views/system/RouteNotFoundView.vue'), meta: { titleKey: 'notFound.title', }, }, ], }) router.beforeEach(createAuthGuard()) export function createAuthGuard(resolveAuthStore: () => AuthStore = () => useAuthStore()) { return async (to: RouteLocationNormalized) => { const authStore = resolveAuthStore() const meta = to.meta as AppRouteMeta if (!authStore.restoreAttempted && authStore.hasStoredToken()) { await authStore.restoreFromSession() } if (meta.public) { if (to.name === 'login' && authStore.isAuthenticated) { return resolveLoginRedirectPath(to.query.redirect, authStore.firstMenuPath) } return true } if (!authStore.isAuthenticated) { return { path: '/login', query: { redirect: to.fullPath, }, } } if (to.path === '/') { return resolveAuthenticatedEntryPath(authStore.firstMenuPath) } if (meta.permission && !authStore.hasPermission(meta.permission)) { return { name: 'unauthorized', } } if (to.path === '/system') { return resolveSystemAdminEntryPath(authStore) } return true } } function resolveSystemAdminEntryPath(authStore: AuthStore): string { if (authStore.hasPermission('SYSTEM_USER_MANAGE')) { return '/system/users' } if (authStore.hasPermission('SYSTEM_ROLE_MANAGE')) { return '/system/roles' } if (authStore.hasPermission('SYSTEM_MENU_MANAGE')) { return '/system/menus' } if (authStore.hasPermission('HOTEL_MANAGE')) { return '/system/hotels' } return '/system/audits' }