NeahFront5/components/main-nav.tsx
2025-04-10 11:30:00 +02:00

356 lines
12 KiB
TypeScript

"use client";
import { useState } from "react";
import {
Calendar,
MessageSquare,
BotIcon as Robot,
Bell,
Users,
LogOut,
UserCog,
Clock,
PenLine,
Video,
Radio as RadioIcon,
Megaphone,
Heart,
Target,
Mail,
Telescope,
Lightbulb,
Circle,
Menu,
} from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { Sidebar } from "./sidebar";
import { useSession, signIn, signOut } from "next-auth/react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { format } from 'date-fns';
import { fr } from 'date-fns/locale';
const requestNotificationPermission = async () => {
try {
const permission = await Notification.requestPermission();
return permission === "granted";
} catch (error) {
console.error("Error requesting notification permission:", error);
return false;
}
};
export function MainNav() {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const { data: session, status } = useSession();
const [userStatus, setUserStatus] = useState<'online' | 'busy' | 'away'>('online');
console.log("Session:", session);
console.log("Status:", status);
// Updated function to get user initials
const getUserInitials = () => {
if (session?.user?.name) {
// Split the full name and get initials
const names = session.user.name.split(' ');
if (names.length >= 2) {
return `${names[0][0]}${names[names.length - 1][0]}`.toUpperCase();
}
// If only one name, use first two letters
return names[0].slice(0, 2).toUpperCase();
}
return "?";
};
// Function to get display name
const getDisplayName = () => {
return session?.user?.name || "User";
};
// Function to get user role
const getUserRole = () => {
if (session?.user?.role) {
if (Array.isArray(session.user.role)) {
// Filter out technical roles and format remaining ones
return session.user.role
.filter(role =>
!['offline_access', 'uma_authorization', 'default-roles-cercle'].includes(role)
)
.map(role => {
// Transform role names
switch(role) {
case 'ROLE_Mentors':
return 'Mentor';
case 'ROLE_apprentice':
return 'Apprentice';
case 'ROLE_Admin':
return 'Admin';
default:
return role.replace('ROLE_', '');
}
})
.join(', ');
}
return session.user.role;
}
return "";
};
// Function to check if user has a specific role
const hasRole = (requiredRoles: string[]) => {
if (!session?.user?.role) return false;
const userRoles = Array.isArray(session.user.role) ? session.user.role : [session.user.role];
// Add console.log to debug roles
console.log('User roles:', userRoles);
console.log('Required roles:', requiredRoles);
return userRoles.some(role => {
// Remove ROLE_ prefix if it exists
const cleanRole = role.replace('ROLE_', '');
return requiredRoles.includes(cleanRole) || cleanRole === 'Admin';
});
};
// Status configurations
const statusConfig = {
online: {
color: 'text-green-500',
label: 'Online',
notifications: true
},
busy: {
color: 'text-orange-500',
label: 'Busy',
notifications: false
},
away: {
color: 'text-gray-500',
label: 'Away',
notifications: false
},
};
// Handle status change
const handleStatusChange = async (newStatus: 'online' | 'busy' | 'away') => {
setUserStatus(newStatus);
if (newStatus !== 'online') {
// If status is busy or away, check and request notification permission if needed
const hasPermission = await requestNotificationPermission();
if (hasPermission) {
// Disable notifications
if ('serviceWorker' in navigator) {
const registration = await navigator.serviceWorker.ready;
await registration.pushManager.getSubscription()?.then(subscription => {
if (subscription) {
subscription.unsubscribe();
}
});
}
}
} else {
// Re-enable notifications if going back online
requestNotificationPermission();
}
};
// Base menu items (available for everyone)
const baseMenuItems = [
{
title: "HealthView",
icon: Heart,
href: '/health-view',
},
{
title: "MissionView",
icon: Target,
href: '/mission-view',
},
];
// Role-specific menu items
const roleSpecificItems = [
{
title: "ShowCase",
icon: Lightbulb,
href: '/showcase',
requiredRoles: ["Expression"],
},
{
title: "UsersView",
icon: UserCog,
href: '/management',
requiredRoles: ["Admin", "Entrepreneurship"],
},
{
title: "TheMessage",
icon: Mail,
href: '/the-message',
requiredRoles: ["Mediation", "Expression"],
},
];
// Get visible menu items based on user roles
const visibleMenuItems = [
...baseMenuItems,
...roleSpecificItems.filter(item => hasRole(item.requiredRoles))
];
// Format current date and time
const now = new Date();
const formattedDate = format(now, "d MMMM yyyy", { locale: fr });
const formattedTime = format(now, "HH:mm");
return (
<>
<div className="fixed top-0 left-0 right-0 z-50 bg-black">
<div className="flex items-center justify-between px-4 py-1">
{/* Left side */}
<div className="flex items-center space-x-4">
<button
onClick={() => setIsSidebarOpen(true)}
className="text-white/80 hover:text-white"
>
<Menu className="w-5 h-5" />
</button>
<Link href='/'>
<Image
src='/Neahv2 logo W.png'
alt='Neah Logo'
width={40}
height={13}
className='text-white'
/>
</Link>
<Link href='/timetracker' className='text-white/80 hover:text-white'>
<Clock className='w-5 h-5' />
<span className="sr-only">TimeTracker</span>
</Link>
<Link href='/calendar' className='text-white/80 hover:text-white'>
<Calendar className='w-5 h-5' />
</Link>
<Link href='/notes' className='text-white/80 hover:text-white'>
<PenLine className='w-5 h-5' />
<span className="sr-only">Notes</span>
</Link>
<Link href='/ai-assistant' className='text-white/80 hover:text-white'>
<Robot className='w-5 h-5' />
<span className="sr-only">Alma</span>
</Link>
<Link href='/conference' className='text-white/80 hover:text-white'>
<Video className='w-5 h-5' />
<span className="sr-only">Conference</span>
</Link>
<Link href='/radio' className='text-white/80 hover:text-white'>
<RadioIcon className='w-5 h-5' />
<span className="sr-only">Radio</span>
</Link>
<Link href='/announcement' className='text-white/80 hover:text-white'>
<Megaphone className='w-5 h-5' />
<span className="sr-only">Announcement</span>
</Link>
</div>
{/* Right side */}
<div className="flex items-center space-x-8">
{/* Date and Time with smaller text */}
<div className="text-white/80 text-sm">
<span className="mr-2">{formattedDate}</span>
<span>{formattedTime}</span>
</div>
<Link
href='/notifications'
className='text-white/80 hover:text-white'
>
<Bell className='w-5 h-5' />
</Link>
{status === "authenticated" && session?.user ? (
<DropdownMenu>
<DropdownMenuTrigger className="outline-none">
<div className="w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white cursor-pointer hover:bg-blue-700 transition-colors">
{getUserInitials()}
</div>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56 bg-black/90 border-gray-700">
<DropdownMenuLabel className="text-white/80">
<div className="flex items-center justify-between">
<span>{getDisplayName()}</span>
<DropdownMenu>
<DropdownMenuTrigger className="outline-none">
<div className="flex items-center space-x-1 text-sm">
<Circle className={`h-3 w-3 ${statusConfig[userStatus].color}`} />
<span className="text-gray-400">{statusConfig[userStatus].label}</span>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className="bg-black/90 border-gray-700">
<DropdownMenuItem
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
onClick={() => handleStatusChange('online')}
>
<Circle className="h-3 w-3 text-green-500 mr-2" />
<span>Online</span>
</DropdownMenuItem>
<DropdownMenuItem
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
onClick={() => handleStatusChange('busy')}
>
<Circle className="h-3 w-3 text-orange-500 mr-2" />
<span>Busy</span>
</DropdownMenuItem>
<DropdownMenuItem
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
onClick={() => handleStatusChange('away')}
>
<Circle className="h-3 w-3 text-gray-500 mr-2" />
<span>Away</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator className="bg-gray-700" />
{visibleMenuItems.map((item) => (
<DropdownMenuItem
key={item.title}
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
onClick={() => window.location.href = item.href}
>
<item.icon className="mr-2 h-4 w-4" />
<span>{item.title}</span>
</DropdownMenuItem>
))}
<DropdownMenuItem
className="text-white/80 hover:text-white hover:bg-black/50 cursor-pointer"
onClick={() => signOut()}
>
<LogOut className="mr-2 h-4 w-4" />
<span>Déconnexion</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
) : (
<div className='cursor-pointer text-white/80 hover:text-white'>
<span onClick={() => signIn("keycloak", { callbackUrl: "/" })}>
Login
</span>
</div>
)}
</div>
</div>
</div>
<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
</>
);
}