132 lines
5.9 KiB
JavaScript
132 lines
5.9 KiB
JavaScript
|
|
import React, { useState } from 'react';
|
|
import { Menu, Bell, Clock, Moon, Sun, User, LogOut, Settings, UserCircle } from 'lucide-react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useTheme } from '@/contexts/ThemeContext';
|
|
import NotificationCenter from '@/components/NotificationCenter';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { ACCESS_TOKEN, REFRESH_TOKEN } from '@/lib/data';
|
|
import Cookies from 'js-cookie';
|
|
import { resetApp } from '@/store/resetAction';
|
|
import { useAppDispatch } from '@/store/hooks';
|
|
import { CompanyInfo } from '@/data/mockData';
|
|
|
|
const Topbar = ({ onMenuClick }) => {
|
|
const navigate = useNavigate();
|
|
const dispatch = useAppDispatch()
|
|
const { isDark, toggleTheme } = useTheme();
|
|
const [showNotifications, setShowNotifications] = useState(false);
|
|
const [showUserMenu, setShowUserMenu] = useState(false);
|
|
|
|
const handleLogout = () => {
|
|
Cookies.remove(ACCESS_TOKEN);
|
|
Cookies.remove(REFRESH_TOKEN);
|
|
|
|
dispatch(resetApp());
|
|
|
|
navigate('/login')
|
|
};
|
|
|
|
return (
|
|
<header className="sticky top-0 z-30 bg-white dark:bg-gray-950 border-b border-gray-200 dark:border-gray-800">
|
|
<div className="flex items-center justify-between px-4 lg:px-8 h-16">
|
|
<button
|
|
onClick={onMenuClick}
|
|
className="lg:hidden p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors"
|
|
>
|
|
<Menu className="w-5 h-5" />
|
|
</button>
|
|
|
|
<div className="flex-1" />
|
|
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={toggleTheme}
|
|
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors"
|
|
title={isDark ? "Mode clair" : "Mode sombre"}
|
|
>
|
|
{isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
|
|
</button>
|
|
|
|
<div className="relative">
|
|
<button
|
|
onClick={() => setShowNotifications(!showNotifications)}
|
|
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors relative"
|
|
>
|
|
<Bell className="w-5 h-5" />
|
|
<span className="absolute top-1.5 right-1.5 w-2 h-2 bg-[#007E45] rounded-full" />
|
|
</button>
|
|
{showNotifications && (
|
|
<NotificationCenter onClose={() => setShowNotifications(false)} />
|
|
)}
|
|
</div>
|
|
|
|
<div className="relative ml-2">
|
|
<button
|
|
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
className="flex items-center gap-3 pl-3 border-l border-gray-200 dark:border-gray-800 hover:opacity-80 transition-opacity"
|
|
>
|
|
<div className="text-right hidden sm:block">
|
|
<p className="text-sm font-medium text-gray-900 dark:text-white">{CompanyInfo.name}</p>
|
|
<p className="text-xs text-gray-500 dark:text-gray-400">Administrateur</p>
|
|
</div>
|
|
{/* <div className="w-9 h-9 rounded-full bg-[#941403] text-white flex items-center justify-center text-sm font-semibold"> */}
|
|
<div className="w-9 h-9 rounded-full bg-[#007E45] text-white flex items-center justify-center text-sm font-semibold">
|
|
SG
|
|
</div>
|
|
</button>
|
|
|
|
<AnimatePresence>
|
|
{showUserMenu && (
|
|
<>
|
|
<div
|
|
className="fixed inset-0 z-40"
|
|
onClick={() => setShowUserMenu(false)}
|
|
/>
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.95, y: 10 }}
|
|
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
exit={{ opacity: 0, scale: 0.95, y: 10 }}
|
|
className="absolute right-0 top-12 w-56 bg-white dark:bg-gray-950 border border-gray-200 dark:border-gray-800 rounded-xl shadow-xl z-50 overflow-hidden"
|
|
>
|
|
<div className="p-2 border-b border-gray-100 dark:border-gray-800">
|
|
<p className="px-2 py-1.5 text-sm font-medium text-gray-900 dark:text-white">{CompanyInfo.name}</p>
|
|
<p className="px-2 text-xs text-gray-500 dark:text-gray-400">{CompanyInfo.email}</p>
|
|
</div>
|
|
<div className="p-1">
|
|
<button
|
|
onClick={() => { navigate('/profile'); setShowUserMenu(false); }}
|
|
className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
>
|
|
<UserCircle className="w-4 h-4" />
|
|
Mon profil
|
|
</button>
|
|
<button
|
|
onClick={() => { navigate('/parametres'); setShowUserMenu(false); }}
|
|
className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-lg transition-colors"
|
|
>
|
|
<Settings className="w-4 h-4" />
|
|
Préférences
|
|
</button>
|
|
</div>
|
|
<div className="p-1 border-t border-gray-100 dark:border-gray-800">
|
|
<button
|
|
onClick={handleLogout}
|
|
className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
Déconnexion
|
|
</button>
|
|
</div>
|
|
</motion.div>
|
|
</>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
};
|
|
|
|
export default Topbar;
|