You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.4 KiB

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