Remove standalone Network page, add as future tab on Infrastructure

Drop the /network route, page, and sidebar entry. Network will instead
become a tab alongside Overview on the Infrastructure page later, so add
a disabled placeholder tab for now.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
This commit is contained in:
Claude 2026-06-18 18:02:09 +00:00
parent f29bce550f
commit 106af334a3
No known key found for this signature in database
5 changed files with 18 additions and 388 deletions

View file

@ -4,7 +4,6 @@ import Sidebar from './components/Sidebar'
import TopBar from './components/TopBar'
import Glance from './pages/Glance'
import Infrastructure from './pages/Infrastructure'
import Network from './pages/Network'
function App() {
const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
@ -56,7 +55,6 @@ function App() {
<Routes>
<Route path="/" element={<Glance />} />
<Route path="/infrastructure" element={<Infrastructure />} />
<Route path="/network" element={<Network />} />
</Routes>
</section>
</main>

View file

@ -2,7 +2,6 @@ import { useLocation, Link } from 'react-router-dom'
import {
LayoutGrid,
Server,
Globe,
Bookmark,
Terminal,
Settings,
@ -18,7 +17,6 @@ interface SidebarProps {
const navItems = [
{ icon: LayoutGrid, label: 'Glance', route: '/' },
{ icon: Server, label: 'Infrastructure', route: '/infrastructure' },
{ icon: Globe, label: 'Network', route: '/network' },
{ icon: Bookmark, label: 'BookNest', route: '/booknest' },
{ icon: Terminal, label: 'Terminal', route: '/terminal' },
{ icon: Settings, label: 'Settings', route: '/settings' },

View file

@ -5,7 +5,6 @@ import { Search, Bell, ChevronDown, User, Palette, LogOut, Shield, HelpCircle }
const pageTitles: Record<string, string> = {
'/': 'Glance',
'/infrastructure': 'Infrastructure',
'/network': 'Network',
'/booknest': 'BookNest',
'/terminal': 'Terminal',
'/settings': 'Settings',

View file

@ -3,6 +3,7 @@ import { PieChart, Pie, Cell, ResponsiveContainer, LineChart, Line, XAxis } from
import { Plus, Server, Activity, AlertTriangle, DollarSign } from 'lucide-react'
const subTabs = ['Overview']
const futureSubTabs = ['Network']
const statusCards = [
{ label: 'Total Resources', value: '128', icon: Server, sub: '+4 this week' },
@ -174,6 +175,23 @@ export default function Infrastructure() {
</button>
)
})}
{futureSubTabs.map((tab) => (
<button
key={tab}
disabled
title="Coming soon"
className="cursor-not-allowed bg-transparent border-none whitespace-nowrap"
style={{
fontSize: '12px',
fontWeight: 500,
padding: '8px 14px',
borderRadius: '8px',
color: '#4A4D55',
}}
>
{tab}
</button>
))}
</div>
<button
className="flex items-center gap-2 cursor-pointer transition-colors whitespace-nowrap"

View file

@ -1,383 +0,0 @@
import { useState } from 'react'
import { PieChart, Pie, Cell, ResponsiveContainer, AreaChart, Area, XAxis } from 'recharts'
import { Activity, Gauge, ShieldAlert, Radio, Zap, Download, ChevronDown, Globe2 } from 'lucide-react'
const subTabs = ['Overview']
const statusCards = [
{ label: 'Network Health', value: '98.7%', icon: Activity, sub: '↑ 2.3% yesterday', color: '#2ECC71' },
{ label: 'Total Traffic', value: '1.23 Tbps', icon: Radio, sub: '↑ 18.6% yesterday' },
{ label: 'Packet Loss', value: '0.02%', icon: Gauge, sub: '↓ 0.01% yesterday', color: '#2ECC71' },
{ label: 'Active Connections', value: '28,457', icon: Zap, sub: '↑ 6.7% yesterday' },
{ label: 'Threats Blocked', value: '152', icon: ShieldAlert, sub: '↑ 12.4% yesterday', color: '#E67E22' },
{ label: 'Avg. Latency', value: '12.4 ms', icon: Activity, sub: '↓ 8.1% yesterday', color: '#2ECC71' },
]
const topTalkers = [
{ name: 'web-app-01', rate: '203.4 Gbps' },
{ name: 'db-primary', rate: '156.7 Gbps' },
{ name: 'cache-cluster', rate: '98.3 Gbps' },
{ name: 'api-gateway', rate: '76.1 Gbps' },
{ name: 'backup-server', rate: '54.8 Gbps' },
]
const regions = [
{ name: 'us-east-1', x: '22%', y: '38%', status: 'live' },
{ name: 'us-west-2', x: '12%', y: '42%', status: 'live' },
{ name: 'eu-west-1', x: '48%', y: '30%', status: 'warning' },
{ name: 'ap-southeast-1', x: '78%', y: '58%', status: 'live' },
{ name: 'sa-east-1', x: '32%', y: '72%', status: 'live' },
{ name: 'ap-northeast-1', x: '85%', y: '40%', status: 'critical' },
]
const regionStatusColor: Record<string, string> = {
live: '#2ECC71',
warning: '#E67E22',
critical: '#E74C3C',
}
const interfaces = [
{ name: 'ethernet1/1', percentage: 85 },
{ name: 'ethernet1/2', percentage: 72 },
{ name: 'ethernet1/3', percentage: 68 },
{ name: 'ethernet1/4', percentage: 55 },
{ name: 'ethernet1/5', percentage: 48 },
]
const alertSummary = [
{ label: 'Critical', value: 2, color: '#E74C3C' },
{ label: 'Warning', value: 5, color: '#E67E22' },
{ label: 'Info', value: 12, color: '#2ECC71' },
]
const trafficData = Array.from({ length: 12 }, (_, i) => ({
hour: i * 2,
inbound: 500 + i * 40 + Math.sin(i / 2) * 60,
outbound: 350 + i * 30 + Math.cos(i / 3) * 50,
total: 900 + i * 60 + Math.sin(i / 2.5) * 80,
}))
const protocolData = [
{ name: 'TCP', value: 65, color: '#C8A434' },
{ name: 'UDP', value: 19, color: '#E67E22' },
{ name: 'ICMP', value: 7, color: '#2ECC71' },
{ name: 'DNS', value: 4, color: '#7A7D85' },
{ name: 'Others', value: 5, color: '#3B82F6' },
]
const recentEvents = [
{ title: 'ethernet1/2 UP', source: 'Interface restored', time: '2m ago' },
{ title: 'High bandwidth detected', source: 'web-app-01', time: '8m ago' },
{ title: 'New device joined', source: '10.0.1.45', time: '15m ago' },
{ title: 'VPN tunnel established', source: 'us-west-2', time: '22m ago' },
{ title: 'Blocked threat', source: '185.199.108.153', time: '35m ago' },
]
const cardBase: React.CSSProperties = {
backgroundColor: 'rgba(10, 10, 12, 0.92)',
border: '1px solid rgba(200, 164, 52, 0.08)',
borderRadius: '12px',
padding: '20px',
boxShadow: '0 0 20px rgba(200, 164, 52, 0.03)',
transition: 'border-color 0.2s ease',
position: 'relative',
overflow: 'hidden',
height: '100%',
display: 'flex',
flexDirection: 'column',
}
const sectionTitle: React.CSSProperties = {
fontSize: '11px',
textTransform: 'uppercase',
letterSpacing: '1.5px',
color: '#7A7D85',
fontWeight: 500,
marginBottom: '16px',
}
function framedCard(bgUrl: string): React.CSSProperties {
return {
backgroundImage: `url(${bgUrl})`,
backgroundSize: '100% 100%',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
position: 'relative',
overflow: 'hidden',
height: '100%',
display: 'flex',
flexDirection: 'column',
padding: '20px 20px 64px 20px',
}
}
const cardVignette: React.CSSProperties = {
position: 'absolute',
inset: 0,
pointerEvents: 'none',
background: 'radial-gradient(ellipse closest-side at center, transparent 70%, var(--color-page) 100%)',
}
const cardDim: React.CSSProperties = {
position: 'absolute',
inset: 0,
pointerEvents: 'none',
backgroundColor: 'rgba(8, 8, 10, 0.45)',
}
function Donut({ data, centerLabel }: { data: { name: string; value: number; color: string }[]; centerLabel?: string }) {
return (
<div className="flex flex-1 items-center gap-4">
<div className="relative" style={{ width: '120px', height: '120px', flexShrink: 0 }}>
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie data={data} dataKey="value" innerRadius={38} outerRadius={56} paddingAngle={2} isAnimationActive animationDuration={1000}>
{data.map((entry) => (
<Cell key={entry.name} fill={entry.color} stroke="none" />
))}
</Pie>
</PieChart>
</ResponsiveContainer>
{centerLabel && (
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
<span style={{ fontSize: '18px', fontWeight: 700, color: '#E8E6E0' }}>{centerLabel}</span>
</div>
)}
</div>
<div className="flex flex-col gap-2">
{data.map((entry) => (
<div key={entry.name} className="flex items-center gap-2">
<span style={{ width: '8px', height: '8px', borderRadius: '50%', backgroundColor: entry.color, flexShrink: 0 }} />
<span style={{ fontSize: '12px', color: '#E8E6E0', width: '60px' }}>{entry.name}</span>
<span style={{ fontSize: '12px', color: '#7A7D85' }}>{entry.value}%</span>
</div>
))}
</div>
</div>
)
}
export default function Network() {
const [activeTab, setActiveTab] = useState('Overview')
return (
<>
{/* Sub-tabs + Actions */}
<div className="flex items-center justify-between shrink-0">
<div className="flex items-center gap-1 overflow-x-auto" style={{ scrollbarWidth: 'none' }}>
{subTabs.map((tab) => {
const active = tab === activeTab
return (
<button
key={tab}
onClick={() => setActiveTab(tab)}
className="cursor-pointer bg-transparent border-none transition-colors whitespace-nowrap"
style={{
fontSize: '12px',
fontWeight: 500,
padding: '8px 14px',
borderRadius: '8px',
color: active ? '#C8A434' : '#7A7D85',
backgroundColor: active ? 'rgba(200,164,52,0.1)' : 'transparent',
}}
>
{tab}
</button>
)
})}
</div>
<div className="flex items-center gap-3">
<button
className="flex items-center gap-2 cursor-pointer transition-colors whitespace-nowrap"
style={{
fontSize: '12px',
fontWeight: 500,
color: '#E8E6E0',
backgroundColor: 'rgba(255,255,255,0.04)',
border: '1px solid rgba(200,164,52,0.12)',
borderRadius: '8px',
padding: '9px 14px',
}}
>
Last 24 Hours
<ChevronDown size={13} />
</button>
<button
className="flex items-center gap-2 cursor-pointer transition-colors whitespace-nowrap"
style={{
fontSize: '12px',
fontWeight: 600,
color: '#0A0B0D',
backgroundColor: '#C8A434',
border: 'none',
borderRadius: '8px',
padding: '9px 16px',
boxShadow: '0 0 14px rgba(200,164,52,0.2)',
}}
>
<Download size={14} />
Export Report
</button>
</div>
</div>
{/* Status Cards */}
<div className="grid w-full grid-cols-6 gap-4 shrink-0" style={{ marginTop: '8px', height: '110px' }}>
{statusCards.map((card) => {
const Icon = card.icon
return (
<div
key={card.label}
style={{ ...cardBase, backgroundColor: 'rgba(10, 10, 12, 0.5)', padding: '14px', justifyContent: 'center', alignItems: 'center', gap: '8px' }}
className="hover:!border-gold/20"
>
<h3 style={{ fontSize: '9.5px', textTransform: 'uppercase', letterSpacing: '1.2px', color: '#7A7D85', fontWeight: 500, textAlign: 'center' }}>
{card.label}
</h3>
<div className="flex items-center gap-1.5">
<Icon size={16} style={{ color: card.color ?? '#C8A434' }} />
<span style={{ fontSize: '20px', fontWeight: 700, color: '#E8E6E0', lineHeight: 1 }}>{card.value}</span>
</div>
<p style={{ fontSize: '9.5px', color: card.color ?? '#7A7D85', textAlign: 'center' }}>{card.sub}</p>
</div>
)
})}
</div>
{/* Middle Row */}
<div className="min-h-0 flex-1">
<div className="grid h-full w-full grid-cols-[1fr_2fr_1fr] gap-6">
{/* Top Talkers */}
<div style={{ ...cardBase }} className="hover:!border-gold/15">
<div className="relative z-10 flex flex-1 flex-col">
<h3 style={sectionTitle}>Top Talkers</h3>
<div className="flex flex-1 flex-col justify-around gap-3">
{topTalkers.map((t) => (
<div key={t.name} className="flex items-center justify-between">
<span style={{ fontSize: '12px', color: '#E8E6E0' }}>{t.name}</span>
<span style={{ fontSize: '11px', color: '#C8A434', fontWeight: 600 }}>{t.rate}</span>
</div>
))}
</div>
</div>
</div>
{/* Network Topology */}
<div style={framedCard('/network-kpi-bg.png')}>
<div style={cardDim} />
<div style={cardVignette} />
<div className="relative z-10 flex flex-1 flex-col">
<div className="flex items-center justify-between">
<h3 style={{ ...sectionTitle, marginBottom: 0 }}>Network Topology</h3>
<div className="flex items-center gap-3" style={{ fontSize: '10px', color: '#7A7D85' }}>
<span className="flex items-center gap-1"><span style={{ width: '6px', height: '6px', borderRadius: '50%', backgroundColor: '#2ECC71' }} />Live</span>
<span className="flex items-center gap-1"><span style={{ width: '6px', height: '6px', borderRadius: '50%', backgroundColor: '#E67E22' }} />Warning</span>
<span className="flex items-center gap-1"><span style={{ width: '6px', height: '6px', borderRadius: '50%', backgroundColor: '#E74C3C' }} />Critical</span>
</div>
</div>
<div className="relative flex-1" style={{ minHeight: '140px', marginTop: '12px' }}>
<Globe2 size={170} strokeWidth={0.6} style={{ position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)', color: 'rgba(200,164,52,0.1)' }} />
{regions.map((r) => (
<div key={r.name} className="absolute" style={{ left: r.x, top: r.y, transform: 'translate(-50%, -50%)' }} title={r.name}>
<div style={{ width: '8px', height: '8px', borderRadius: '50%', backgroundColor: regionStatusColor[r.status], boxShadow: `0 0 10px ${regionStatusColor[r.status]}` }} />
</div>
))}
</div>
</div>
</div>
{/* Interface Utilization + Alert Summary, stacked */}
<div className="flex h-full flex-col gap-6">
<div style={{ ...cardBase, height: 'auto', flex: 1 }} className="hover:!border-gold/15">
<h3 style={sectionTitle}>Interface Utilization</h3>
<div className="flex flex-1 flex-col justify-around gap-2.5">
{interfaces.map((iface) => (
<div key={iface.name}>
<div className="flex items-center justify-between mb-1">
<span style={{ fontSize: '11px', color: '#E8E6E0' }}>{iface.name}</span>
<span style={{ fontSize: '10px', color: '#7A7D85' }}>{iface.percentage}%</span>
</div>
<div style={{ height: '5px', backgroundColor: 'rgba(30,32,37,0.8)', borderRadius: '3px', overflow: 'hidden' }}>
<div style={{ height: '100%', width: `${iface.percentage}%`, backgroundColor: '#C8A434', borderRadius: '3px', transition: 'width 0.8s ease' }} />
</div>
</div>
))}
</div>
</div>
<div style={{ ...cardBase, height: 'auto', flex: 1 }} className="hover:!border-gold/15">
<h3 style={sectionTitle}>Alert Summary</h3>
<div className="flex flex-1 items-center justify-around">
{alertSummary.map((a) => (
<div key={a.label} className="flex flex-col items-center gap-1">
<span style={{ fontSize: '22px', fontWeight: 700, color: a.color }}>{a.value}</span>
<span style={{ fontSize: '10px', color: '#7A7D85' }}>{a.label}</span>
</div>
))}
</div>
</div>
</div>
</div>
</div>
{/* Bottom Row */}
<div className="shrink-0">
<div className="grid w-full grid-cols-[1.4fr_1fr_1fr] gap-6">
{/* Traffic Over Time */}
<div style={{ ...cardBase, height: 'auto' }} className="hover:!border-gold/15">
<h3 style={sectionTitle}>Traffic Over Time</h3>
<div style={{ height: '100px' }}>
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={trafficData} margin={{ top: 0, right: 0, left: 0, bottom: 0 }}>
<XAxis dataKey="hour" hide />
<Area type="monotone" dataKey="total" stroke="#7A7D85" fill="rgba(122,125,133,0.08)" strokeWidth={1} dot={false} isAnimationActive animationDuration={1000} />
<Area type="monotone" dataKey="inbound" stroke="#C8A434" fill="rgba(200,164,52,0.12)" strokeWidth={1.5} dot={false} isAnimationActive animationDuration={1000} />
<Area type="monotone" dataKey="outbound" stroke="#E67E22" fill="rgba(230,126,34,0.1)" strokeWidth={1.5} dot={false} isAnimationActive animationDuration={1000} />
</AreaChart>
</ResponsiveContainer>
</div>
</div>
{/* Protocol Distribution */}
<div style={{ ...cardBase, height: 'auto' }} className="hover:!border-gold/15">
<h3 style={sectionTitle}>Protocol Distribution</h3>
<Donut data={protocolData} centerLabel="1.23 Tbps" />
</div>
{/* Recent Events */}
<div style={{ ...cardBase, height: 'auto' }} className="hover:!border-gold/15">
<h3 style={sectionTitle}>Recent Events</h3>
<div className="flex flex-col gap-3">
{recentEvents.map((item, i) => (
<div key={i} className="flex items-start justify-between gap-3">
<div style={{ flex: 1, minWidth: 0 }}>
<p style={{ fontSize: '12px', color: '#E8E6E0', fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{item.title}</p>
<p style={{ fontSize: '11px', color: '#7A7D85', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{item.source}</p>
</div>
<span style={{ fontSize: '11px', color: '#7A7D85', flexShrink: 0 }}>{item.time}</span>
</div>
))}
</div>
</div>
</div>
</div>
{/* Footer stats bar */}
<div
className="shrink-0 flex items-center justify-center gap-3"
style={{
fontSize: '11px',
color: '#7A7D85',
padding: '8px 0',
borderTop: '1px solid rgba(200,164,52,0.08)',
}}
>
<span>6 Regions</span><span style={{ color: 'rgba(200,164,52,0.3)' }}>|</span>
<span>42 Sites</span><span style={{ color: 'rgba(200,164,52,0.3)' }}>|</span>
<span>248 Devices</span><span style={{ color: 'rgba(200,164,52,0.3)' }}>|</span>
<span>1,245 Interfaces</span><span style={{ color: 'rgba(200,164,52,0.3)' }}>|</span>
<span>28,457 Connections</span><span style={{ color: 'rgba(200,164,52,0.3)' }}>|</span>
<span style={{ color: '#2ECC71' }}>98.7% Health</span>
</div>
</>
)
}