|
1 | 1 | import { useState, useEffect } from "react"; |
2 | 2 | import { Button } from "../components/ui/button.js"; |
3 | 3 | import { useNavigate } from "react-router-dom"; |
4 | | -import { Menu, X, PlusSquare, LogIn, LogOut } from "lucide-react"; |
| 4 | +import { Menu, X } from "lucide-react"; |
5 | 5 | import axios from "axios"; |
6 | 6 |
|
7 | 7 | function Header() { |
8 | 8 | const [isScrolled, setIsScrolled] = useState(false); |
9 | 9 | const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); |
10 | 10 | const [user, setUser] = useState<{ _id: string; name: string } | null>(null); |
11 | | - const [isDropdownOpen, setIsDropdownOpen] = useState(false); |
12 | 11 | const navigate = useNavigate(); |
13 | 12 |
|
14 | | - // Scroll effect |
| 13 | + // Scroll shadow effect |
15 | 14 | useEffect(() => { |
16 | | - const handleScroll = () => setIsScrolled(window.scrollY > 20); |
| 15 | + const handleScroll = () => setIsScrolled(window.scrollY > 10); |
17 | 16 | window.addEventListener("scroll", handleScroll); |
18 | 17 | return () => window.removeEventListener("scroll", handleScroll); |
19 | 18 | }, []); |
20 | 19 |
|
21 | | - // Fetch authenticated user |
| 20 | + // Fetch logged-in user |
22 | 21 | useEffect(() => { |
23 | 22 | const token = localStorage.getItem("token"); |
24 | 23 | if (!token) return; |
25 | | - |
26 | 24 | const fetchUser = async () => { |
27 | 25 | try { |
28 | 26 | const res = await axios.get("http://localhost:3000/api/auth/me", { |
29 | 27 | headers: { Authorization: `Bearer ${token}` }, |
30 | 28 | }); |
31 | 29 | setUser(res.data.user); |
32 | 30 | } catch { |
| 31 | + localStorage.removeItem("token"); |
33 | 32 | setUser(null); |
34 | | - localStorage.removeItem("token"); // remove invalid token |
35 | 33 | } |
36 | 34 | }; |
37 | | - |
38 | 35 | fetchUser(); |
39 | 36 | }, []); |
40 | 37 |
|
| 38 | + // Scroll to section smoothly |
41 | 39 | const scrollToSection = (id: string) => { |
42 | | - const element = document.getElementById(id); |
43 | | - if (element) { |
44 | | - element.scrollIntoView({ behavior: "smooth" }); |
| 40 | + const el = document.getElementById(id); |
| 41 | + if (el) { |
| 42 | + el.scrollIntoView({ behavior: "smooth" }); |
45 | 43 | setIsMobileMenuOpen(false); |
46 | 44 | } |
47 | 45 | }; |
48 | 46 |
|
49 | | - // Navigate to a separate page which provides actions (join/create/logout) |
50 | 47 | const handleJoinNow = () => { |
51 | | - if (!user) { |
52 | | - navigate("/signin"); |
53 | | - } else { |
54 | | - navigate("/room-actions"); |
55 | | - } |
| 48 | + if (!user) navigate("/signin"); |
| 49 | + else navigate("/room-actions"); |
56 | 50 | }; |
57 | 51 |
|
58 | 52 | const handleLogout = () => { |
59 | 53 | localStorage.removeItem("token"); |
60 | 54 | setUser(null); |
61 | | - setIsDropdownOpen(false); |
62 | 55 | navigate("/"); |
63 | 56 | }; |
64 | 57 |
|
65 | 58 | return ( |
66 | 59 | <header |
67 | 60 | className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${ |
68 | | - isScrolled ? "bg-white/80 backdrop-blur-lg shadow-lg" : "bg-transparent" |
| 61 | + isScrolled |
| 62 | + ? "bg-white/70 backdrop-blur-md shadow-md" |
| 63 | + : "bg-transparent" |
69 | 64 | }`} |
70 | 65 | > |
71 | | - <nav className="container mx-auto px-6 py-4"> |
72 | | - <div className="flex items-center justify-between"> |
73 | | - <a href="/" className="text-2xl font-bold text-green-600 bg-clip-text"> |
74 | | - PeerCall |
75 | | - </a> |
| 66 | + <nav |
| 67 | + className={`flex items-center justify-between w-full px-4 sm:px-6 py-3 md:py-4 max-w-[100vw] mx-auto`} |
| 68 | +> |
| 69 | + {/* Logo aligned to extreme left */} |
| 70 | + <a |
| 71 | + href="/" |
| 72 | + className="text-2xl md:text-3xl font-extrabold text-green-600 tracking-tight" |
| 73 | + > |
| 74 | + PeerCall |
| 75 | + </a> |
76 | 76 |
|
77 | | - {/* Desktop Navigation */} |
78 | | - <div className="hidden md:flex items-center gap-8 relative"> |
79 | | - <button |
80 | | - onClick={() => scrollToSection("features")} |
81 | | - className="text-gray-900 hover:text-green-600 transition-colors font-medium" |
82 | | - > |
83 | | - Features |
84 | | - </button> |
85 | | - <button |
86 | | - onClick={() => scrollToSection("tech-stack")} |
87 | | - className="text-gray-900 hover:text-green-600 transition-colors font-medium" |
88 | | - > |
89 | | - Tech Stack |
90 | | - </button> |
91 | | - <div className="relative"> |
92 | | - <Button |
93 | | - size="default" |
94 | | - className="bg-green-600 text-white hover:bg-green-700 flex items-center gap-2" |
95 | | - onClick={handleJoinNow} |
96 | | - > |
97 | | - Join Now |
98 | | - </Button> |
99 | | - </div> |
100 | | - </div> |
| 77 | + {/* Desktop Navigation */} |
| 78 | + <div className="hidden md:flex items-center gap-8"> |
| 79 | + <button |
| 80 | + onClick={() => scrollToSection("features")} |
| 81 | + className="text-gray-800 hover:text-green-600 transition-colors font-medium" |
| 82 | + > |
| 83 | + Features |
| 84 | + </button> |
| 85 | + <button |
| 86 | + onClick={() => scrollToSection("tech-stack")} |
| 87 | + className="text-gray-800 hover:text-green-600 transition-colors font-medium" |
| 88 | + > |
| 89 | + Tech Stack |
| 90 | + </button> |
| 91 | + |
| 92 | + {user ? ( |
| 93 | + <div className="flex items-center gap-4"> |
| 94 | + <span className="text-gray-700 font-medium"> |
| 95 | + Hi, {user.name.split(" ")[0]} |
| 96 | + </span> |
| 97 | + <Button |
| 98 | + onClick={handleLogout} |
| 99 | + variant="outline" |
| 100 | + className="border-green-600 text-green-600 hover:bg-green-50" |
| 101 | + > |
| 102 | + Logout |
| 103 | + </Button> |
| 104 | + </div> |
| 105 | + ) : ( |
| 106 | + <Button |
| 107 | + onClick={handleJoinNow} |
| 108 | + className="bg-green-600 text-white hover:bg-green-700" |
| 109 | + > |
| 110 | + Join Now |
| 111 | + </Button> |
| 112 | + )} |
| 113 | + </div> |
| 114 | + |
| 115 | + {/* Mobile Menu Button */} |
| 116 | + <button |
| 117 | + className="md:hidden text-gray-800 focus:outline-none" |
| 118 | + onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} |
| 119 | + aria-label="Toggle menu" |
| 120 | + > |
| 121 | + {isMobileMenuOpen ? <X size={26} /> : <Menu size={26} />} |
| 122 | + </button> |
| 123 | +</nav> |
101 | 124 |
|
102 | | - {/* Mobile Menu Button */} |
| 125 | + |
| 126 | + {/* Mobile Menu */} |
| 127 | + <div |
| 128 | + className={`md:hidden absolute top-full left-0 right-0 bg-white/95 backdrop-blur-md shadow-lg transform transition-all duration-300 origin-top ${ |
| 129 | + isMobileMenuOpen |
| 130 | + ? "opacity-100 scale-y-100 visible" |
| 131 | + : "opacity-0 scale-y-0 invisible" |
| 132 | + }`} |
| 133 | + > |
| 134 | + <div className="flex flex-col px-6 py-4 space-y-4"> |
103 | 135 | <button |
104 | | - className="md:hidden text-gray-900" |
105 | | - onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} |
106 | | - aria-label="Toggle menu" |
| 136 | + onClick={() => scrollToSection("features")} |
| 137 | + className="text-gray-800 hover:text-green-600 text-lg text-left font-medium" |
107 | 138 | > |
108 | | - {isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />} |
| 139 | + Features |
| 140 | + </button> |
| 141 | + <button |
| 142 | + onClick={() => scrollToSection("tech-stack")} |
| 143 | + className="text-gray-800 hover:text-green-600 text-lg text-left font-medium" |
| 144 | + > |
| 145 | + Tech Stack |
109 | 146 | </button> |
110 | | - </div> |
111 | 147 |
|
112 | | - {/* Mobile Navigation */} |
113 | | - {isMobileMenuOpen && ( |
114 | | - <div className="md:hidden mt-4 pb-4 space-y-4 animate-fade-in"> |
115 | | - <button |
116 | | - onClick={() => scrollToSection("features")} |
117 | | - className="block w-full text-left text-gray-900 hover:text-green-600 transition-colors font-medium py-2" |
118 | | - > |
119 | | - Features |
120 | | - </button> |
121 | | - <button |
122 | | - onClick={() => scrollToSection("tech-stack")} |
123 | | - className="block w-full text-left text-gray-900 hover:text-green-600 transition-colors font-medium py-2" |
124 | | - > |
125 | | - Tech Stack |
126 | | - </button> |
| 148 | + {user ? ( |
| 149 | + <> |
| 150 | + <span className="text-gray-700 font-medium"> |
| 151 | + Hello, {user.name.split(" ")[0]} |
| 152 | + </span> |
| 153 | + <Button |
| 154 | + onClick={handleLogout} |
| 155 | + variant="outline" |
| 156 | + className="border-green-600 text-green-600 hover:bg-green-50" |
| 157 | + > |
| 158 | + Logout |
| 159 | + </Button> |
| 160 | + </> |
| 161 | + ) : ( |
127 | 162 | <Button |
128 | | - size="default" |
129 | | - className="w-full bg-green-600 text-white hover:bg-green-700 flex items-center justify-center gap-2" |
130 | 163 | onClick={handleJoinNow} |
| 164 | + className="bg-green-600 text-white hover:bg-green-700 w-full" |
131 | 165 | > |
132 | 166 | Join Now |
133 | 167 | </Button> |
134 | | - {/* mobile: action buttons moved to /room-actions page */} |
135 | | - </div> |
136 | | - )} |
137 | | - </nav> |
| 168 | + )} |
| 169 | + </div> |
| 170 | + </div> |
138 | 171 | </header> |
139 | 172 | ); |
140 | 173 | } |
|
0 commit comments