Add profile settings page, mentor management, and S3 email logos

- Add universal /settings/profile page accessible to all roles with
  avatar upload, bio, phone, password change, and account deletion
- Expand updateProfile endpoint to accept bio (metadataJson), phone,
  and notification preference
- Add deleteAccount endpoint with password confirmation
- Add Profile Settings link to all nav components (admin, jury, mentor,
  observer)
- Add /admin/mentors list page and /admin/mentors/[id] detail page for
  mentor management
- Add Mentors nav item to admin sidebar
- Update email logo URLs to S3 (s3.monaco-opc.com/public/)
- Add ocean.png background image to email wrapper

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 19:57:12 +01:00
parent 0c0a9b7eb5
commit 402bdfd8c5
10 changed files with 1248 additions and 10 deletions

View File

@@ -2,6 +2,7 @@
import { useState } from 'react'
import Link from 'next/link'
import type { Route } from 'next'
import { usePathname } from 'next/navigation'
import { signOut } from 'next-auth/react'
import { cn } from '@/lib/utils'
@@ -29,6 +30,7 @@ import {
Handshake,
FileText,
CircleDot,
GraduationCap,
History,
User,
} from 'lucide-react'
@@ -66,6 +68,11 @@ const navigation = [
href: '/admin/users' as const,
icon: Users,
},
{
name: 'Mentors',
href: '/admin/mentors' as const,
icon: GraduationCap,
},
{
name: 'Reports',
href: '/admin/reports' as const,
@@ -176,7 +183,7 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
return (
<Link
key={item.name}
href={item.href}
href={item.href as Route}
onClick={() => setIsMobileMenuOpen(false)}
className={cn(
'group flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-all duration-150',
@@ -278,7 +285,7 @@ export function AdminSidebar({ user }: AdminSidebarProps) {
<DropdownMenuItem asChild>
<Link
href="/admin/settings"
href={"/settings/profile" as Route}
className="flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-2"
>
<User className="h-4 w-4 text-muted-foreground" />