adding base project
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Menu, Search, Bell, User as UserIcon, LogOut, ShieldCheck, ChevronDown } from 'lucide-react';
|
||||
import { useAuth } from '../../context/AuthContext';
|
||||
import { ThemeToggle } from './ThemeToggle';
|
||||
import './layout.css';
|
||||
|
||||
export function Header({ setMobileOpen }) {
|
||||
const { user, logout, isDemoMode } = useAuth();
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
const dropdownRef = useRef(null);
|
||||
|
||||
// Close dropdown on click outside
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event) {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||
setDropdownOpen(false);
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<header className="dashboard-header">
|
||||
{/* Left: Mobile hamburger & Search */}
|
||||
<div className="header-left">
|
||||
<button
|
||||
className="mobile-menu-btn"
|
||||
onClick={() => setMobileOpen(true)}
|
||||
aria-label="Open navigation menu"
|
||||
>
|
||||
<Menu size={22} />
|
||||
</button>
|
||||
|
||||
<div className="header-search">
|
||||
<Search size={18} className="header-search-icon" />
|
||||
<input
|
||||
type="text"
|
||||
className="header-search-input"
|
||||
placeholder="Search workspaces, logs, users..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Actions, Theme, User */}
|
||||
<div className="header-right">
|
||||
{/* Backend Connectivity Status Badge */}
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '6px',
|
||||
fontSize: '0.8rem',
|
||||
padding: '4px 10px',
|
||||
borderRadius: 'var(--radius-full)',
|
||||
background: isDemoMode ? 'var(--color-warning-bg)' : 'var(--color-success-bg)',
|
||||
color: isDemoMode ? 'var(--color-warning)' : 'var(--color-success)',
|
||||
border: `1px solid ${isDemoMode ? 'rgba(245, 158, 11, 0.3)' : 'rgba(16, 185, 129, 0.3)'}`,
|
||||
}}
|
||||
title={isDemoMode ? 'Running in Standalone Demo Mode' : 'Connected to Spring Boot API'}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
width: 7,
|
||||
height: 7,
|
||||
borderRadius: '50%',
|
||||
backgroundColor: isDemoMode ? 'var(--color-warning)' : 'var(--color-success)',
|
||||
}}
|
||||
/>
|
||||
<span>{isDemoMode ? 'Demo Sandbox' : 'Backend Live'}</span>
|
||||
</div>
|
||||
|
||||
{/* Theme Switcher */}
|
||||
<ThemeToggle />
|
||||
|
||||
{/* Notifications */}
|
||||
<button className="header-btn" title="Recent security alerts">
|
||||
<Bell size={18} />
|
||||
<span className="header-badge-dot" />
|
||||
</button>
|
||||
|
||||
{/* User Dropdown */}
|
||||
<div className="profile-dropdown-wrapper" ref={dropdownRef}>
|
||||
<button
|
||||
className="profile-trigger-btn"
|
||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
||||
aria-expanded={dropdownOpen}
|
||||
>
|
||||
<div className="sidebar-user-avatar" style={{ width: 30, height: 30, fontSize: '0.75rem' }}>
|
||||
{(user?.firstName?.[0] || 'A')}
|
||||
</div>
|
||||
<span style={{ fontSize: '0.85rem', fontWeight: 600 }}>
|
||||
{user?.firstName || 'User'}
|
||||
</span>
|
||||
<ChevronDown size={14} color="var(--text-muted)" />
|
||||
</button>
|
||||
|
||||
{dropdownOpen && (
|
||||
<div className="profile-dropdown-menu animate-fade-in">
|
||||
<div style={{ padding: '8px 12px', borderBottom: '1px solid var(--border-subtle)' }}>
|
||||
<p style={{ fontSize: '0.825rem', fontWeight: 700 }}>{user?.fullname || user?.firstName}</p>
|
||||
<p style={{ fontSize: '0.75rem', color: 'var(--text-muted)' }}>{user?.email}</p>
|
||||
</div>
|
||||
|
||||
<div className="dropdown-item" onClick={() => setDropdownOpen(false)}>
|
||||
<UserIcon size={16} />
|
||||
<span>Profile Settings</span>
|
||||
</div>
|
||||
<div className="dropdown-item" onClick={() => setDropdownOpen(false)}>
|
||||
<ShieldCheck size={16} />
|
||||
<span>Security Token Info</span>
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item danger"
|
||||
onClick={() => {
|
||||
setDropdownOpen(false);
|
||||
logout();
|
||||
}}
|
||||
>
|
||||
<LogOut size={16} />
|
||||
<span>Sign Out</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user