import { createRouter, createWebHistory } from 'vue-router' import type { RouteRecordRaw } from 'vue-router' import { useAuthStore } from '@/stores/auth' const routes: RouteRecordRaw[] = [ // Public routes { path: '/login', name: 'Login', component: () => import('@/views/auth/LoginView.vue'), meta: { requiresGuest: true } }, { path: '/register', name: 'Register', component: () => import('@/views/auth/RegisterView.vue'), meta: { requiresGuest: true } }, // Protected routes { path: '/', name: 'Dashboard', component: () => import('@/views/DashboardView.vue'), meta: { requiresAuth: true } }, { path: '/tasks', name: 'Tasks', component: () => import('@/views/TasksView.vue'), meta: { requiresAuth: true } }, { path: '/projects', name: 'Projects', component: () => import('@/views/ProjectsView.vue'), meta: { requiresAuth: true, roles: ['coordinator'], adminPermission: true } }, // Project detail routes with tab navigation { path: '/projects/:projectId', component: () => import('@/views/ProjectDetailView.vue'), meta: { requiresAuth: true }, children: [ { path: '', name: 'ProjectOverview', component: () => import('@/views/project/ProjectOverviewView.vue'), meta: { tab: 'overview', tabLabel: 'Overview' } }, { path: 'shots', name: 'ProjectShots', component: () => import('@/views/project/ProjectShotsView.vue'), meta: { tab: 'shots', tabLabel: 'Shots' } }, { path: 'shots/episode/:episodeId', name: 'ProjectShotsEpisode', component: () => import('@/views/project/ProjectShotsView.vue'), meta: { tab: 'shots', tabLabel: 'Shots', hasEpisode: true } }, { path: 'shots/:shotId', name: 'ShotDetail', component: () => import('@/views/project/ShotDetailView.vue'), meta: { requiresAuth: true } }, { path: 'assets', name: 'ProjectAssets', component: () => import('@/views/project/ProjectAssetsView.vue'), meta: { tab: 'assets', tabLabel: 'Assets' } }, { path: 'tasks', name: 'ProjectTasks', component: () => import('@/views/project/ProjectTasksView.vue'), meta: { tab: 'tasks', tabLabel: 'Tasks' } }, { path: 'settings', name: 'ProjectSettings', component: () => import('@/views/ProjectSettingsView.vue'), meta: { tab: 'settings', tabLabel: 'Settings' } } ] }, { path: '/projects/:projectId/episodes', name: 'Episodes', component: () => import('@/views/EpisodesView.vue'), meta: { requiresAuth: true } }, { path: '/users', name: 'Users', component: () => import('@/views/UsersView.vue'), meta: { requiresAuth: true, roles: ['coordinator'], adminPermission: true } }, { path: '/reviews', name: 'Reviews', component: () => import('@/views/ReviewsView.vue'), meta: { requiresAuth: true, roles: ['director'], adminPermission: true } }, { path: '/settings', name: 'Settings', component: () => import('@/views/SettingsView.vue'), meta: { requiresAuth: true, adminPermission: 'required' } }, // Admin routes { path: '/admin', name: 'Admin', redirect: '/admin/deleted-items', meta: { requiresAuth: true, adminPermission: 'required' } }, { path: '/admin/deleted-items', name: 'RecoveryManagement', component: () => import('@/views/admin/DeletedItemsManagementView.vue'), meta: { requiresAuth: true, adminPermission: 'required', title: 'Recovery Management' } }, // Developer routes { path: '/developer', name: 'Developer', redirect: '/developer/api-keys', meta: { requiresAuth: true, roles: ['developer'] } }, { path: '/developer/api-keys', name: 'DeveloperAPIKeys', component: () => import('@/views/developer/APIKeysView.vue'), meta: { requiresAuth: true, roles: ['developer'] } }, { path: '/developer/projects', name: 'DeveloperProjects', component: () => import('@/views/developer/ProjectsView.vue'), meta: { requiresAuth: true, roles: ['developer'] } }, { path: '/developer/tasks', name: 'DeveloperTasks', component: () => import('@/views/developer/TasksView.vue'), meta: { requiresAuth: true, roles: ['developer'] } }, { path: '/developer/analytics', name: 'DeveloperAnalytics', component: () => import('@/views/developer/AnalyticsView.vue'), meta: { requiresAuth: true, roles: ['developer'] } }, // Profile route { path: '/profile', name: 'Profile', component: () => import('@/views/ProfileView.vue'), meta: { requiresAuth: true } }, // Catch all route { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('@/views/NotFoundView.vue') } ] const router = createRouter({ history: createWebHistory(), routes }) // Navigation guards router.beforeEach(async (to, from, next) => { const authStore = useAuthStore() // Initialize auth if not already done if (!authStore.user && authStore.accessToken) { try { await authStore.initializeAuth() } catch (error) { console.error('Auth initialization failed:', error) } } const requiresAuth = to.meta.requiresAuth const requiresGuest = to.meta.requiresGuest const requiredRoles = to.meta.roles as string[] | undefined const adminPermission = to.meta.adminPermission const isAuthenticated = authStore.isAuthenticated const userRole = authStore.userRole const isAdmin = authStore.isAdmin // Handle guest-only routes (login, register) if (requiresGuest && isAuthenticated) { return next('/') } // Handle protected routes if (requiresAuth && !isAuthenticated) { return next('/login') } // Handle role-based access with admin permission support if (requiredRoles && userRole) { const hasRequiredRole = requiredRoles.includes(userRole) const hasAdminPermission = adminPermission && isAdmin if (!hasRequiredRole && !hasAdminPermission) { return next('/') } } // Handle admin-only routes if (adminPermission === 'required' && !isAdmin) { return next('/') } next() }) // Set page title from route meta router.afterEach((to) => { const title = to.meta.title as string if (title) { document.title = `${title} - VFX Studio` } else { document.title = 'VFX Studio' } }) export default router