feat: Make menu context-aware and hide current page links
Implement intelligent menu filtering that hides self-referencing links and shows all applicable pages based on user role and authentication state. Changes: - Menu component now uses currentPath to filter out the current page link - Added computed properties to detect which page user is on - Fixed profile, admin, and users pages to dynamically detect admin status from API - Added menu to forgot-password page for consistent navigation - All pages now pass correct authentication state to Menu component This ensures menus always show relevant navigation options while avoiding redundant links to the current page. Admin users now see all admin options (Manage Sermons, Manage Users) regardless of which page they're on, except the current one. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
<div class="py-1">
|
||||
<!-- Home Link -->
|
||||
<NuxtLink
|
||||
v-if="showHome"
|
||||
v-if="showHome && !isOnHomePage"
|
||||
to="/"
|
||||
@click="isOpen = false"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
@@ -54,6 +54,7 @@
|
||||
<template v-if="isAuthenticated">
|
||||
<!-- Profile Link -->
|
||||
<NuxtLink
|
||||
v-if="!isOnProfilePage"
|
||||
to="/profile"
|
||||
@click="isOpen = false"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
@@ -64,6 +65,7 @@
|
||||
<!-- Admin Links -->
|
||||
<template v-if="isAdmin">
|
||||
<NuxtLink
|
||||
v-if="!isOnAdminPage"
|
||||
to="/admin"
|
||||
@click="isOpen = false"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
@@ -71,6 +73,7 @@
|
||||
📝 Manage Sermons
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
v-if="!isOnUsersPage"
|
||||
to="/users"
|
||||
@click="isOpen = false"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
@@ -91,6 +94,7 @@
|
||||
<!-- Not authenticated -->
|
||||
<template v-else>
|
||||
<NuxtLink
|
||||
v-if="!isOnLoginPage"
|
||||
:to="loginRedirectUrl"
|
||||
@click="isOpen = false"
|
||||
class="block px-4 py-2 text-sm text-green-700 hover:bg-green-50 font-medium"
|
||||
@@ -98,6 +102,7 @@
|
||||
🔑 Log In
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
v-if="!isOnRegisterPage"
|
||||
to="/register"
|
||||
@click="isOpen = false"
|
||||
class="block px-4 py-2 text-sm text-blue-700 hover:bg-blue-50 font-medium"
|
||||
@@ -130,6 +135,20 @@ const loginRedirectUrl = computed(() => {
|
||||
return `/login?redirect=${encodeURIComponent(redirectPath)}`
|
||||
})
|
||||
|
||||
// Determine which page we're currently on to hide self-referencing links
|
||||
const currentPathNormalized = computed(() => {
|
||||
const path = props.currentPath || route.fullPath
|
||||
// Remove query params and trailing slashes for comparison
|
||||
return path.split('?')[0].replace(/\/$/, '')
|
||||
})
|
||||
|
||||
const isOnHomePage = computed(() => currentPathNormalized.value === '' || currentPathNormalized.value === '/')
|
||||
const isOnProfilePage = computed(() => currentPathNormalized.value === '/profile')
|
||||
const isOnAdminPage = computed(() => currentPathNormalized.value === '/admin')
|
||||
const isOnUsersPage = computed(() => currentPathNormalized.value === '/users')
|
||||
const isOnLoginPage = computed(() => currentPathNormalized.value === '/login')
|
||||
const isOnRegisterPage = computed(() => currentPathNormalized.value === '/register')
|
||||
|
||||
// Toggle menu with debounce to prevent accidental double-taps
|
||||
const toggleMenu = () => {
|
||||
if (isToggling.value) return
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
</NuxtLink>
|
||||
<ClientOnly>
|
||||
<Menu
|
||||
:is-authenticated="true"
|
||||
:is-admin="true"
|
||||
:is-authenticated="isAuthenticated"
|
||||
:is-admin="isAdmin"
|
||||
:show-home="true"
|
||||
:current-path="route.fullPath"
|
||||
/>
|
||||
@@ -411,6 +411,11 @@ definePageMeta({
|
||||
middleware: 'auth'
|
||||
})
|
||||
|
||||
// Check authentication status
|
||||
const { data: authData } = await useFetch('/api/auth/verify')
|
||||
const isAuthenticated = computed(() => authData.value?.authenticated || false)
|
||||
const isAdmin = computed(() => authData.value?.isAdmin || false)
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
// Fetch all sermons for management (including archived)
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-gray-50 flex flex-col">
|
||||
<!-- Header -->
|
||||
<header class="bg-white shadow-sm">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<NuxtLink to="/">
|
||||
<img src="/logos/logo.png" alt="New Life Christian Church" class="h-16 w-auto" />
|
||||
</NuxtLink>
|
||||
<ClientOnly fallback-tag="div">
|
||||
<Menu
|
||||
:is-authenticated="isAuthenticated"
|
||||
:is-admin="isAdmin"
|
||||
:show-home="true"
|
||||
/>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex-1 flex items-center justify-center px-4">
|
||||
<div class="max-w-md w-full">
|
||||
<div class="text-center mb-8">
|
||||
<img src="/logos/logo.png" alt="New Life Christian Church" class="h-20 w-auto mx-auto mb-4" />
|
||||
<h2 class="text-3xl font-bold text-gray-900">Reset Password</h2>
|
||||
<p class="mt-2 text-sm text-gray-600">{{ stepMessage }}</p>
|
||||
</div>
|
||||
@@ -171,6 +188,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Check authentication status
|
||||
const { data: authData } = await useFetch('/api/auth/verify')
|
||||
const isAuthenticated = computed(() => authData.value?.authenticated || false)
|
||||
const isAdmin = computed(() => authData.value?.isAdmin || false)
|
||||
|
||||
const email = ref('')
|
||||
const code = ref('')
|
||||
const newPassword = ref('')
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
</NuxtLink>
|
||||
<ClientOnly>
|
||||
<Menu
|
||||
:is-authenticated="true"
|
||||
:is-admin="false"
|
||||
:is-authenticated="isAuthenticated"
|
||||
:is-admin="isAdmin"
|
||||
:show-home="true"
|
||||
:current-path="route.fullPath"
|
||||
/>
|
||||
@@ -248,6 +248,11 @@ definePageMeta({
|
||||
middleware: 'auth'
|
||||
})
|
||||
|
||||
// Check authentication status
|
||||
const { data: authData } = await useFetch('/api/auth/verify')
|
||||
const isAuthenticated = computed(() => authData.value?.authenticated || false)
|
||||
const isAdmin = computed(() => authData.value?.isAdmin || false)
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const profile = ref({
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
</NuxtLink>
|
||||
<ClientOnly>
|
||||
<Menu
|
||||
:is-authenticated="true"
|
||||
:is-admin="true"
|
||||
:is-authenticated="isAuthenticated"
|
||||
:is-admin="isAdmin"
|
||||
:show-home="true"
|
||||
:current-path="route.fullPath"
|
||||
/>
|
||||
@@ -227,6 +227,8 @@ interface User {
|
||||
|
||||
const { data: authData } = await useFetch('/api/auth/verify')
|
||||
const currentUsername = computed(() => authData.value?.username)
|
||||
const isAuthenticated = computed(() => authData.value?.authenticated || false)
|
||||
const isAdmin = computed(() => authData.value?.isAdmin || false)
|
||||
|
||||
const users = ref<User[]>([])
|
||||
const loading = ref(true)
|
||||
|
||||
Reference in New Issue
Block a user