diff --git a/app/admin/layout.tsx b/app/admin/layout.tsx
index 2121dcc..5fc5121 100644
--- a/app/admin/layout.tsx
+++ b/app/admin/layout.tsx
@@ -3,12 +3,11 @@
import Sidebar from "@/components/admin/Sidebar";
import { useAuth } from "@/contexts/AuthContext";
import { useRouter } from "next/navigation";
-import { useEffect, useState } from "react";
+import { useEffect } from "react";
import { Loading } from "@/components/ui/Loading";
import toast from "react-hot-toast";
-import { LogOut, User, ChevronDown } from "lucide-react";
import Logo from "@/components/Logo";
-import Link from "next/link";
+import UserDropdown from "@/components/UserDropdown";
export default function AdminLayout({
children,
@@ -17,7 +16,6 @@ export default function AdminLayout({
}) {
const { user, isAuthenticated, isLoading, logout } = useAuth();
const router = useRouter();
- const [dropdownOpen, setDropdownOpen] = useState(false);
useEffect(() => {
if (!isLoading && !isAuthenticated) {
@@ -32,24 +30,6 @@ export default function AdminLayout({
}
}, [isLoading, isAuthenticated, user, router]);
- // Close dropdown when clicking outside
- useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- const target = event.target as HTMLElement;
- if (!target.closest('.user-dropdown')) {
- setDropdownOpen(false);
- }
- };
-
- if (dropdownOpen) {
- document.addEventListener('mousedown', handleClickOutside);
- }
-
- return () => {
- document.removeEventListener('mousedown', handleClickOutside);
- };
- }, [dropdownOpen]);
-
const handleLogout = async () => {
await logout();
router.push("/login");
@@ -81,48 +61,12 @@ export default function AdminLayout({
- {/* User Dropdown */}
-
-
-
- {/* Dropdown Menu */}
- {dropdownOpen && (
-
-
setDropdownOpen(false)}
- className="flex items-center gap-3 px-4 py-3 hover:bg-gray-100 transition-colors"
- >
-
-
Profil
-
-
-
-
- )}
-
+
diff --git a/app/employe/layout.tsx b/app/employe/layout.tsx
index 8e91de4..ca31a82 100644
--- a/app/employe/layout.tsx
+++ b/app/employe/layout.tsx
@@ -2,13 +2,14 @@
import { useAuth } from "@/contexts/AuthContext";
import { useRouter } from "next/navigation";
-import { useEffect, useState } from "react";
+import { useEffect } from "react";
import { Loading } from "@/components/ui/Loading";
import toast from "react-hot-toast";
-import { LogOut, Ticket, BarChart3, User, ChevronDown } from "lucide-react";
+import { Ticket, BarChart3 } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import Logo from "@/components/Logo";
+import UserDropdown from "@/components/UserDropdown";
export default function EmployeLayout({
children,
@@ -18,7 +19,6 @@ export default function EmployeLayout({
const { user, isAuthenticated, isLoading, logout } = useAuth();
const router = useRouter();
const pathname = usePathname();
- const [dropdownOpen, setDropdownOpen] = useState(false);
useEffect(() => {
if (!isLoading && !isAuthenticated) {
@@ -33,24 +33,6 @@ export default function EmployeLayout({
}
}, [isLoading, isAuthenticated, user, router]);
- // Close dropdown when clicking outside
- useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- const target = event.target as HTMLElement;
- if (!target.closest('.user-dropdown')) {
- setDropdownOpen(false);
- }
- };
-
- if (dropdownOpen) {
- document.addEventListener('mousedown', handleClickOutside);
- }
-
- return () => {
- document.removeEventListener('mousedown', handleClickOutside);
- };
- }, [dropdownOpen]);
-
const handleLogout = async () => {
await logout();
router.push("/login");
@@ -129,48 +111,12 @@ export default function EmployeLayout({
- {/* User Dropdown */}
-
-
-
- {/* Dropdown Menu */}
- {dropdownOpen && (
-
-
setDropdownOpen(false)}
- className="flex items-center gap-3 px-4 py-3 hover:bg-gray-100 transition-colors"
- >
-
-
Profil
-
-
-
-
- )}
-
+
diff --git a/components/UserDropdown.tsx b/components/UserDropdown.tsx
new file mode 100644
index 0000000..7264192
--- /dev/null
+++ b/components/UserDropdown.tsx
@@ -0,0 +1,93 @@
+'use client';
+
+import React, { useState, useRef } from 'react';
+import Link from 'next/link';
+import { LogOut, User, ChevronDown } from 'lucide-react';
+import { useClickOutside } from '@/hooks/useClickOutside';
+import { cn } from '@/utils/helpers';
+
+interface UserDropdownProps {
+ user: {
+ firstName?: string;
+ lastName?: string;
+ email?: string;
+ } | null;
+ profilePath: string;
+ onLogout: () => void;
+ accentColor?: 'blue' | 'green';
+ className?: string;
+}
+
+const accentColors = {
+ blue: 'bg-blue-600',
+ green: 'bg-green-600',
+};
+
+export const UserDropdown: React.FC = ({
+ user,
+ profilePath,
+ onLogout,
+ accentColor = 'blue',
+ className,
+}) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const dropdownRef = useRef(null);
+
+ useClickOutside(dropdownRef, () => setIsOpen(false), isOpen);
+
+ const initials = `${user?.firstName?.charAt(0) || ''}${user?.lastName?.charAt(0) || ''}`;
+
+ return (
+
+
+
+ {isOpen && (
+
+
setIsOpen(false)}
+ className="flex items-center gap-3 px-4 py-3 hover:bg-gray-100 transition-colors"
+ >
+
+
Profil
+
+
+
+
+ )}
+
+ );
+};
+
+export default UserDropdown;
diff --git a/hooks/useClickOutside.ts b/hooks/useClickOutside.ts
new file mode 100644
index 0000000..d64d530
--- /dev/null
+++ b/hooks/useClickOutside.ts
@@ -0,0 +1,31 @@
+import { useEffect, RefObject } from 'react';
+
+/**
+ * Hook to detect clicks outside of a specified element
+ * @param ref - Reference to the element to monitor
+ * @param callback - Function to call when clicking outside
+ * @param enabled - Whether the hook is active (default: true)
+ */
+export function useClickOutside(
+ ref: RefObject,
+ callback: () => void,
+ enabled: boolean = true
+): void {
+ useEffect(() => {
+ if (!enabled) return;
+
+ const handleClickOutside = (event: MouseEvent) => {
+ if (ref.current && !ref.current.contains(event.target as Node)) {
+ callback();
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, [ref, callback, enabled]);
+}
+
+export default useClickOutside;