From a3d24a37159e1c777ead8384dd178fee8b24bfd6 Mon Sep 17 00:00:00 2001 From: yosaphatprs Date: Tue, 28 Oct 2025 14:53:33 +0700 Subject: [PATCH] feat: add route navigation guard --- frontend/hospital-log/src/routes/index.ts | 30 +++++++++++++++++-- .../hospital-log/src/views/auth/Login.vue | 6 ++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/frontend/hospital-log/src/routes/index.ts b/frontend/hospital-log/src/routes/index.ts index bec6046..b69bcde 100644 --- a/frontend/hospital-log/src/routes/index.ts +++ b/frontend/hospital-log/src/routes/index.ts @@ -5,8 +5,18 @@ import Login from "../views/auth/Login.vue"; import NotFoundView from "../views/NotFoundView.vue"; const routes = [ - { path: "/", name: "login", component: Login }, - { path: "/dashboard", name: "dashboard", component: DashboardView }, + { + path: "/", + name: "login", + component: Login, + meta: { requiresGuest: true }, + }, + { + path: "/dashboard", + name: "dashboard", + component: DashboardView, + meta: { requiresAuth: true }, + }, { path: "/:catchAll(.*)*", // This regex matches any path name: "NotFound", @@ -14,7 +24,21 @@ const routes = [ }, ]; -export const router = createRouter({ +const router = createRouter({ history: createWebHistory(), routes, }); + +router.beforeEach((to, _from, next) => { + const token = localStorage.getItem("csrf_token"); + + if (to.meta.requiresAuth && !token) { + next({ name: "login" }); + } else if (to.meta.requiresGuest && token) { + next({ name: "dashboard" }); + } else { + next(); + } +}); + +export { router }; diff --git a/frontend/hospital-log/src/views/auth/Login.vue b/frontend/hospital-log/src/views/auth/Login.vue index c69a529..a994794 100644 --- a/frontend/hospital-log/src/views/auth/Login.vue +++ b/frontend/hospital-log/src/views/auth/Login.vue @@ -28,6 +28,10 @@ const { handleSubmit } = useForm({ const { value: username, errorMessage: usernameError } = useField("username"); const { value: password, errorMessage: passwordError } = useField("password"); +const saveToken = async (token: string) => { + localStorage.setItem("csrf_token", token); +}; + const onSubmit = handleSubmit(async (values: any) => { isLoading.value = true; try { @@ -44,6 +48,7 @@ const onSubmit = handleSubmit(async (values: any) => { } loginError.value = ""; console.log("Success:", data); + await saveToken(data.csrfToken); router.push({ name: "dashboard" }); } catch (error: any) { if (error && Array.isArray(error.message)) { @@ -55,6 +60,7 @@ const onSubmit = handleSubmit(async (values: any) => { isLoading.value = false; } }); + const baseButtonClass = "bg-primary hover:bg-primary-dark text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full";