import { createRouter, createWebHistory } from 'vue-router' import { TOKEN_KEY, PARTICIPANT_COMPETITION_SLUG_KEY, pathIsReviewerZone, readReviewerSession, } from '../config/api' import { useAdminAuthStore } from '../stores/adminAuth' import { adminDynamicRoutesRegistered, registerAdminDynamicRoutes, } from './admin/registerDynamicRoutes' import './admin/routeMeta' const MainLayout = () => import('../layouts/MainLayout.vue') function participantRootRedirect() { const t = localStorage.getItem(TOKEN_KEY) const s = localStorage.getItem(PARTICIPANT_COMPETITION_SLUG_KEY) if (s) { return t ? { name: 'participant-apply', params: { slug: s }, replace: true as const } : { name: 'participant-login', params: { slug: s }, replace: true as const } } return { path: '/c', replace: true as const } } const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', redirect: participantRootRedirect, }, { path: '/c', name: 'participant-landing', component: () => import('../views/ParticipantLandingView.vue'), }, { path: '/c/:slug/login', name: 'participant-login', component: () => import('../views/LoginView.vue'), meta: { guestOnly: true }, }, { path: '/c/:slug/review/login', name: 'reviewer-login', component: () => import('../views/reviewer/ReviewerLoginView.vue'), meta: { guestReviewerOnly: true }, }, { path: '/c/:slug/review', component: () => import('../layouts/ReviewerLayout.vue'), meta: { requiresReviewerAuth: true }, children: [ { path: 'applications/:id(\\d+)', name: 'reviewer-application-detail', component: () => import('../views/reviewer/ReviewerApplicationDetailView.vue'), }, { path: '', name: 'reviewer-projects', component: () => import('../views/reviewer/ReviewerProjectsView.vue'), }, ], }, { path: '/c/:slug', component: MainLayout, meta: { requiresAuth: true }, children: [ { path: '', redirect: (to) => ({ name: 'participant-apply', params: { slug: to.params.slug as string }, }), }, { path: 'apply', name: 'participant-apply', component: () => import('../views/ApplyView.vue'), }, ], }, { path: '/app', redirect: () => { const s = localStorage.getItem(PARTICIPANT_COMPETITION_SLUG_KEY) return s ? { name: 'participant-apply', params: { slug: s } } : { path: '/c' } }, }, { path: '/app/apply', redirect: () => { const s = localStorage.getItem(PARTICIPANT_COMPETITION_SLUG_KEY) return s ? { name: 'participant-apply', params: { slug: s } } : { path: '/c' } }, }, { path: '/admin/login', name: 'admin-login', component: () => import('../views/admin/AdminLoginView.vue'), }, { path: '/admin', name: 'AdminLayout', component: () => import('../layouts/AdminLayout.vue'), children: [], }, ], }) router.beforeEach(async (to) => { const slugRaw = to.params.slug != null ? String(to.params.slug).trim() : '' if (!pathIsReviewerZone(to.path) && slugRaw) { localStorage.setItem(PARTICIPANT_COMPETITION_SLUG_KEY, slugRaw) } const participantToken = localStorage.getItem(TOKEN_KEY) if (pathIsReviewerZone(to.path)) { const { token: reviewerToken, competitionSlug: reviewerSlug } = readReviewerSession() if (to.name === 'reviewer-login') { if (reviewerToken && reviewerSlug !== '' && reviewerSlug === slugRaw) { return { name: 'reviewer-projects', params: { slug: slugRaw }, replace: true } } return true } if (to.matched.some((r) => r.meta.requiresReviewerAuth === true)) { if (!reviewerToken || reviewerSlug !== slugRaw) { return { name: 'reviewer-login', params: { slug: slugRaw }, query: slugRaw ? { redirect: to.fullPath } : {}, } } } return true } if (to.path.startsWith('/admin')) { const adminAuth = useAdminAuthStore() if (to.name === 'admin-login' || to.path === '/admin/login') { if (adminAuth.isAuthenticated) { if (!adminDynamicRoutesRegistered()) { await registerAdminDynamicRoutes(router) } return { name: 'admin-competitions-list', replace: true } } return true } if (!adminAuth.isAuthenticated) { return { path: '/admin/login', query: { redirect: to.fullPath } } } if (!adminDynamicRoutesRegistered()) { await registerAdminDynamicRoutes(router) return { ...to, replace: true } } return true } if (to.matched.some((r) => r.meta.requiresAuth) && !participantToken) { const slug = to.params.slug != null ? String(to.params.slug) : '' if (slug) { return { name: 'participant-login', params: { slug }, query: { redirect: to.fullPath } } } return { path: '/c', query: { redirect: to.fullPath } } } if (to.meta.guestOnly && participantToken) { const slug = to.params.slug != null ? String(to.params.slug) : '' if (slug) { return { name: 'participant-apply', params: { slug }, replace: true } } return participantRootRedirect() } return true }) export default router