Add src/components/dashboard/TopBar.jsx
This commit is contained in:
parent
b1d89f1e47
commit
312ac7ab85
|
|
@ -0,0 +1,140 @@
|
||||||
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
|
import { Search, Bell, ChevronDown, User, Mail, LogOut } from "lucide-react";
|
||||||
|
|
||||||
|
export default function TopBar({ breadcrumb, userData }) {
|
||||||
|
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
||||||
|
const [notifOpen, setNotifOpen] = useState(false);
|
||||||
|
const userRef = useRef(null);
|
||||||
|
const notifRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClick = (e) => {
|
||||||
|
if (userRef.current && !userRef.current.contains(e.target)) setUserMenuOpen(false);
|
||||||
|
if (notifRef.current && !notifRef.current.contains(e.target)) setNotifOpen(false);
|
||||||
|
};
|
||||||
|
document.addEventListener("mousedown", handleClick);
|
||||||
|
return () => document.removeEventListener("mousedown", handleClick);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header id="topbar" className="h-14 bg-white border-b border-gray-200 flex items-center justify-between px-6 sticky top-0 z-20">
|
||||||
|
{/* Left - Breadcrumb */}
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<span className="text-[#2980b9] hover:underline cursor-pointer font-medium">Homepage</span>
|
||||||
|
<span className="text-gray-400">/</span>
|
||||||
|
<span className="font-medium text-gray-700">{breadcrumb}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Center - Search */}
|
||||||
|
<div className="hidden md:flex items-center max-w-md w-full mx-8">
|
||||||
|
<div className="relative w-full">
|
||||||
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search..."
|
||||||
|
className="w-full h-9 pl-10 pr-4 bg-gray-50 border border-gray-200 rounded-lg text-sm focus:outline-none focus:border-[#3498db] focus:ring-1 focus:ring-[#3498db] transition-all"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right - Notifications + User */}
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
{/* Notifications */}
|
||||||
|
<div ref={notifRef} className="relative">
|
||||||
|
<button
|
||||||
|
id="notifications-btn"
|
||||||
|
onClick={() => setNotifOpen(!notifOpen)}
|
||||||
|
className="relative w-10 h-10 rounded border border-gray-300 bg-white flex items-center justify-center hover:bg-gray-50 transition-colors shadow-sm"
|
||||||
|
>
|
||||||
|
<Bell className="w-5 h-5 text-gray-600" />
|
||||||
|
<span className="absolute -top-1.5 -right-1.5 min-w-[18px] h-[18px] bg-red-500 text-white text-[10px] font-bold rounded-full flex items-center justify-center px-1">
|
||||||
|
6
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
{notifOpen && (
|
||||||
|
<div className="absolute right-0 top-full mt-2 w-96 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden">
|
||||||
|
<div className="px-4 py-3 border-b border-gray-200 flex items-center justify-between bg-gray-50">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h3 className="font-bold text-gray-800">Alerts</h3>
|
||||||
|
<span className="text-xs bg-gray-200 text-gray-600 px-2 py-0.5 rounded-full font-medium">6 unread</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<label className="flex items-center gap-1.5 text-xs text-gray-500 cursor-pointer">
|
||||||
|
<input type="checkbox" className="w-3 h-3" /> Select all
|
||||||
|
</label>
|
||||||
|
<button className="text-xs bg-white border border-gray-300 text-gray-600 px-2 py-1 rounded flex items-center gap-1">
|
||||||
|
Actions <ChevronDown className="w-3 h-3" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="max-h-80 overflow-y-auto">
|
||||||
|
<div className="m-3 border border-yellow-300 rounded-lg bg-yellow-50 p-3">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex items-center gap-2 mb-1">
|
||||||
|
<span className="text-[10px] font-bold text-gray-500 uppercase tracking-wider">Bulletin</span>
|
||||||
|
<span className="w-2 h-2 bg-blue-500 rounded-full" />
|
||||||
|
</div>
|
||||||
|
<button className="text-gray-400 hover:text-gray-600 text-xs">✕</button>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm font-semibold text-gray-800">Now Available: PBC Marketing Toolbox</p>
|
||||||
|
<p className="text-xs text-gray-600 mt-1 leading-relaxed">The Marketing Toolbox is the dedicated spot to find all kinds of materials, logos and resources.</p>
|
||||||
|
<p className="text-xs text-amber-600 font-semibold mt-2">Action Required</p>
|
||||||
|
</div>
|
||||||
|
<div className="mx-3 mb-3 border border-gray-200 rounded-lg bg-white p-3">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex items-center gap-2 mb-1">
|
||||||
|
<span className="text-[10px] font-bold text-gray-500 uppercase tracking-wider">Bulletin</span>
|
||||||
|
<span className="w-2 h-2 bg-blue-500 rounded-full" />
|
||||||
|
</div>
|
||||||
|
<button className="text-gray-400 hover:text-gray-600 text-xs">✕</button>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm font-semibold text-gray-800">Now Available: Contact Us</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* User Menu */}
|
||||||
|
<div ref={userRef} className="relative">
|
||||||
|
<button
|
||||||
|
id="user-menu-btn"
|
||||||
|
onClick={() => setUserMenuOpen(!userMenuOpen)}
|
||||||
|
className="flex items-center gap-2 bg-[#2980b9] hover:bg-[#2471a3] text-white px-4 py-2 rounded-md transition-colors shadow-sm text-sm font-semibold"
|
||||||
|
>
|
||||||
|
<User className="w-4 h-4" />
|
||||||
|
<span className="text-sm font-medium max-w-[120px] truncate">
|
||||||
|
{userData?.full_name || "Demo User"}
|
||||||
|
</span>
|
||||||
|
<ChevronDown className="w-3.5 h-3.5" />
|
||||||
|
</button>
|
||||||
|
{userMenuOpen && (
|
||||||
|
<div className="absolute right-0 top-full mt-2 w-64 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden">
|
||||||
|
<div className="px-4 py-3 border-b border-gray-100">
|
||||||
|
<p className="text-sm font-bold text-gray-800 uppercase">{userData?.full_name || "Demo User"}</p>
|
||||||
|
<p className="text-xs text-gray-500">{userData?.email || "demo@example.com"}</p>
|
||||||
|
<div className="mt-2 space-y-1 text-xs text-gray-600">
|
||||||
|
<p><span className="text-gray-400">Store ID:</span> {userData?.store_id || "AA1112"}</p>
|
||||||
|
<p><span className="text-gray-400">Store Name:</span> {userData?.store_name || "Demo Store"}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="py-1">
|
||||||
|
<button id="my-profile-menu" className="flex items-center gap-2 px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-50 w-full">
|
||||||
|
<User className="w-4 h-4 text-gray-400" /> My Profile
|
||||||
|
</button>
|
||||||
|
<button className="flex items-center gap-2 px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-50 w-full">
|
||||||
|
<Mail className="w-4 h-4 text-gray-400" /> Contact Us
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-gray-100 py-1">
|
||||||
|
<button className="flex items-center gap-2 px-4 py-2.5 text-sm text-red-600 hover:bg-red-50 w-full">
|
||||||
|
<LogOut className="w-4 h-4" /> Logout
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue