Files
FabledScribe/frontend/src/router/index.ts
T
bvandeusen 65c85bab15
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 43s
CI & Build / Build & push image (push) Successful in 44s
feat(dashboard): DashboardView landing + route + nav
Task 3 of #583. New DashboardView at /dashboard composes the approved layout:
done-recently strip, Active-now project panels (project -> active milestones ->
open tasks, in-progress flagged, + no-milestone group), and a rail with
upcoming events / week stats / quick-create (Task/Note/Process). '/' now
redirects to /dashboard; AppHeader gains a Dashboard link and relabels
Knowledge -> Browse (route unchanged). Empty + loading states included.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 23:24:32 -04:00

147 lines
3.5 KiB
TypeScript

import { createRouter, createWebHistory } from "vue-router";
import { useAuthStore } from "@/stores/auth";
const router = createRouter({
history: createWebHistory(),
routes: [
{
// The dashboard ("what to work on") is the landing page; Knowledge
// remains as the exhaustive "Browse" surface.
path: "/",
redirect: "/dashboard",
},
{
path: "/dashboard",
name: "dashboard",
component: () => import("@/views/DashboardView.vue"),
},
{
path: "/knowledge",
name: "knowledge",
component: () => import("@/views/KnowledgeView.vue"),
},
{
path: "/login",
name: "login",
component: () => import("@/views/LoginView.vue"),
meta: { public: true },
},
{
path: "/register",
name: "register",
component: () => import("@/views/RegisterView.vue"),
meta: { public: true },
},
{
path: "/forgot-password",
name: "forgot-password",
component: () => import("@/views/ForgotPasswordView.vue"),
meta: { public: true },
},
{
path: "/reset-password",
name: "reset-password",
component: () => import("@/views/ResetPasswordView.vue"),
meta: { public: true },
},
{
path: "/register-invite",
name: "register-invite",
component: () => import("@/views/RegisterInviteView.vue"),
meta: { public: true },
},
{
path: "/notes",
redirect: "/knowledge",
},
{
path: "/notes/new",
name: "note-new",
component: () => import("@/views/NoteEditorView.vue"),
},
{
path: "/notes/:id",
name: "note-view",
component: () => import("@/views/NoteViewerView.vue"),
},
{
path: "/notes/:id/edit",
name: "note-edit",
component: () => import("@/views/NoteEditorView.vue"),
},
{
path: "/graph",
name: "graph",
component: () => import("@/views/GraphView.vue"),
},
{
path: "/projects",
name: "projects",
component: () => import("@/views/ProjectListView.vue"),
},
{
path: "/projects/:id",
name: "project-view",
component: () => import("@/views/ProjectView.vue"),
},
{
path: "/rules",
name: "rules",
component: () => import("@/views/RulesView.vue"),
},
{
path: "/tasks",
redirect: "/",
},
{
path: "/tasks/new",
name: "task-new",
component: () => import("@/views/TaskEditorView.vue"),
},
{
path: "/tasks/:id",
name: "task-edit",
component: () => import("@/views/TaskEditorView.vue"),
},
{
path: "/shared",
name: "shared-with-me",
component: () => import("@/views/SharedWithMeView.vue"),
},
{
path: "/calendar",
name: "calendar",
component: () => import("@/views/CalendarView.vue"),
},
{
path: "/settings",
name: "settings",
component: () => import("@/views/SettingsView.vue"),
},
{
path: "/trash",
name: "trash",
component: () => import("@/views/TrashView.vue"),
},
{ path: "/admin/users", redirect: "/settings" },
{ path: "/admin/logs", redirect: "/settings" },
],
});
router.beforeEach(async (to) => {
if (to.meta.public) return;
const authStore = useAuthStore();
// Wait for initial auth check if still loading
if (authStore.loading && !authStore.isAuthenticated) {
await authStore.checkAuth();
}
if (!authStore.isAuthenticated) {
return { name: "login", query: { redirect: to.fullPath } };
}
});
export default router;