This commit is contained in:
205
frontend/vue-app/src/router/index.ts
Normal file
205
frontend/vue-app/src/router/index.ts
Normal file
@@ -0,0 +1,205 @@
|
||||
import { watch } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import ChildLayout from '../layout/ChildLayout.vue'
|
||||
import ParentLayout from '../layout/ParentLayout.vue'
|
||||
import ChildrenListView from '../components/shared/ChildrenListView.vue'
|
||||
import ChildView from '../components/child/ChildView.vue'
|
||||
import ParentView from '../components/child/ParentView.vue'
|
||||
import TaskView from '../components/task/TaskView.vue'
|
||||
import RewardView from '../components/reward/RewardView.vue'
|
||||
import TaskEditView from '@/components/task/TaskEditView.vue'
|
||||
import RewardEditView from '@/components/reward/RewardEditView.vue'
|
||||
import ChildEditView from '@/components/child/ChildEditView.vue'
|
||||
import TaskAssignView from '@/components/child/TaskAssignView.vue'
|
||||
import RewardAssignView from '@/components/child/RewardAssignView.vue'
|
||||
import NotificationView from '@/components/notification/NotificationView.vue'
|
||||
import AuthLayout from '@/layout/AuthLayout.vue'
|
||||
import Signup from '@/components/auth/Signup.vue'
|
||||
import AuthLanding from '@/components/auth/AuthLanding.vue'
|
||||
import Login from '@/components/auth/Login.vue'
|
||||
import { isUserLoggedIn, isParentAuthenticated, isAuthReady } from '../stores/auth'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/auth',
|
||||
component: AuthLayout,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'AuthLanding',
|
||||
component: AuthLanding,
|
||||
},
|
||||
{
|
||||
path: 'signup',
|
||||
name: 'Signup',
|
||||
component: Signup,
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
name: 'Login',
|
||||
component: Login,
|
||||
},
|
||||
{
|
||||
path: 'verify',
|
||||
name: 'VerifySignup',
|
||||
component: () => import('@/components/auth/VerifySignup.vue'),
|
||||
},
|
||||
{
|
||||
path: 'forgot-password',
|
||||
name: 'ForgotPassword',
|
||||
component: () => import('@/components/auth/ForgotPassword.vue'),
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
name: 'ResetPassword',
|
||||
component: () => import('@/components/auth/ResetPassword.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/child',
|
||||
component: ChildLayout,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'ChildrenListView',
|
||||
component: ChildrenListView,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
name: 'ChildView',
|
||||
component: ChildView,
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/parent',
|
||||
component: ParentLayout,
|
||||
meta: { requiresAuth: true },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'ParentChildrenListView',
|
||||
component: ChildrenListView,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
name: 'ParentView',
|
||||
component: ParentView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'children/create',
|
||||
name: 'CreateChild',
|
||||
component: ChildEditView,
|
||||
},
|
||||
{
|
||||
path: ':id/edit',
|
||||
name: 'ChildEditView',
|
||||
component: ChildEditView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'tasks',
|
||||
name: 'TaskView',
|
||||
component: TaskView,
|
||||
props: false,
|
||||
},
|
||||
{
|
||||
path: 'tasks/create',
|
||||
name: 'CreateTask',
|
||||
component: TaskEditView,
|
||||
},
|
||||
{
|
||||
path: 'tasks/:id/edit',
|
||||
name: 'EditTask',
|
||||
component: TaskEditView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'rewards',
|
||||
name: 'RewardView',
|
||||
component: RewardView,
|
||||
props: false,
|
||||
},
|
||||
{
|
||||
path: 'rewards/create',
|
||||
name: 'CreateReward',
|
||||
component: RewardEditView,
|
||||
},
|
||||
{
|
||||
path: 'rewards/:id/edit',
|
||||
name: 'EditReward',
|
||||
component: RewardEditView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: ':id/assign-tasks/:type?',
|
||||
name: 'TaskAssignView',
|
||||
component: TaskAssignView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: ':id/assign-rewards',
|
||||
name: 'RewardAssignView',
|
||||
component: RewardAssignView,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'notifications',
|
||||
name: 'NotificationView',
|
||||
component: NotificationView,
|
||||
props: false,
|
||||
},
|
||||
{
|
||||
path: 'profile',
|
||||
name: 'UserProfile',
|
||||
component: () => import('@/components/profile/UserProfile.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/child',
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
// Auth guard
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
if (!isAuthReady.value) {
|
||||
await new Promise((resolve) => {
|
||||
const stop = watch(isAuthReady, (ready) => {
|
||||
if (ready) {
|
||||
stop()
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Always allow access to /auth routes
|
||||
if (to.path.startsWith('/auth')) {
|
||||
return next()
|
||||
}
|
||||
|
||||
// If not logged in, redirect to /auth
|
||||
if (!isUserLoggedIn.value) {
|
||||
return next('/auth')
|
||||
}
|
||||
|
||||
// If logged in but not parent-authenticated, redirect to /child (unless already there)
|
||||
if (!isParentAuthenticated.value && !to.path.startsWith('/child')) {
|
||||
return next('/child')
|
||||
}
|
||||
|
||||
// Otherwise, allow navigation
|
||||
next()
|
||||
})
|
||||
|
||||
export default router
|
||||
Reference in New Issue
Block a user