diff --git a/app/(app)/layout.tsx b/app/(app)/layout.tsx
index cdd8fae..5bc6df2 100644
--- a/app/(app)/layout.tsx
+++ b/app/(app)/layout.tsx
@@ -14,18 +14,34 @@ export default async function AppLayout({ children }: { children: React.ReactNod
redirect('/login')
}
- const userRoles = await prisma.userRole.findMany({
- where: { user_id: session.userId },
- select: { role: true },
- })
+ const [user, userRoles] = await Promise.all([
+ prisma.user.findUnique({
+ where: { id: session.userId },
+ select: { username: true, bio: true },
+ }),
+ prisma.userRole.findMany({
+ where: { user_id: session.userId },
+ select: { role: true },
+ }),
+ ])
const roles = userRoles.map(r => r.role as string)
+ if (!user) {
+ redirect('/login')
+ }
+
return (
Ga naar inhoud
-
+
{children}
diff --git a/components/shared/nav-bar.tsx b/components/shared/nav-bar.tsx
index dcee6ab..bafdd5c 100644
--- a/components/shared/nav-bar.tsx
+++ b/components/shared/nav-bar.tsx
@@ -2,32 +2,22 @@
import Link from 'next/link'
import { usePathname } from 'next/navigation'
-import { logoutAction } from '@/actions/auth'
-import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { AppIcon } from '@/components/shared/app-icon'
+import { UserMenu } from '@/components/shared/user-menu'
import { cn } from '@/lib/utils'
import { useProductStore } from '@/stores/product-store'
-const ROLE_LABELS: Record = {
- PRODUCT_OWNER: 'PO',
- SCRUM_MASTER: 'SM',
- DEVELOPER: 'Dev',
-}
-
-const ROLE_FULL_LABELS: Record = {
- PRODUCT_OWNER: 'Product Owner',
- SCRUM_MASTER: 'Scrum Master',
- DEVELOPER: 'Developer',
-}
-
interface NavBarProps {
isDemo: boolean
roles: string[]
+ userId: string
+ username: string
+ bio: string | null
}
-export function NavBar({ isDemo, roles }: NavBarProps) {
+export function NavBar({ isDemo, roles, userId, username, bio }: NavBarProps) {
const pathname = usePathname()
const currentProduct = useProductStore(s => s.currentProduct)
@@ -105,36 +95,9 @@ export function NavBar({ isDemo, roles }: NavBarProps) {
)}
- {/* Rechts: rollen + instellingen + uitloggen */}
+ {/* Rechts: account-menu */}
- {roles.length > 0 && (
-
-
- }>
- {roles.map(r => ROLE_LABELS[r]).filter(Boolean).join(' · ')}
-
-
- {roles.map(r => ROLE_FULL_LABELS[r]).filter(Boolean).join(' · ')}
-
-
-
- )}
-
- Instellingen
-
-
+
)
diff --git a/components/shared/user-menu.tsx b/components/shared/user-menu.tsx
new file mode 100644
index 0000000..a7c750b
--- /dev/null
+++ b/components/shared/user-menu.tsx
@@ -0,0 +1,113 @@
+'use client'
+
+import Link from 'next/link'
+import { Settings, Sun, Globe, LogOut } from 'lucide-react'
+import { logoutAction } from '@/actions/auth'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { Badge } from '@/components/ui/badge'
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from '@/components/ui/dropdown-menu'
+
+const ROLE_LABELS: Record = {
+ PRODUCT_OWNER: 'Product Owner',
+ SCRUM_MASTER: 'Scrum Master',
+ DEVELOPER: 'Developer',
+}
+
+interface UserMenuProps {
+ userId: string
+ username: string
+ bio: string | null
+ roles: string[]
+}
+
+export function UserMenu({ userId, username, bio, roles }: UserMenuProps) {
+ const initials = username.slice(0, 2).toUpperCase()
+ const roleLabels = roles.map((r) => ROLE_LABELS[r]).filter(Boolean)
+ const subtitle = bio?.trim() ? bio.trim() : 'Lokaal account'
+
+ return (
+
+
+
+
+
+ {initials}
+
+
+
+
+
+
+
+
+
+ {initials}
+
+
+
+
{username}
+
{subtitle}
+
+
+
+ {roleLabels.length > 0 && (
+ <>
+
+
+ Rollen
+
+
+ {roleLabels.join(', ')}
+
+ >
+ )}
+
+
+
+ }>
+
+ Instellingen
+
+
+
+
+ Thema: licht
+
+ Binnenkort
+
+
+
+
+
+ Taal: Nederlands
+
+ Binnenkort
+
+
+
+
+
+
+
+
+ )
+}