Add hamburger nav menu with 4-page navigation structure

- NavDrawer component: slide-in left drawer with backdrop, matches dark theme
- Nav items: Home, Reporting, Knowledge Base, Exports with color-coded icons
- Active page highlighted with colored background + indicator dot
- Placeholder pages for Reporting (amber), Knowledge Base (green), Exports (purple)
- Stats bar and three-column layout conditionally render on Home page only
- currentPage state drives all page switching

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 11:47:03 -06:00
parent d63e7cc9b9
commit ea3b72db5c
5 changed files with 242 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
import { Search, FileText, AlertCircle, Download, Upload, Eye, Filter, CheckCircle, XCircle, Loader, Trash2, Plus, RefreshCw, Edit2, ChevronDown, Shield, Activity } from 'lucide-react';
import { Search, FileText, AlertCircle, Download, Upload, Eye, Filter, CheckCircle, XCircle, Loader, Trash2, Plus, RefreshCw, Edit2, ChevronDown, Shield, Activity, Menu } from 'lucide-react';
import { useAuth } from './contexts/AuthContext';
import LoginForm from './components/LoginForm';
import UserMenu from './components/UserMenu';
@@ -8,6 +8,10 @@ import AuditLog from './components/AuditLog';
import NvdSyncModal from './components/NvdSyncModal';
import KnowledgeBaseModal from './components/KnowledgeBaseModal';
import KnowledgeBaseViewer from './components/KnowledgeBaseViewer';
import NavDrawer from './components/NavDrawer';
import ReportingPage from './components/pages/ReportingPage';
import KnowledgeBasePage from './components/pages/KnowledgeBasePage';
import ExportsPage from './components/pages/ExportsPage';
import './App.css';
const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:3001/api';
@@ -171,6 +175,8 @@ export default function App() {
const [cveDocuments, setCveDocuments] = useState({});
const [quickCheckCVE, setQuickCheckCVE] = useState('');
const [quickCheckResult, setQuickCheckResult] = useState(null);
const [currentPage, setCurrentPage] = useState('home');
const [navOpen, setNavOpen] = useState(false);
const [showAddCVE, setShowAddCVE] = useState(false);
const [showUserManagement, setShowUserManagement] = useState(false);
const [showAuditLog, setShowAuditLog] = useState(false);
@@ -950,6 +956,12 @@ export default function App() {
return (
<div className="min-h-screen bg-intel-darkest grid-bg p-6 relative overflow-hidden fade-in">
<NavDrawer
isOpen={navOpen}
onClose={() => setNavOpen(false)}
currentPage={currentPage}
onNavigate={setCurrentPage}
/>
{/* Scanning line effect */}
<div className="scan-line"></div>
@@ -957,11 +969,22 @@ export default function App() {
{/* Header */}
<div className="mb-8">
<div className="flex justify-between items-start mb-6">
<div className="flex-1">
<h1 className="text-4xl font-bold text-intel-accent mb-1 font-mono tracking-tight">
STEAM Security Dashboard
</h1>
<p className="text-gray-400 text-sm font-sans">NTS Threat Intelligence and Metric Aggregation</p>
<div className="flex items-center gap-4 flex-1">
<button
onClick={() => setNavOpen(true)}
style={{ background: 'none', border: '1px solid rgba(14, 165, 233, 0.25)', borderRadius: '0.375rem', padding: '0.5rem', cursor: 'pointer', color: '#64748B', flexShrink: 0 }}
onMouseEnter={e => { e.currentTarget.style.color = '#0EA5E9'; e.currentTarget.style.borderColor = 'rgba(14, 165, 233, 0.6)'; }}
onMouseLeave={e => { e.currentTarget.style.color = '#64748B'; e.currentTarget.style.borderColor = 'rgba(14, 165, 233, 0.25)'; }}
title="Navigation"
>
<Menu className="w-5 h-5" />
</button>
<div>
<h1 className="text-4xl font-bold text-intel-accent mb-1 font-mono tracking-tight">
STEAM Security Dashboard
</h1>
<p className="text-gray-400 text-sm font-sans">NTS Threat Intelligence and Metric Aggregation</p>
</div>
</div>
<div className="flex items-center gap-3">
{canWrite() && (
@@ -986,8 +1009,8 @@ export default function App() {
</div>
</div>
{/* Stats Bar - Modern refined styling */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
{/* Stats Bar - only shown on Home page */}
{currentPage === 'home' && <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div style={STYLES.statCard}>
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: '2px', background: 'linear-gradient(90deg, transparent, #0EA5E9, transparent)', boxShadow: '0 0 8px rgba(14, 165, 233, 0.5)' }}></div>
<div style={{ fontSize: '0.75rem', textTransform: 'uppercase', letterSpacing: '0.1em', color: '#CBD5E1', marginBottom: '0.25rem' }}>Total CVEs</div>
@@ -1008,9 +1031,14 @@ export default function App() {
<div style={{ fontSize: '0.75rem', textTransform: 'uppercase', letterSpacing: '0.1em', color: '#CBD5E1', marginBottom: '0.25rem' }}>Critical</div>
<div style={{ fontSize: '1.5rem', fontWeight: '700', fontFamily: 'monospace', color: '#EF4444', textShadow: '0 0 16px rgba(239, 68, 68, 0.4)' }}>{cves.filter(c => c.severity === 'Critical').length}</div>
</div>
</div>
</div>}
</div>
{/* Page content */}
{currentPage === 'reporting' && <ReportingPage />}
{currentPage === 'knowledge-base' && <KnowledgeBasePage />}
{currentPage === 'exports' && <ExportsPage />}
{/* User Management Modal */}
{showUserManagement && (
<UserManagement onClose={() => setShowUserManagement(false)} />
@@ -1624,8 +1652,8 @@ export default function App() {
</div>
)}
{/* Three Column Layout */}
<div className="grid grid-cols-12 gap-6">
{/* Three Column Layout - Home page only */}
{currentPage === 'home' && <div className="grid grid-cols-12 gap-6">
{/* LEFT PANEL - Wiki/Knowledge Base */}
<div className="col-span-12 lg:col-span-3 space-y-4">
<div style={{...STYLES.intelCard, padding: '1.5rem', borderLeft: '3px solid #10B981'}} className="rounded-lg">
@@ -2472,7 +2500,7 @@ export default function App() {
</div>
{/* End Right Panel */}
</div>
</div>}
{/* End Three Column Layout */}
</div>
</div>