Base UI design, May contain bugs
This commit is contained in:
63
frontend/src/components/Navbar.jsx
Normal file
63
frontend/src/components/Navbar.jsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import UserDropdown from './UserDropdown';
|
||||
import { Search, Heart } from 'lucide-react';
|
||||
|
||||
const Navbar = ({ onLogout, userName }) => {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const handleSearchChange = (e) => {
|
||||
setSearchQuery(e.target.value);
|
||||
};
|
||||
|
||||
const handleSearchSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
console.log('Searching for:', searchQuery);
|
||||
// TODO: Implement search functionality
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="bg-white shadow-sm border-b border-gray-200">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
{/* Logo */}
|
||||
<div className="flex-shrink-0">
|
||||
<Link to="/" className="flex items-center">
|
||||
<span className="text-green-600 font-bold text-xl">Campus Plug</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Search Bar */}
|
||||
<div className="flex-1 max-w-2xl px-4">
|
||||
<form onSubmit={handleSearchSubmit} className="w-full">
|
||||
<div className="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search for books, electronics, furniture..."
|
||||
className="w-full p-2 pl-10 pr-4 border border-gray-300 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<Search className="h-5 w-5 text-gray-400" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/* User Navigation */}
|
||||
<div className="flex items-center space-x-4">
|
||||
{/* Favorites Button */}
|
||||
<Link to="/favorites" className="p-2 text-gray-600 hover:text-green-600">
|
||||
<Heart className="h-6 w-6" />
|
||||
</Link>
|
||||
{/* User Profile */}
|
||||
<UserDropdown onLogout={onLogout} userName={userName} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navbar;
|
||||
106
frontend/src/components/UserDropdown.jsx
Normal file
106
frontend/src/components/UserDropdown.jsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { User, Settings, ShoppingBag, DollarSign, LogOut } from 'lucide-react';
|
||||
|
||||
const UserDropdown = ({ onLogout, userName }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const dropdownRef = useRef(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Use passed userName or fallback to default
|
||||
const displayName = userName || 'User';
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleLogout = () => {
|
||||
// Close the dropdown
|
||||
setIsOpen(false);
|
||||
|
||||
// Call the onLogout function from props
|
||||
if (onLogout) {
|
||||
onLogout();
|
||||
console.log("Logout successful");
|
||||
}
|
||||
|
||||
// Navigate to login page (this may be redundant as App.jsx should handle redirection)
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<button
|
||||
className="flex items-center focus:outline-none"
|
||||
onClick={toggleDropdown}
|
||||
>
|
||||
<div className="h-8 w-8 rounded-full bg-green-100 flex items-center justify-center">
|
||||
<User className="h-5 w-5 text-green-600" />
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
<div className="absolute right-0 mt-2 w-48 bg-white border border-gray-200 shadow-md z-10">
|
||||
{/* User Info */}
|
||||
<div className="px-4 py-3 border-b border-gray-100">
|
||||
<p className="text-sm font-medium text-gray-900">{displayName}</p>
|
||||
</div>
|
||||
|
||||
{/* Navigation Links */}
|
||||
<div className="py-1">
|
||||
<Link
|
||||
to="/selling"
|
||||
className="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
<ShoppingBag className="h-4 w-4 mr-2 text-gray-500" />
|
||||
My Listings
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/transactions"
|
||||
className="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
<DollarSign className="h-4 w-4 mr-2 text-gray-500" />
|
||||
Transactions
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/settings"
|
||||
className="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
<Settings className="h-4 w-4 mr-2 text-gray-500" />
|
||||
Settings
|
||||
</Link>
|
||||
|
||||
<button
|
||||
className="flex w-full items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
||||
onClick={handleLogout}
|
||||
>
|
||||
<LogOut className="h-4 w-4 mr-2 text-gray-500" />
|
||||
Log out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserDropdown;
|
||||
Reference in New Issue
Block a user