| [694fc25] | 1 | import { useEffect, useRef, useState } from "react";
|
|---|
| [24a2a2a] | 2 | import { Link } from "react-router-dom";
|
|---|
| [b70fbeb] | 3 | import { toast } from "react-toastify";
|
|---|
| [4e5cf92] | 4 | import axiosInstance, { baseURL } from "../api/axiosInstance";
|
|---|
| 5 | import Logo from "../assets/logo-finkwave.png";
|
|---|
| 6 | import { useAuth } from "../context/authContext";
|
|---|
| [24a2a2a] | 7 |
|
|---|
| [694fc25] | 8 | interface NavProps {
|
|---|
| 9 | isSidebarOpen?: boolean;
|
|---|
| 10 | onToggleSidebar?: () => void;
|
|---|
| 11 | }
|
|---|
| 12 |
|
|---|
| 13 | const Nav = ({ isSidebarOpen = false, onToggleSidebar }: NavProps) => {
|
|---|
| [24a2a2a] | 14 | const { user, setUser, isAuthLoading } = useAuth();
|
|---|
| [694fc25] | 15 | const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|---|
| 16 | const dropdownRef = useRef<HTMLDivElement>(null);
|
|---|
| [24a2a2a] | 17 |
|
|---|
| [4022db1] | 18 | const handleLogout = async (e: React.MouseEvent<HTMLButtonElement>) => {
|
|---|
| 19 | e.preventDefault();
|
|---|
| [24a2a2a] | 20 | try {
|
|---|
| 21 | await axiosInstance.post("/auth/logout");
|
|---|
| 22 | setUser(undefined);
|
|---|
| [694fc25] | 23 | setIsDropdownOpen(false);
|
|---|
| [8dd3e22] | 24 | window.location.href = "/";
|
|---|
| 25 | // toast.success("Logout successful!");
|
|---|
| [24a2a2a] | 26 | } catch (error) {
|
|---|
| 27 | console.error("Logout failed:", error);
|
|---|
| [b70fbeb] | 28 | toast.error("Logout failed!");
|
|---|
| [24a2a2a] | 29 | }
|
|---|
| 30 | };
|
|---|
| 31 |
|
|---|
| [694fc25] | 32 | useEffect(() => {
|
|---|
| 33 | const handleClickOutside = (event: MouseEvent) => {
|
|---|
| 34 | if (
|
|---|
| 35 | dropdownRef.current &&
|
|---|
| 36 | !dropdownRef.current.contains(event.target as Node)
|
|---|
| 37 | ) {
|
|---|
| 38 | setIsDropdownOpen(false);
|
|---|
| 39 | }
|
|---|
| 40 | };
|
|---|
| 41 |
|
|---|
| 42 | document.addEventListener("mousedown", handleClickOutside);
|
|---|
| 43 | return () => {
|
|---|
| 44 | document.removeEventListener("mousedown", handleClickOutside);
|
|---|
| 45 | };
|
|---|
| 46 | }, []);
|
|---|
| 47 |
|
|---|
| [24a2a2a] | 48 | return (
|
|---|
| [694fc25] | 49 | <div
|
|---|
| 50 | className={`bg-gray-800 p-4 flex justify-between items-center fixed top-0 right-0 z-50 transition-all duration-300 ${
|
|---|
| 51 | isSidebarOpen ? "left-64" : "left-0"
|
|---|
| 52 | }`}
|
|---|
| 53 | >
|
|---|
| 54 | <div className="flex items-center gap-4">
|
|---|
| [dc30259] | 55 | {onToggleSidebar && user && (
|
|---|
| [694fc25] | 56 | <button
|
|---|
| 57 | onClick={onToggleSidebar}
|
|---|
| 58 | className="text-white hover:text-[#1db954] transition-colors p-2"
|
|---|
| 59 | aria-label="Toggle sidebar"
|
|---|
| 60 | >
|
|---|
| 61 | <svg
|
|---|
| 62 | className="w-6 h-6"
|
|---|
| 63 | fill="none"
|
|---|
| 64 | stroke="currentColor"
|
|---|
| 65 | viewBox="0 0 24 24"
|
|---|
| 66 | >
|
|---|
| 67 | <path
|
|---|
| 68 | strokeLinecap="round"
|
|---|
| 69 | strokeLinejoin="round"
|
|---|
| 70 | strokeWidth={2}
|
|---|
| 71 | d="M4 6h16M4 12h16M4 18h16"
|
|---|
| 72 | />
|
|---|
| 73 | </svg>
|
|---|
| 74 | </button>
|
|---|
| 75 | )}
|
|---|
| 76 | <Link to="/" className="text-white text-lg font-semibold">
|
|---|
| 77 | <img src={Logo} alt="Finkwave Logo" className="h-12 w-auto" />
|
|---|
| 78 | </Link>
|
|---|
| 79 | </div>
|
|---|
| [24a2a2a] | 80 |
|
|---|
| 81 | <div className="flex items-center space-x-4">
|
|---|
| 82 | {!isAuthLoading && (
|
|---|
| 83 | <div className="flex items-center space-x-3">
|
|---|
| [8dd3e22] | 84 | {user?.isArtist && (
|
|---|
| 85 | <Link
|
|---|
| 86 | to="/my-songs"
|
|---|
| 87 | className="text-white hover:text-[#1db954] px-4 py-2 text-sm font-medium transition-colors"
|
|---|
| 88 | >
|
|---|
| 89 | My Songs
|
|---|
| 90 | </Link>
|
|---|
| 91 | )}
|
|---|
| [24a2a2a] | 92 | {user ? (
|
|---|
| [694fc25] | 93 | <div className="relative" ref={dropdownRef}>
|
|---|
| 94 | <button
|
|---|
| 95 | onClick={() => setIsDropdownOpen(!isDropdownOpen)}
|
|---|
| 96 | className="focus:outline-none focus:ring-2 focus:ring-blue-500 rounded-full"
|
|---|
| 97 | >
|
|---|
| [484dc3f] | 98 | {user.profilePhoto ? (
|
|---|
| 99 | <img
|
|---|
| 100 | src={`${baseURL}/${user.profilePhoto}`}
|
|---|
| 101 | alt={`${user.username}'s profile`}
|
|---|
| [694fc25] | 102 | className="w-10 h-10 rounded-full object-cover cursor-pointer hover:ring-2 hover:ring-blue-400 transition-all"
|
|---|
| [484dc3f] | 103 | />
|
|---|
| 104 | ) : (
|
|---|
| [694fc25] | 105 | <div className="w-10 h-10 bg-blue-500 rounded-full flex items-center justify-center cursor-pointer hover:ring-2 hover:ring-blue-400 transition-all">
|
|---|
| 106 | <span className="text-white text-lg font-semibold">
|
|---|
| [484dc3f] | 107 | {user.username.charAt(0).toUpperCase()}
|
|---|
| 108 | </span>
|
|---|
| 109 | </div>
|
|---|
| 110 | )}
|
|---|
| [694fc25] | 111 | </button>
|
|---|
| [484dc3f] | 112 |
|
|---|
| [694fc25] | 113 | {isDropdownOpen && (
|
|---|
| 114 | <div className="absolute right-0 mt-2 w-48 bg-gray-700 rounded-lg shadow-lg py-1 z-50">
|
|---|
| 115 | <Link
|
|---|
| [ebdd3d4] | 116 | to="/me"
|
|---|
| [694fc25] | 117 | className="block px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
|
|---|
| 118 | onClick={() => setIsDropdownOpen(false)}
|
|---|
| 119 | >
|
|---|
| 120 | Account
|
|---|
| 121 | </Link>
|
|---|
| 122 | <button
|
|---|
| 123 | onClick={handleLogout}
|
|---|
| 124 | className="w-full text-left px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
|
|---|
| 125 | >
|
|---|
| 126 | Log out
|
|---|
| 127 | </button>
|
|---|
| [24a2a2a] | 128 | </div>
|
|---|
| [694fc25] | 129 | )}
|
|---|
| [24a2a2a] | 130 | </div>
|
|---|
| 131 | ) : (
|
|---|
| [4022db1] | 132 | <div className="flex items-center space-x-4">
|
|---|
| [24a2a2a] | 133 | <Link
|
|---|
| 134 | to="/login"
|
|---|
| [4022db1] | 135 | className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm
|
|---|
| 136 | font-medium transition-colors duration-200 cursor-pointer"
|
|---|
| [24a2a2a] | 137 | >
|
|---|
| 138 | Login
|
|---|
| 139 | </Link>
|
|---|
| [4022db1] | 140 | <Link
|
|---|
| 141 | to="/register"
|
|---|
| 142 | className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg text-sm
|
|---|
| 143 | font-medium transition-colors duration-200 cursor-pointer"
|
|---|
| 144 | >
|
|---|
| 145 | Register
|
|---|
| 146 | </Link>
|
|---|
| [24a2a2a] | 147 | </div>
|
|---|
| 148 | )}
|
|---|
| 149 | </div>
|
|---|
| 150 | )}
|
|---|
| 151 | </div>
|
|---|
| 152 | </div>
|
|---|
| 153 | );
|
|---|
| 154 | };
|
|---|
| 155 |
|
|---|
| 156 | export default Nav;
|
|---|