From 2d7464e05b59488afc5a9b828478ba87f0f7e5f8 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Mon, 13 Apr 2026 12:44:21 +0200 Subject: [PATCH] feat(portal): horizontal navbar layout with avatar menu and profile restructuring Replace the simple inline header with a proper Vuexy-style horizontal navbar featuring left (logo + event switcher), center (conditional menu items based on approval status), and right (avatar dropdown with profile link and logout) sections. Move profile page from /profile to /profiel as a platform-level page with "Mijn evenementen" section, removing the event-scoped status card and remarks field. Registration and success pages now use the portal layout with hideEventMenu meta so they get the navbar when logged in but no event menu items. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/portal/components.d.ts | 1 + apps/portal/env.d.ts | 1 + .../src/components/portal/StatusCard.vue | 2 +- .../src/components/portal/UserAvatarMenu.vue | 75 +++ apps/portal/src/layouts/portal.vue | 190 +++++--- apps/portal/src/pages/profiel.vue | 426 ++++++++++++++++++ apps/portal/src/pages/profile/index.vue | 389 ---------------- .../portal/src/pages/register/[eventSlug].vue | 3 +- apps/portal/src/pages/register/success.vue | 3 +- apps/portal/typed-router.d.ts | 2 +- 10 files changed, 628 insertions(+), 464 deletions(-) create mode 100644 apps/portal/src/components/portal/UserAvatarMenu.vue create mode 100644 apps/portal/src/pages/profiel.vue delete mode 100644 apps/portal/src/pages/profile/index.vue diff --git a/apps/portal/components.d.ts b/apps/portal/components.d.ts index 9fbbc02e..299a945a 100644 --- a/apps/portal/components.d.ts +++ b/apps/portal/components.d.ts @@ -46,5 +46,6 @@ declare module 'vue' { TheCustomizer: typeof import('./src/@core/components/TheCustomizer.vue')['default'] ThemeSwitcher: typeof import('./src/@core/components/ThemeSwitcher.vue')['default'] TiptapEditor: typeof import('./src/@core/components/TiptapEditor.vue')['default'] + UserAvatarMenu: typeof import('./src/components/portal/UserAvatarMenu.vue')['default'] } } diff --git a/apps/portal/env.d.ts b/apps/portal/env.d.ts index 4bd4b4cf..69ad44da 100644 --- a/apps/portal/env.d.ts +++ b/apps/portal/env.d.ts @@ -7,5 +7,6 @@ declare module 'vue-router' { requiresAuth?: boolean requiresToken?: boolean public?: boolean + hideEventMenu?: boolean } } diff --git a/apps/portal/src/components/portal/StatusCard.vue b/apps/portal/src/components/portal/StatusCard.vue index d5f35d91..352156d8 100644 --- a/apps/portal/src/components/portal/StatusCard.vue +++ b/apps/portal/src/components/portal/StatusCard.vue @@ -147,7 +147,7 @@ const registeredLabel = computed(() => { sm="4" > diff --git a/apps/portal/src/components/portal/UserAvatarMenu.vue b/apps/portal/src/components/portal/UserAvatarMenu.vue new file mode 100644 index 00000000..ae740203 --- /dev/null +++ b/apps/portal/src/components/portal/UserAvatarMenu.vue @@ -0,0 +1,75 @@ + + + diff --git a/apps/portal/src/layouts/portal.vue b/apps/portal/src/layouts/portal.vue index d626d40b..4c744198 100644 --- a/apps/portal/src/layouts/portal.vue +++ b/apps/portal/src/layouts/portal.vue @@ -1,5 +1,6 @@ @@ -60,20 +76,22 @@ async function logoutFromDrawer(): Promise { + - + { size="26" color="primary" /> - + Crewli - + - - - - -
+ +
{ - - - - Uitloggen - + +
+ +
- - - Inloggen - + + + +
+
+ + + {{ (authStore.user?.first_name?.charAt(0) ?? '') + (authStore.user?.last_name?.charAt(0) ?? '') }} + + +
+
+ {{ authStore.user?.full_name }} +
+
+ {{ authStore.user?.email }} +
+
+
+
+ + + { - -
@@ -204,5 +215,42 @@ async function logoutFromDrawer(): Promise { + + + + Powered by Crewli + + + diff --git a/apps/portal/src/pages/profiel.vue b/apps/portal/src/pages/profiel.vue new file mode 100644 index 00000000..46acfd37 --- /dev/null +++ b/apps/portal/src/pages/profiel.vue @@ -0,0 +1,426 @@ + + + diff --git a/apps/portal/src/pages/profile/index.vue b/apps/portal/src/pages/profile/index.vue deleted file mode 100644 index fcad9098..00000000 --- a/apps/portal/src/pages/profile/index.vue +++ /dev/null @@ -1,389 +0,0 @@ - - - diff --git a/apps/portal/src/pages/register/[eventSlug].vue b/apps/portal/src/pages/register/[eventSlug].vue index aa23fdfe..939331a0 100644 --- a/apps/portal/src/pages/register/[eventSlug].vue +++ b/apps/portal/src/pages/register/[eventSlug].vue @@ -21,8 +21,9 @@ import type { definePage({ name: 'volunteer-register', meta: { - layout: 'blank', + layout: 'portal', requiresAuth: false, + hideEventMenu: true, }, }) diff --git a/apps/portal/src/pages/register/success.vue b/apps/portal/src/pages/register/success.vue index 10e5f512..5f62db7e 100644 --- a/apps/portal/src/pages/register/success.vue +++ b/apps/portal/src/pages/register/success.vue @@ -4,8 +4,9 @@ import { useAuthStore } from '@/stores/useAuthStore' definePage({ name: 'register-success', meta: { - layout: 'blank', + layout: 'portal', requiresAuth: false, + hideEventMenu: true, }, }) diff --git a/apps/portal/typed-router.d.ts b/apps/portal/typed-router.d.ts index d92b41b7..97ba4cae 100644 --- a/apps/portal/typed-router.d.ts +++ b/apps/portal/typed-router.d.ts @@ -25,7 +25,7 @@ declare module 'vue-router/auto-routes' { 'portal-claim-shifts': RouteRecordInfo<'portal-claim-shifts', '/dashboard/claim-shifts', Record, Record>, 'portal-my-shifts': RouteRecordInfo<'portal-my-shifts', '/dashboard/my-shifts', Record, Record>, 'login': RouteRecordInfo<'login', '/login', Record, Record>, - 'portal-profile': RouteRecordInfo<'portal-profile', '/profile', Record, Record>, + 'portal-profiel': RouteRecordInfo<'portal-profiel', '/profiel', Record, Record>, 'volunteer-register': RouteRecordInfo<'volunteer-register', '/register/:eventSlug', { eventSlug: ParamValue }, { eventSlug: ParamValue }>, 'register-success': RouteRecordInfo<'register-success', '/register/success', Record, Record>, 'volunteer-register-info': RouteRecordInfo<'volunteer-register-info', '/registreren', Record, Record>,