CodebaseAi commited on
Commit
01b6aad
·
1 Parent(s): ba888f3

mobile way

Browse files
frontend/.gitignore CHANGED
@@ -8,7 +8,7 @@ pnpm-debug.log*
8
  lerna-debug.log*
9
 
10
  node_modules
11
- dist
12
  dist-ssr
13
  *.local
14
 
 
8
  lerna-debug.log*
9
 
10
  node_modules
11
+
12
  dist-ssr
13
  *.local
14
 
frontend/src/App.jsx CHANGED
@@ -1,13 +1,12 @@
1
- import { BrowserRouter as Router, Routes, Route, useLocation, Navigate } from "react-router-dom";
2
  import { LiveDataProvider } from "./context/DataContext";
3
  import { AuthProvider } from "./context/AuthContext";
4
  import ProtectedRoute from "./components/ProtectedRoute";
5
  import Sidebar from "./components/Sidebar";
6
  import { useState } from "react";
 
7
 
8
- // --- IMPORT THE GUARD ---
9
  import FeatureGuard from "./components/FeatureGuard";
10
-
11
  import AuthPage from "./pages/Login";
12
  import Dashboard from "./pages/Dashboard";
13
  import LiveTraffic from "./components/dashboard/LiveDashboard";
@@ -29,41 +28,54 @@ import MainLayout from "./components/MainLayout";
29
  function AppLayout() {
30
  const location = useLocation();
31
  const hideSidebar = location.pathname === "/login";
 
32
  const [collapsed, setCollapsed] = useState(false);
 
33
 
34
- // 🛠️ DEFINE LOCAL-ONLY ROUTES HERE
35
  const localOnlyRoutes = ["/livetraffic", "/flow", "/system", "/traffic"];
36
  const isProtectedFeature = localOnlyRoutes.includes(location.pathname);
37
 
38
  return (
39
- <div className="flex min-h-screen text-slate-100 relative bg-transparent">
40
  <ConstellationBackground />
41
 
42
  {!hideSidebar && (
43
- <Sidebar collapsed={collapsed} setCollapsed={setCollapsed} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  )}
45
 
46
  <main
47
- className={`flex-1 overflow-y-auto overflow-x-hidden p-6 min-h-0 transition-all duration-300
48
- ${collapsed ? "ml-20" : "ml-64"}
 
49
  `}
50
  >
51
- {/* Wrap the Routes in the FeatureGuard.
52
- It will only trigger the popup if the current path is in localOnlyRoutes
53
- AND the user is not on localhost.
54
- */}
55
  <FeatureGuard requireLocal={isProtectedFeature}>
56
  <Routes>
57
  <Route path="/login" element={<AuthPage />} />
58
  <Route path="/" element={<ProtectedRoute><MainLayout><Dashboard /></MainLayout></ProtectedRoute>} />
59
-
60
- {/* These routes will now trigger the popup if deployed */}
61
  <Route path="/livetraffic" element={<ProtectedRoute><MainLayout><LiveTraffic /></MainLayout></ProtectedRoute>} />
62
  <Route path="/flow" element={<ProtectedRoute><MainLayout><FlowPage /></MainLayout></ProtectedRoute>} />
63
  <Route path="/system" element={<ProtectedRoute><MainLayout><SystemPage /></MainLayout></ProtectedRoute>} />
64
  <Route path="/traffic" element={<ProtectedRoute><MainLayout><TrafficPage /></MainLayout></ProtectedRoute>} />
65
-
66
- {/* These routes work fine in the cloud (Database/AI based) */}
67
  <Route path="/settings" element={<ProtectedRoute><MainLayout><SettingsPage /></MainLayout></ProtectedRoute>} />
68
  <Route path="/alerts" element={<ProtectedRoute><MainLayout><InfoPage /></MainLayout></ProtectedRoute>} />
69
  <Route path="/samplepred" element={<ProtectedRoute><MainLayout><SamplePred /></MainLayout></ProtectedRoute>} />
 
1
+ import { BrowserRouter as Router, Routes, Route, useLocation } from "react-router-dom";
2
  import { LiveDataProvider } from "./context/DataContext";
3
  import { AuthProvider } from "./context/AuthContext";
4
  import ProtectedRoute from "./components/ProtectedRoute";
5
  import Sidebar from "./components/Sidebar";
6
  import { useState } from "react";
7
+ import { Menu } from "lucide-react"; // Import Menu icon for mobile
8
 
 
9
  import FeatureGuard from "./components/FeatureGuard";
 
10
  import AuthPage from "./pages/Login";
11
  import Dashboard from "./pages/Dashboard";
12
  import LiveTraffic from "./components/dashboard/LiveDashboard";
 
28
  function AppLayout() {
29
  const location = useLocation();
30
  const hideSidebar = location.pathname === "/login";
31
+
32
  const [collapsed, setCollapsed] = useState(false);
33
+ const [isMobileOpen, setIsMobileOpen] = useState(false); // New state for mobile toggle
34
 
 
35
  const localOnlyRoutes = ["/livetraffic", "/flow", "/system", "/traffic"];
36
  const isProtectedFeature = localOnlyRoutes.includes(location.pathname);
37
 
38
  return (
39
+ <div className="flex min-h-screen text-slate-100 relative bg-transparent overflow-x-hidden">
40
  <ConstellationBackground />
41
 
42
  {!hideSidebar && (
43
+ <>
44
+ {/* Sidebar now receives mobile state props */}
45
+ <Sidebar
46
+ collapsed={collapsed}
47
+ setCollapsed={setCollapsed}
48
+ isMobileOpen={isMobileOpen}
49
+ setIsMobileOpen={setIsMobileOpen}
50
+ />
51
+
52
+ {/* MOBILE HAMBURGER BUTTON (Visible only on mobile) */}
53
+ <button
54
+ onClick={() => setIsMobileOpen(true)}
55
+ className="lg:hidden fixed top-4 left-4 z-[40] p-2 bg-[#0b1120] border border-cyan-500/30 rounded-lg text-cyan-400 shadow-lg"
56
+ >
57
+ <Menu size={24} />
58
+ </button>
59
+ </>
60
  )}
61
 
62
  <main
63
+ className={`flex-1 overflow-y-auto p-4 md:p-6 min-h-0 transition-all duration-300
64
+ /* On mobile: 0 margin. On desktop: match sidebar width */
65
+ ml-0 ${!hideSidebar ? (collapsed ? "lg:ml-20" : "lg:ml-64") : "ml-0"}
66
  `}
67
  >
68
+ {/* Top Spacer for Mobile (Prevents content from being hidden under hamburger) */}
69
+ {!hideSidebar && <div className="h-12 lg:hidden" />}
70
+
 
71
  <FeatureGuard requireLocal={isProtectedFeature}>
72
  <Routes>
73
  <Route path="/login" element={<AuthPage />} />
74
  <Route path="/" element={<ProtectedRoute><MainLayout><Dashboard /></MainLayout></ProtectedRoute>} />
 
 
75
  <Route path="/livetraffic" element={<ProtectedRoute><MainLayout><LiveTraffic /></MainLayout></ProtectedRoute>} />
76
  <Route path="/flow" element={<ProtectedRoute><MainLayout><FlowPage /></MainLayout></ProtectedRoute>} />
77
  <Route path="/system" element={<ProtectedRoute><MainLayout><SystemPage /></MainLayout></ProtectedRoute>} />
78
  <Route path="/traffic" element={<ProtectedRoute><MainLayout><TrafficPage /></MainLayout></ProtectedRoute>} />
 
 
79
  <Route path="/settings" element={<ProtectedRoute><MainLayout><SettingsPage /></MainLayout></ProtectedRoute>} />
80
  <Route path="/alerts" element={<ProtectedRoute><MainLayout><InfoPage /></MainLayout></ProtectedRoute>} />
81
  <Route path="/samplepred" element={<ProtectedRoute><MainLayout><SamplePred /></MainLayout></ProtectedRoute>} />
frontend/src/api.js CHANGED
@@ -2,183 +2,162 @@
2
  // 🔐 API Layer for Adaptive AI NIDS Frontend
3
  // ===============================================
4
 
5
- const BASE_URL =
6
- import.meta.env.VITE_API_URL || "http://127.0.0.1:5000";
7
 
8
- // Safe fetch wrapper
9
  async function safeFetch(url, options = {}, timeout = 10000, retries = 1) {
10
  const controller = new AbortController();
11
  const id = setTimeout(() => controller.abort(), timeout);
12
 
13
- try {
14
- const res = await fetch(url, { ...options, signal: controller.signal });
15
 
16
- if (!res.ok) {
17
- const errText = await res.text();
18
- throw new Error(`HTTP ${res.status}: ${errText}`);
19
-     }
20
-     return await res.json();
21
-   } catch (err) {
22
-     console.error(`❌ API Error [${url}]:`, err.message);
23
 
24
-     if (retries > 0 && url.includes("/geo/")) {
25
-       await new Promise((r) => setTimeout(r, 1500));
26
-       return safeFetch(url, options, timeout * 1.5, retries - 1);
27
-     }
 
28
 
29
-     return { error: err.message };
30
-   } finally {
31
-     clearTimeout(id);
32
-   }
33
  }
34
 
35
  // -------------------------------------------------------------
36
- // 🚀 LIVE CAPTURE
37
  // -------------------------------------------------------------
38
- export async function startSniffer(iface = null) {
39
-   const q = iface ? `?iface=${iface}` : "";
40
-   return safeFetch(`${BASE_URL}/api/live/start${q}`);
41
  }
42
 
43
- export async function stopSniffer() {
44
-   return safeFetch(`${BASE_URL}/api/live/stop`);
45
  }
46
 
47
- export async function getStatus() {
48
-   return safeFetch(`${BASE_URL}/api/live/status`);
49
  }
50
 
51
- // MODEL-AWARE 🎯
52
- export async function getRecent(model, limit = 300) {
53
-   const res = await safeFetch(`${BASE_URL}/api/live/recent?model=${model}`);
54
-
55
-   if (res?.events && Array.isArray(res.events)) {
56
-     res.events = res.events.slice(-limit);
57
-   }
58
-   return res;
59
  }
60
 
61
- // MODEL-AWARE 🎯
62
- export async function getStats(model) {
63
-   return safeFetch(`${BASE_URL}/api/live/stats?model=${model}`);
64
  }
65
 
66
  // -------------------------------------------------------------
67
- // 🧾 LOGS (MODEL-AWARE)
68
  // -------------------------------------------------------------
69
- export function download_logs(model) {
70
-   window.location.href = `${BASE_URL}/api/logs/download?model=${model}`;
 
71
  }
72
 
73
- export async function clearLogs(model, n = 50) {
74
-   return safeFetch(
75
-     `${BASE_URL}/api/logs/clear?model=${model}&n=${n}`,
76
-     { method: "POST" }
77
-   );
78
  }
79
 
80
- export async function clearByPrediction(model, pred) {
81
-   return safeFetch(
82
-     `${BASE_URL}/api/logs/clear_pred?model=${model}&pred=${pred}`,
83
-     { method: "POST" }
84
-   );
85
  }
86
 
87
- export async function deleteOne(model, index) {
88
-   return safeFetch(
89
-     `${BASE_URL}/api/logs/delete_one?model=${model}&index=${index}`,
90
-     { method: "POST" }
91
-   );
 
 
 
 
 
92
  }
93
 
94
  // -------------------------------------------------------------
95
- // 🌍 GEO + ALERTS
96
  // -------------------------------------------------------------
97
- export async function getGeoData() {
98
-   return safeFetch(`${BASE_URL}/api/geo/recent`, {}, 20000, 2);
99
  }
100
 
101
- export async function getAlerts() {
102
-   return safeFetch(`${BASE_URL}/api/alerts`);
103
  }
104
 
105
  // -------------------------------------------------------------
106
  // 🧩 MODEL CONTROL
107
  // -------------------------------------------------------------
108
- // Change this line in api.js to ensure fresh data
109
  export async function getActiveModel() {
110
- return safeFetch(`${BASE_URL}/api/model/active?t=${Date.now()}`);
111
  }
112
 
113
  export async function switchModel(model) {
114
-   return safeFetch(`${BASE_URL}/api/model/select`, {
115
-     method: "POST",
116
-     headers: { "Content-Type": "application/json" },
117
-     body: JSON.stringify({ model }),
118
-   });
119
  }
120
 
121
- export async function getModelHealth() {
122
-   return safeFetch(`${BASE_URL}/api/model/health`);
 
 
 
 
 
 
 
 
123
  }
124
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
  // -------------------------------------------------------------
127
- // 🤖 AI HELPERS
128
  // -------------------------------------------------------------
129
- export async function explainThreat(event) {
130
-   return safeFetch(`${BASE_URL}/api/ai/explain`, {
131
-     method: "POST",
132
-     headers: { "Content-Type": "application/json" },
133
-     body: JSON.stringify(event),
134
-   });
135
- }
136
 
137
- export async function getAISummary(model, n = 200) {
138
-   return safeFetch(
139
-     `${BASE_URL}/api/ai/summary?model=${encodeURIComponent(model)}&n=${n}`
140
-   );
 
 
 
141
  }
142
 
 
 
 
 
 
 
143
 
144
- export async function sendMessageToAI(message) {
145
-   try {
146
-     const res = await fetch(`${BASE_URL}/api/chat`, {
147
-       method: "POST",
148
-       headers: { "Content-Type": "application/json" },
149
-       body: JSON.stringify({ message })
150
-     });
151
-
152
-     if (!res.ok) throw new Error("Chat API failed");
153
-     return res.json();
154
-   } catch (err) {
155
-     console.error("Chat error:", err);
156
-     return { reply: "⚠ AI Assistant not responding." };
157
-   }
158
- }
159
-
160
- // ➤ Offline CSV/PCAP prediction
161
- export const offlinePredictAPI = async (file, model) => {
162
-   const formData = new FormData();
163
-   formData.append("file", file);
164
-   formData.append("model", model);
165
-
166
-   // FIX: Using BASE_URL for live deployment
167
-   const res = await fetch(`${BASE_URL}/api/offline/predict`, {
168
-     method: "POST",
169
-     body: formData,
170
-   });
171
-
172
-   return res.json();
173
- };
174
-
175
- // ➤ Get PDF forensic report download link
176
  export const downloadOfflineReport = () => {
177
- // FIX: Using BASE_URL for live deployment
178
- window.open(`${BASE_URL}/api/offline/report`, "_blank");
179
- };
180
-
181
 
182
- // -------------------------------------------------------------
183
  export { BASE_URL };
184
 
 
2
  // 🔐 API Layer for Adaptive AI NIDS Frontend
3
  // ===============================================
4
 
5
+ const BASE_URL = import.meta.env.VITE_API_URL || "http://127.0.0.1:5000";
 
6
 
7
+ // Safe fetch wrapper with timeout and retry logic
8
  async function safeFetch(url, options = {}, timeout = 10000, retries = 1) {
9
  const controller = new AbortController();
10
  const id = setTimeout(() => controller.abort(), timeout);
11
 
12
+ try {
13
+ const res = await fetch(url, { ...options, signal: controller.signal });
14
 
15
+ if (!res.ok) {
16
+ const errText = await res.text();
17
+ throw new Error(`HTTP ${res.status}: ${errText}`);
18
+ }
19
+ return await res.json();
20
+ } catch (err) {
21
+ console.error(`❌ API Error [${url}]:`, err.message);
22
 
23
+ // Retry logic for specific sensitive endpoints
24
+ if (retries > 0 && url.includes("/geo/")) {
25
+ await new Promise((r) => setTimeout(r, 1500));
26
+ return safeFetch(url, options, timeout * 1.5, retries - 1);
27
+ }
28
 
29
+ return { error: err.message };
30
+ } finally {
31
+ clearTimeout(id);
32
+ }
33
  }
34
 
35
  // -------------------------------------------------------------
36
+ // 🖥️ SYSTEM & DIAGNOSTICS (NEWLY UPDATED)
37
  // -------------------------------------------------------------
38
+ export async function getSystemStatus() {
39
+ return safeFetch(`${BASE_URL}/api/system/status`);
 
40
  }
41
 
42
+ export async function runSystemDiagnostic() {
43
+ return safeFetch(`${BASE_URL}/api/system/diagnostic`);
44
  }
45
 
46
+ export async function getSystemProcesses() {
47
+ return safeFetch(`${BASE_URL}/api/system/processes`);
48
  }
49
 
50
+ export async function getSystemConnections() {
51
+ return safeFetch(`${BASE_URL}/api/system/connections`);
 
 
 
 
 
 
52
  }
53
 
54
+ export function downloadSystemReport() {
55
+ // Standard window.open for PDF downloads
56
+ window.open(`${BASE_URL}/api/system/report`, "_blank");
57
  }
58
 
59
  // -------------------------------------------------------------
60
+ // 🚀 LIVE CAPTURE
61
  // -------------------------------------------------------------
62
+ export async function startSniffer(iface = null) {
63
+ const q = iface ? `?iface=${iface}` : "";
64
+ return safeFetch(`${BASE_URL}/api/live/start${q}`);
65
  }
66
 
67
+ export async function stopSniffer() {
68
+ return safeFetch(`${BASE_URL}/api/live/stop`);
 
 
 
69
  }
70
 
71
+ export async function getStatus() {
72
+ return safeFetch(`${BASE_URL}/api/live/status`);
 
 
 
73
  }
74
 
75
+ export async function getRecent(model, limit = 300) {
76
+ const res = await safeFetch(`${BASE_URL}/api/live/recent?model=${model}`);
77
+ if (res?.events && Array.isArray(res.events)) {
78
+ res.events = res.events.slice(-limit);
79
+ }
80
+ return res;
81
+ }
82
+
83
+ export async function getStats(model) {
84
+ return safeFetch(`${BASE_URL}/api/live/stats?model=${model}`);
85
  }
86
 
87
  // -------------------------------------------------------------
88
+ // 🧾 LOGS (MODEL-AWARE)
89
  // -------------------------------------------------------------
90
+ export function download_logs(model) {
91
+ window.location.href = `${BASE_URL}/api/logs/download?model=${model}`;
92
  }
93
 
94
+ export async function clearLogs(model, n = 50) {
95
+ return safeFetch(`${BASE_URL}/api/logs/clear?model=${model}&n=${n}`, { method: "POST" });
96
  }
97
 
98
  // -------------------------------------------------------------
99
  // 🧩 MODEL CONTROL
100
  // -------------------------------------------------------------
 
101
  export async function getActiveModel() {
102
+ return safeFetch(`${BASE_URL}/api/model/active?t=${Date.now()}`);
103
  }
104
 
105
  export async function switchModel(model) {
106
+ return safeFetch(`${BASE_URL}/api/model/select`, {
107
+ method: "POST",
108
+ headers: { "Content-Type": "application/json" },
109
+ body: JSON.stringify({ model }),
110
+ });
111
  }
112
 
113
+ // -------------------------------------------------------------
114
+ // 🤖 AI HELPERS & CHAT
115
+ // -------------------------------------------------------------
116
+ export async function sendMessageToAI(message) {
117
+ // Using the safeFetch logic for consistency
118
+ return safeFetch(`${BASE_URL}/api/chat`, {
119
+ method: "POST",
120
+ headers: { "Content-Type": "application/json" },
121
+ body: JSON.stringify({ message })
122
+ });
123
  }
124
 
125
+ export async function offlinePredictAPI(file, model) {
126
+ const formData = new FormData();
127
+ formData.append("file", file);
128
+ formData.append("model", model);
129
+
130
+ const res = await fetch(`${BASE_URL}/api/offline/predict`, {
131
+ method: "POST",
132
+ body: formData,
133
+ });
134
+ return res.json();
135
+ }
136
 
137
  // -------------------------------------------------------------
138
+ // 🧾 LOGS (MODEL-AWARE)
139
  // -------------------------------------------------------------
 
 
 
 
 
 
 
140
 
141
+ // ... keep your existing clearLogs function ...
142
+
143
+ export async function clearByPrediction(model, pred) {
144
+ return safeFetch(
145
+ `${BASE_URL}/api/logs/clear_pred?model=${model}&pred=${pred}`,
146
+ { method: "POST" }
147
+ );
148
  }
149
 
150
+ export async function deleteOne(model, index) {
151
+ return safeFetch(
152
+ `${BASE_URL}/api/logs/delete_one?model=${model}&index=${index}`,
153
+ { method: "POST" }
154
+ );
155
+ }
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  export const downloadOfflineReport = () => {
158
+ // FIX: Using BASE_URL for live deployment
159
+ window.open(`${BASE_URL}/api/offline/report`, "_blank");
160
+ }
 
161
 
 
162
  export { BASE_URL };
163
 
frontend/src/components/FeatureGuard.jsx CHANGED
@@ -1,109 +1,173 @@
1
  import React, { useState, useEffect } from "react";
2
- import { AlertTriangle, Github, Terminal, ShieldAlert, Copy, Check, Search } from "lucide-react";
 
 
 
3
  import { motion, AnimatePresence } from "framer-motion";
4
 
5
  const FeatureGuard = ({ children, requireLocal = false }) => {
6
  const [isLocal, setIsLocal] = useState(true);
7
  const [isScanning, setIsScanning] = useState(false);
8
  const [showPopup, setShowPopup] = useState(false);
9
- const [copied, setCopied] = useState(false);
10
 
11
  useEffect(() => {
12
- const local = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1";
13
  setIsLocal(local);
14
 
15
  if (requireLocal && !local) {
16
- // Feature 2: Simulated System Scan
17
  setIsScanning(true);
18
  const timer = setTimeout(() => {
19
  setIsScanning(false);
20
  setShowPopup(true);
21
- }, 2000); // 2 second scan time
22
  return () => clearTimeout(timer);
23
  }
24
  }, [requireLocal]);
25
 
26
- // Feature 1: Copy to Clipboard Function
27
- const copyToClipboard = (text) => {
28
  navigator.clipboard.writeText(text);
29
- setCopied(true);
30
- setTimeout(() => setCopied(false), 2000);
31
  };
32
 
33
  if (isLocal || !requireLocal) return <>{children}</>;
34
 
35
  return (
36
- <div className="relative min-h-screen bg-[#020617]">
37
- <div className="blur-xl pointer-events-none opacity-20 grayscale">{children}</div>
 
 
 
38
 
39
  <AnimatePresence mode="wait">
40
- {/* Feature 2: Scanning UI */}
41
  {isScanning && (
42
  <motion.div
43
  key="scanner"
44
  initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
45
- className="fixed inset-0 z-[9999] flex flex-col items-center justify-center bg-black/90 backdrop-blur-md"
46
  >
47
- <div className="relative w-24 h-24 mb-6">
48
- <motion.div
49
- animate={{ rotate: 360 }} transition={{ repeat: Infinity, duration: 2, ease: "linear" }}
50
- className="absolute inset-0 border-t-2 border-b-2 border-cyan-500 rounded-full"
51
- />
52
- <Search className="absolute inset-0 m-auto text-cyan-400 animate-pulse" size={32} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  </div>
54
- <h2 className="text-cyan-100 font-mono tracking-widest uppercase text-sm">Initializing Hardware Probe...</h2>
55
- <p className="text-cyan-800 font-mono text-xs mt-2">Checking local network interfaces (NICs)</p>
56
  </motion.div>
57
  )}
58
 
59
- {/* Feature 1: Restructured UI with Copy Buttons */}
60
  {showPopup && !isScanning && (
61
  <motion.div
62
  key="popup"
63
- initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }}
64
- className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 p-4"
65
  >
66
- <div className="relative w-full max-w-lg bg-[#0b1120] border border-cyan-500/30 rounded-lg overflow-hidden shadow-[0_0_50px_rgba(6,182,212,0.2)]">
67
-
68
- <div className="bg-cyan-900/20 p-4 flex items-center gap-3 border-b border-cyan-500/20">
69
- <ShieldAlert className="text-cyan-400" size={20} />
70
- <span className="text-cyan-100 font-mono text-[11px] uppercase tracking-widest">Hardware Exception</span>
 
 
 
 
 
 
 
 
 
 
 
71
  </div>
72
 
73
- <div className="p-8">
74
- <h2 className="text-2xl font-black text-white mb-2 tracking-tighter uppercase italic">
75
- Hardware <span className="text-cyan-400">Not Linked</span>
76
- </h2>
77
- <p className="text-slate-400 text-sm mb-6">
78
- Remote deployment detected. To sniff live packets, the kernel requires direct access to your local hardware.
79
- </p>
 
 
 
80
 
81
- {/* Terminal with Copy Buttons */}
82
- <div className="bg-black/60 rounded border border-cyan-500/10 p-5 mb-8 font-mono text-xs space-y-4">
83
- <div className="flex items-center justify-between group">
84
- <span className="text-emerald-400">$ git clone https://github.com/ayu-yishu13/Astra_Gaurd.git</span>
85
- <button onClick={() => copyToClipboard("git clone https://github.com/ayu-yishu13/Astra_Gaurd.git")} className="text-cyan-600 hover:text-cyan-300">
86
- {copied ? <Check size={14} /> : <Copy size={14} />}
 
 
 
 
 
 
 
 
 
 
87
  </button>
88
- </div>
89
- <div className="flex items-center justify-between group">
90
- <span className="text-cyan-400">$ python main.py --mode live</span>
91
- <button onClick={() => copyToClipboard("python main.py --mode live")} className="text-cyan-600 hover:text-cyan-300">
92
- <Copy size={14} />
93
- </button>
94
- </div>
95
  </div>
96
 
97
- <div className="grid grid-cols-2 gap-4">
98
- <button onClick={() => window.open('https://github.com/ayu-yishu13/Astra_Gaurd.git', '_blank')} className="bg-cyan-500 text-black py-3 rounded font-black uppercase text-xs tracking-widest hover:bg-white transition-all">
99
- Get Agent
 
 
 
 
 
100
  </button>
101
- <button onClick={() => window.history.back()} className="border border-slate-700 text-slate-400 py-3 rounded font-bold uppercase text-xs tracking-widest hover:bg-slate-800 transition-all">
102
- Disconnect
 
 
 
 
103
  </button>
104
  </div>
 
 
 
 
105
  </div>
106
- </div>
107
  </motion.div>
108
  )}
109
  </AnimatePresence>
 
1
  import React, { useState, useEffect } from "react";
2
+ import {
3
+ AlertTriangle, Github, Terminal, ShieldAlert,
4
+ Copy, Check, Search, Cpu, Globe, Lock
5
+ } from "lucide-react";
6
  import { motion, AnimatePresence } from "framer-motion";
7
 
8
  const FeatureGuard = ({ children, requireLocal = false }) => {
9
  const [isLocal, setIsLocal] = useState(true);
10
  const [isScanning, setIsScanning] = useState(false);
11
  const [showPopup, setShowPopup] = useState(false);
12
+ const [copiedId, setCopiedId] = useState(null);
13
 
14
  useEffect(() => {
15
+ const local = false;
16
  setIsLocal(local);
17
 
18
  if (requireLocal && !local) {
 
19
  setIsScanning(true);
20
  const timer = setTimeout(() => {
21
  setIsScanning(false);
22
  setShowPopup(true);
23
+ }, 5500);
24
  return () => clearTimeout(timer);
25
  }
26
  }, [requireLocal]);
27
 
28
+ const copyToClipboard = (text, id) => {
 
29
  navigator.clipboard.writeText(text);
30
+ setCopiedId(id);
31
+ setTimeout(() => setCopiedId(null), 2000);
32
  };
33
 
34
  if (isLocal || !requireLocal) return <>{children}</>;
35
 
36
  return (
37
+ <div className="relative min-h-screen bg-[#020617] overflow-hidden">
38
+ {/* Background Content (Blurred) */}
39
+ <div className="blur-2xl pointer-events-none opacity-10 grayscale scale-105 transition-all duration-1000">
40
+ {children}
41
+ </div>
42
 
43
  <AnimatePresence mode="wait">
44
+ {/* --- SCANNING STATE --- */}
45
  {isScanning && (
46
  <motion.div
47
  key="scanner"
48
  initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
49
+ className="fixed inset-0 z-[9999] flex flex-col items-center justify-center bg-black/95 backdrop-blur-xl p-6"
50
  >
51
+ <div className="relative w-40 h-40 mb-8">
52
+ {/* Radar Rings */}
53
+ {[...Array(3)].map((_, i) => (
54
+ <motion.div
55
+ key={i}
56
+ className="absolute inset-0 border border-cyan-500/30 rounded-full"
57
+ initial={{ scale: 1, opacity: 0.5 }}
58
+ animate={{ scale: 1.5, opacity: 0 }}
59
+ transition={{ repeat: Infinity, duration: 2, delay: i * 0.6 }}
60
+ />
61
+ ))}
62
+ <div className="absolute inset-0 flex items-center justify-center">
63
+ <div className="w-20 h-20 border-2 border-cyan-500 rounded-full flex items-center justify-center bg-cyan-500/10 shadow-[0_0_20px_rgba(6,182,212,0.3)]">
64
+ <Cpu className="text-cyan-400 animate-pulse" size={40} />
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <div className="text-center space-y-2">
70
+ <h2 className="text-cyan-100 font-mono tracking-[0.3em] uppercase text-sm font-bold">Hardware Probe Active</h2>
71
+ <div className="flex items-center justify-center gap-2 text-cyan-800 font-mono text-[10px]">
72
+ <span className="w-1 h-1 bg-cyan-500 rounded-full animate-ping" />
73
+ CHECKING KERNEL INTERFACES...
74
+ </div>
75
+ </div>
76
+
77
+ {/* Simulated Log */}
78
+ <div className="mt-8 w-full max-w-xs bg-black/50 border border-white/5 p-3 rounded font-mono text-[9px] text-slate-500 h-24 overflow-hidden">
79
+ <motion.div animate={{ y: [-100, 0] }} transition={{ duration: 4, ease: "linear" }}>
80
+ <p>[INFO] Initializing handshake...</p>
81
+ <p className="text-cyan-900">[OK] v4.19.0-x86_64 detected</p>
82
+ <p>[ERR] Device /dev/null/promisc not found</p>
83
+ <p>[INFO] Scanning for local NICs...</p>
84
+ <p className="text-rose-900">[WARN] Remote environment detected</p>
85
+ <p>[INFO] Attempting hardware bypass...</p>
86
+ </motion.div>
87
  </div>
 
 
88
  </motion.div>
89
  )}
90
 
91
+ {/* --- RESTRICTION MODAL --- */}
92
  {showPopup && !isScanning && (
93
  <motion.div
94
  key="popup"
95
+ initial={{ opacity: 0 }} animate={{ opacity: 1 }}
96
+ className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 backdrop-blur-sm p-4"
97
  >
98
+ <motion.div
99
+ initial={{ scale: 0.9, y: 20 }} animate={{ scale: 1, y: 0 }}
100
+ className="relative w-full max-w-xl bg-[#0b1120] border border-cyan-500/20 rounded-xl overflow-hidden shadow-[0_0_80px_rgba(6,182,212,0.15)]"
101
+ >
102
+ {/* Header */}
103
+ <div className="bg-gradient-to-r from-cyan-950/40 to-transparent p-4 flex items-center justify-between border-b border-white/5">
104
+ <div className="flex items-center gap-3">
105
+ <div className="p-1.5 bg-rose-500/10 rounded border border-rose-500/20">
106
+ <ShieldAlert className="text-rose-500" size={16} />
107
+ </div>
108
+ <span className="text-slate-400 font-mono text-[10px] uppercase tracking-widest">Environment Error: 403</span>
109
+ </div>
110
+ <div className="flex gap-1.5">
111
+ <div className="w-2 h-2 rounded-full bg-slate-800" />
112
+ <div className="w-2 h-2 rounded-full bg-slate-800" />
113
+ </div>
114
  </div>
115
 
116
+ <div className="p-6 md:p-10">
117
+ <div className="mb-8">
118
+ <h2 className="text-3xl md:text-4xl font-black text-white mb-3 tracking-tighter uppercase italic flex items-center gap-3">
119
+ <span className="text-cyan-500 text-sm not-italic font-mono bg-cyan-500/10 px-2 py-1 rounded">PROXIED</span>
120
+ LOCAL ONLY
121
+ </h2>
122
+ <p className="text-slate-400 text-sm leading-relaxed font-light">
123
+ The <span className="text-cyan-400 font-medium">AstraGuard Kernel</span> is currently running in an isolated cloud environment. Packet sniffing and live hardware monitoring require a <span className="underline decoration-cyan-500/30">Direct Local Link</span>.
124
+ </p>
125
+ </div>
126
 
127
+ {/* Commands Terminal */}
128
+ <div className="space-y-3 mb-8">
129
+ {[
130
+ { id: 'clone', label: 'SOURCE', cmd: 'git clone https://github.com/ayu-yishu13/Astra_Gaurd.git' },
131
+ { id: 'run', label: 'RUNTIME', cmd: 'python main.py --mode live' }
132
+ ].map((item) => (
133
+ <div key={item.id} className="group flex items-center justify-between bg-black/40 border border-white/5 hover:border-cyan-500/30 rounded-lg p-4 transition-all">
134
+ <div className="flex flex-col gap-1 overflow-hidden">
135
+ <span className="text-[9px] font-bold text-cyan-600 uppercase tracking-tighter">{item.label}</span>
136
+ <code className="text-cyan-100 font-mono text-xs truncate pr-4">{item.cmd}</code>
137
+ </div>
138
+ <button
139
+ onClick={() => copyToClipboard(item.cmd, item.id)}
140
+ className={`flex-shrink-0 p-2 rounded-md transition-all ${copiedId === item.id ? 'bg-emerald-500/20 text-emerald-400' : 'bg-white/5 text-slate-500 hover:text-white'}`}
141
+ >
142
+ {copiedId === item.id ? <Check size={16} /> : <Copy size={16} />}
143
  </button>
144
+ </div>
145
+ ))}
 
 
 
 
 
146
  </div>
147
 
148
+ {/* Actions Grid */}
149
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
150
+ <button
151
+ onClick={() => window.open('https://github.com/ayu-yishu13/Astra_Gaurd.git', '_blank')}
152
+ className="flex items-center justify-center gap-2 bg-cyan-500 text-black py-4 rounded-lg font-black uppercase text-xs tracking-[0.2em] hover:bg-white transition-all group"
153
+ >
154
+ <Github size={16} />
155
+ Download Agent
156
  </button>
157
+ <button
158
+ onClick={() => window.history.back()}
159
+ className="flex items-center justify-center gap-2 border border-slate-800 text-slate-500 py-4 rounded-lg font-bold uppercase text-xs tracking-[0.2em] hover:bg-slate-800/50 hover:text-slate-300 transition-all"
160
+ >
161
+ <Globe size={16} />
162
+ Return Home
163
  </button>
164
  </div>
165
+
166
+ <p className="mt-8 text-center text-[9px] font-mono text-slate-600 uppercase tracking-widest opacity-50">
167
+ System: ASTRAGUARD-SHIELD-V1 // KERNEL-LOCKED
168
+ </p>
169
  </div>
170
+ </motion.div>
171
  </motion.div>
172
  )}
173
  </AnimatePresence>
frontend/src/components/Navbar.jsx CHANGED
@@ -1,5 +1,5 @@
1
  import React, { useState } from "react";
2
- import { Shield, Search, User, ChevronDown, RefreshCcw, LogOut, CurrencyIcon } from "lucide-react";
3
  import { useAuth } from "../context/AuthContext";
4
  import { useLocation, useNavigate } from "react-router-dom";
5
 
@@ -10,43 +10,58 @@ export default function Navbar({ onRefresh }) {
10
 
11
  const [searchQuery, setSearchQuery] = useState("");
12
  const [profileOpen, setProfileOpen] = useState(false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  return (
15
- <nav className="relative z-20 border-b border-accent/20 backdrop-blur-xl py-4 shadow-[0_4px_20px_rgba(0,0,0,0.45)]">
16
- <div className="container mx-auto px-4 py-3 mb-2 flex items-center gap-6">
 
 
 
 
 
 
 
 
17
 
18
  {/* Brand */}
19
- <button onClick={() => navigate("/")} className="flex items-center gap-3 group">
20
- <div className="p-2 rounded-xl border border-accent/50 bg-accent/10 shadow-neon group-hover:bg-accent/20 transition">
21
- <CurrencyIcon size={20} className="text-accent" />
22
  </div>
23
- <div className="flex flex-col leading-tight">
24
- <span className="text-sm font-semibold text-accent tracking-[0.22em] uppercase">
25
  ASTRAGUARD
26
  </span>
27
- <span className="text-[11px] text-slate-400 uppercase tracking-[0.18em]">
28
  AI • NIDS
29
  </span>
30
  </div>
31
  </button>
32
 
33
- {/* Main Nav */}
34
- <div className="hidden lg:flex items-center gap-4 text-sm text-slate-300 ml-4">
35
-
36
- {[
37
- { path: "/", label: "Dashboard" },
38
- { path: "/livetraffic", label: "Live Traffic" },
39
- { path: "/flow", label: "Flow Analyzer" },
40
- { path: "/alerts", label: "Alerts" },
41
- { path: "/threats", label: "Threat Intel" },
42
- { path: "/reports", label: "Reports" },
43
- { path: "/system", label: "System" },
44
- { path: "/mlmodels", label: "ML Models" },
45
- ].map((item, i) => (
46
  <button
47
  key={i}
48
  onClick={() => navigate(item.path)}
49
- className={`px-3 py-1.5 rounded-full transition-all duration-200 ${
50
  location.pathname === item.path
51
  ? "text-accent bg-accent/10 shadow-[0_0_10px_rgba(0,229,255,0.35)]"
52
  : "text-slate-300 hover:text-accent hover:bg-accent/10"
@@ -58,17 +73,16 @@ export default function Navbar({ onRefresh }) {
58
  </div>
59
 
60
  {/* Right side */}
61
- <div className="ml-auto flex items-center gap-4">
62
-
63
- {/* Search */}
64
- <div className="hidden md:flex items-center gap-2 px-3 py-1.5 rounded-full border border-accent/40 bg-white/5 focus-within:ring-1 focus-within:ring-accent/60 transition">
65
- <Search size={16} className="text-accent/80" />
66
  <input
67
  type="text"
68
  value={searchQuery}
69
  onChange={(e) => setSearchQuery(e.target.value)}
70
- placeholder="Search dashboard..."
71
- className="bg-transparent text-xs text-slate-200 placeholder:text-slate-500 focus:outline-none w-40"
72
  />
73
  </div>
74
 
@@ -76,24 +90,24 @@ export default function Navbar({ onRefresh }) {
76
  <div className="relative">
77
  <button
78
  onClick={() => setProfileOpen(!profileOpen)}
79
- className="flex items-center gap-2 px-2 py-1.5 rounded-full border border-accent/40 bg-white/5 hover:bg-accent/10 transition"
80
  >
81
- <div className="w-8 h-8 rounded-full border border-accent/40 bg-accent/10 flex items-center justify-center">
82
- <User size={16} className="text-accent" />
83
  </div>
84
- <div className="hidden sm:flex flex-col items-start max-w-[130px]">
85
- <span className="text-[10px] text-slate-400 uppercase tracking-[0.16em]">
86
  Operator
87
  </span>
88
- <span className="text-xs text-accent font-medium truncate">
89
  {user?.displayName || "Analyst"}
90
  </span>
91
  </div>
92
- <ChevronDown size={14} className="text-slate-400" />
93
  </button>
94
 
95
  {profileOpen && (
96
- <div className="absolute right-0 mt-2 w-44 rounded-xl border border-accent/30 bg-[#020617]/95 shadow-lg py-1 text-sm z-40">
97
  {onRefresh && (
98
  <>
99
  <button
@@ -101,7 +115,7 @@ export default function Navbar({ onRefresh }) {
101
  onRefresh();
102
  setProfileOpen(false);
103
  }}
104
- className="w-full flex items-center gap-2 px-3 py-2 hover:bg-accent/10 text-slate-200"
105
  >
106
  <RefreshCcw size={14} className="text-accent" />
107
  <span>Reload data</span>
@@ -112,7 +126,7 @@ export default function Navbar({ onRefresh }) {
112
 
113
  <button
114
  onClick={() => logout()}
115
- className="w-full flex items-center gap-2 px-3 py-2 hover:bg-red-500/15 text-red-300"
116
  >
117
  <LogOut size={14} />
118
  <span>Logout</span>
@@ -120,9 +134,39 @@ export default function Navbar({ onRefresh }) {
120
  </div>
121
  )}
122
  </div>
123
-
124
  </div>
125
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  </nav>
127
  );
128
- }
 
1
  import React, { useState } from "react";
2
+ import { Shield, Search, User, ChevronDown, RefreshCcw, LogOut, CurrencyIcon, Menu, X } from "lucide-react";
3
  import { useAuth } from "../context/AuthContext";
4
  import { useLocation, useNavigate } from "react-router-dom";
5
 
 
10
 
11
  const [searchQuery, setSearchQuery] = useState("");
12
  const [profileOpen, setProfileOpen] = useState(false);
13
+ const [menuOpen, setMenuOpen] = useState(false); // New state for mobile menu
14
+
15
+ const navLinks = [
16
+ { path: "/", label: "Dashboard" },
17
+ { path: "/livetraffic", label: "Live Traffic" },
18
+ { path: "/flow", label: "Flow Analyzer" },
19
+ { path: "/alerts", label: "Alerts" },
20
+ { path: "/threats", label: "Threat Intel" },
21
+ { path: "/reports", label: "Reports" },
22
+ { path: "/system", label: "System" },
23
+ { path: "/mlmodels", label: "ML Models" },
24
+ ];
25
+
26
+ const handleNavigate = (path) => {
27
+ navigate(path);
28
+ setMenuOpen(false); // Close mobile menu on click
29
+ };
30
 
31
  return (
32
+ <nav className="relative z-[50] border-b border-accent/20 backdrop-blur-xl py-2 lg:py-4 shadow-[0_4px_20px_rgba(0,0,0,0.45)]">
33
+ <div className="container mx-auto px-4 flex items-center justify-between lg:justify-start gap-4 lg:gap-6">
34
+
35
+ {/* Mobile Menu Toggle */}
36
+ <button
37
+ onClick={() => setMenuOpen(!menuOpen)}
38
+ className="lg:hidden p-2 rounded-lg border border-accent/30 text-accent"
39
+ >
40
+ {menuOpen ? <X size={20} /> : <Menu size={20} />}
41
+ </button>
42
 
43
  {/* Brand */}
44
+ <button onClick={() => navigate("/")} className="flex items-center gap-2 lg:gap-3 group">
45
+ <div className="p-1.5 lg:p-2 rounded-xl border border-accent/50 bg-accent/10 shadow-neon group-hover:bg-accent/20 transition">
46
+ <CurrencyIcon size={18} className="text-accent" />
47
  </div>
48
+ <div className="flex flex-col leading-tight text-left">
49
+ <span className="text-[12px] lg:text-sm font-semibold text-accent tracking-[0.15em] lg:tracking-[0.22em] uppercase">
50
  ASTRAGUARD
51
  </span>
52
+ <span className="text-[9px] lg:text-[11px] text-slate-400 uppercase tracking-[0.12em] lg:tracking-[0.18em]">
53
  AI • NIDS
54
  </span>
55
  </div>
56
  </button>
57
 
58
+ {/* Main Nav (Desktop) */}
59
+ <div className="hidden lg:flex items-center gap-2 text-sm text-slate-300 ml-4">
60
+ {navLinks.map((item, i) => (
 
 
 
 
 
 
 
 
 
 
61
  <button
62
  key={i}
63
  onClick={() => navigate(item.path)}
64
+ className={`px-3 py-1.5 rounded-full transition-all duration-200 whitespace-nowrap ${
65
  location.pathname === item.path
66
  ? "text-accent bg-accent/10 shadow-[0_0_10px_rgba(0,229,255,0.35)]"
67
  : "text-slate-300 hover:text-accent hover:bg-accent/10"
 
73
  </div>
74
 
75
  {/* Right side */}
76
+ <div className="ml-auto flex items-center gap-2 lg:gap-4">
77
+ {/* Search (Hidden on small mobile) */}
78
+ <div className="hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-full border border-accent/40 bg-white/5 focus-within:ring-1 focus-within:ring-accent/60 transition">
79
+ <Search size={14} className="text-accent/80" />
 
80
  <input
81
  type="text"
82
  value={searchQuery}
83
  onChange={(e) => setSearchQuery(e.target.value)}
84
+ placeholder="Search..."
85
+ className="bg-transparent text-xs text-slate-200 placeholder:text-slate-500 focus:outline-none w-24 lg:w-40"
86
  />
87
  </div>
88
 
 
90
  <div className="relative">
91
  <button
92
  onClick={() => setProfileOpen(!profileOpen)}
93
+ className="flex items-center gap-2 p-1 lg:px-2 lg:py-1.5 rounded-full border border-accent/40 bg-white/5 hover:bg-accent/10 transition"
94
  >
95
+ <div className="w-7 h-7 lg:w-8 lg:h-8 rounded-full border border-accent/40 bg-accent/10 flex items-center justify-center">
96
+ <User size={14} className="text-accent" />
97
  </div>
98
+ <div className="hidden md:flex flex-col items-start max-w-[100px]">
99
+ <span className="text-[10px] text-slate-400 uppercase tracking-wider font-bold">
100
  Operator
101
  </span>
102
+ <span className="text-xs text-accent font-medium truncate w-full text-left">
103
  {user?.displayName || "Analyst"}
104
  </span>
105
  </div>
106
+ <ChevronDown size={14} className="text-slate-400 hidden sm:block" />
107
  </button>
108
 
109
  {profileOpen && (
110
+ <div className="absolute right-0 mt-3 w-44 rounded-xl border border-accent/30 bg-[#020617] shadow-2xl py-2 text-sm z-50 animate-in fade-in zoom-in duration-200">
111
  {onRefresh && (
112
  <>
113
  <button
 
115
  onRefresh();
116
  setProfileOpen(false);
117
  }}
118
+ className="w-full flex items-center gap-3 px-4 py-2.5 hover:bg-accent/10 text-slate-200 transition"
119
  >
120
  <RefreshCcw size={14} className="text-accent" />
121
  <span>Reload data</span>
 
126
 
127
  <button
128
  onClick={() => logout()}
129
+ className="w-full flex items-center gap-3 px-4 py-2.5 hover:bg-red-500/15 text-red-300 transition"
130
  >
131
  <LogOut size={14} />
132
  <span>Logout</span>
 
134
  </div>
135
  )}
136
  </div>
 
137
  </div>
138
  </div>
139
+
140
+ {/* MOBILE MENU DRAWER */}
141
+ {menuOpen && (
142
+ <div className="lg:hidden absolute top-[100%] left-0 w-full bg-[#020617]/95 border-b border-accent/20 backdrop-blur-2xl animate-in slide-in-from-top duration-300 overflow-hidden shadow-2xl">
143
+ <div className="flex flex-col p-4 gap-2">
144
+ {navLinks.map((item, i) => (
145
+ <button
146
+ key={i}
147
+ onClick={() => handleNavigate(item.path)}
148
+ className={`flex items-center px-4 py-3 rounded-xl transition-all ${
149
+ location.pathname === item.path
150
+ ? "text-accent bg-accent/10 border border-accent/20 shadow-neon-sm"
151
+ : "text-slate-300 hover:text-accent hover:bg-accent/5"
152
+ }`}
153
+ >
154
+ {item.label}
155
+ </button>
156
+ ))}
157
+
158
+ {/* Mobile Search - shown only in menu */}
159
+ <div className="flex sm:hidden items-center gap-3 px-4 py-3 mt-2 rounded-xl border border-accent/20 bg-white/5">
160
+ <Search size={16} className="text-accent" />
161
+ <input
162
+ type="text"
163
+ placeholder="Search systems..."
164
+ className="bg-transparent text-sm text-slate-200 focus:outline-none w-full"
165
+ />
166
+ </div>
167
+ </div>
168
+ </div>
169
+ )}
170
  </nav>
171
  );
172
+ }
frontend/src/components/Sidebar.jsx CHANGED
@@ -2,29 +2,12 @@
2
  import React, { useEffect, useRef, useState } from "react";
3
  import { NavLink } from "react-router-dom";
4
  import {
5
- Activity,
6
- AlertTriangle,
7
- FileText,
8
- Info,
9
- Settings,
10
- TrafficCone,
11
- MonitorCog,
12
- GitBranchMinus,
13
- BrickWallShield,
14
- ChevronLeft,
15
- ChevronRight,
16
- MoonStar,
17
- LayoutDashboard,
18
  } from "lucide-react";
19
 
20
- /**
21
- * Sidebar with mini-constellation canvas (B3)
22
- *
23
- * Props:
24
- * - collapsed: boolean
25
- * - setCollapsed: function
26
- */
27
- export default function Sidebar({ collapsed, setCollapsed }) {
28
  const sidebarRef = useRef(null);
29
  const canvasRef = useRef(null);
30
  const [time, setTime] = useState("");
@@ -33,35 +16,27 @@ export default function Sidebar({ collapsed, setCollapsed }) {
33
  useEffect(() => {
34
  const tick = () => {
35
  const now = new Date();
36
- setTime(
37
- now.toLocaleTimeString("en-IN", {
38
- hour12: true,
39
- hour: "2-digit",
40
- minute: "2-digit",
41
- second: "2-digit",
42
- })
43
- );
44
  };
45
  tick();
46
  const id = setInterval(tick, 1000);
47
  return () => clearInterval(id);
48
  }, []);
49
 
50
- // mini-constellation canvas (node+line) - optimized for sidebar
51
  useEffect(() => {
52
  const canvas = canvasRef.current;
53
  const sidebar = sidebarRef.current;
54
  if (!canvas || !sidebar) return;
55
-
56
  const ctx = canvas.getContext("2d", { alpha: true });
57
  let width = sidebar.clientWidth;
58
  let height = sidebar.clientHeight;
59
  let rafId = null;
60
  let particles = [];
61
- const COUNT = Math.max(18, Math.floor((width * height) / 10000)); // scale nodes by size
62
 
63
- // Resize handler
64
  function resize() {
 
65
  width = sidebar.clientWidth;
66
  height = sidebar.clientHeight;
67
  const dpr = Math.max(1, window.devicePixelRatio || 1);
@@ -70,100 +45,40 @@ export default function Sidebar({ collapsed, setCollapsed }) {
70
  canvas.style.width = `${width}px`;
71
  canvas.style.height = `${height}px`;
72
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
73
- // recreate particles to adapt density
74
  initParticles();
75
  }
76
 
77
- function rand(min, max) {
78
- return Math.random() * (max - min) + min;
79
- }
80
-
81
  function initParticles() {
82
  particles = [];
83
- const n = COUNT;
84
- for (let i = 0; i < n; i++) {
85
  particles.push({
86
- x: rand(10, width - 10),
87
- y: rand(10, height - 10),
88
- vx: rand(-0.15, 0.15),
89
- vy: rand(-0.15, 0.15),
90
- size: rand(0.8, 2.2),
91
- hue: rand(170, 200), // cyan-ish
92
  });
93
  }
94
  }
95
 
96
  function step() {
97
  ctx.clearRect(0, 0, width, height);
98
-
99
- // draw lines between close particles
100
- for (let i = 0; i < particles.length; i++) {
101
- const a = particles[i];
102
- for (let j = i + 1; j < particles.length; j++) {
103
- const b = particles[j];
104
- const dx = a.x - b.x;
105
- const dy = a.y - b.y;
106
- const dist = Math.sqrt(dx * dx + dy * dy);
107
- const MAX = Math.min(120, Math.max(70, (width + height) / 15));
108
- if (dist < MAX) {
109
- const alpha = 0.12 * (1 - dist / MAX);
110
- ctx.beginPath();
111
- ctx.moveTo(a.x, a.y);
112
- ctx.lineTo(b.x, b.y);
113
- ctx.strokeStyle = `rgba(40,220,210, ${alpha.toFixed(3)})`;
114
- ctx.lineWidth = 0.6;
115
- ctx.stroke();
116
- }
117
- }
118
- }
119
-
120
- // draw nodes
121
  for (let p of particles) {
122
- // move
123
- p.x += p.vx;
124
- p.y += p.vy;
125
-
126
- // gentle wrap/bounce
127
- if (p.x < -6) p.x = width + 6;
128
- if (p.x > width + 6) p.x = -6;
129
- if (p.y < -6) p.y = height + 6;
130
- if (p.y > height + 6) p.y = -6;
131
-
132
- // glow circle
133
  ctx.beginPath();
134
- const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 6);
135
- grad.addColorStop(0, `rgba(0,230,255,0.95)`);
136
- grad.addColorStop(0.2, `rgba(0,230,255,0.55)`);
137
- grad.addColorStop(1, `rgba(0,230,255,0.02)`);
138
- ctx.fillStyle = grad;
139
- ctx.arc(p.x, p.y, p.size * 3.2, 0, Math.PI * 2);
140
- ctx.fill();
141
-
142
- // center bright dot
143
- ctx.beginPath();
144
- ctx.fillStyle = `rgba(220,255,255,0.95)`;
145
  ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
 
146
  ctx.fill();
147
  }
148
-
149
  rafId = requestAnimationFrame(step);
150
  }
151
 
152
- // ResizeObserver to respond to sidebar size changes (collapse/expand)
153
  const ro = new ResizeObserver(resize);
154
  ro.observe(sidebar);
 
 
 
155
 
156
- resize();
157
- step(); // start animation
158
-
159
- return () => {
160
- if (rafId) cancelAnimationFrame(rafId);
161
- ro.disconnect();
162
- };
163
- // eslint-disable-next-line react-hooks/exhaustive-deps
164
- }, [sidebarRef, canvasRef, collapsed]);
165
-
166
- // navigation items
167
  const navItems = [
168
  { to: "/", label: "Dashboard", icon: <LayoutDashboard size={18} /> },
169
  { to: "/livetraffic", label: "Live Traffic", icon: <Activity size={18} /> },
@@ -179,146 +94,87 @@ export default function Sidebar({ collapsed, setCollapsed }) {
179
  ];
180
 
181
  return (
182
- <aside
183
- ref={sidebarRef}
184
- aria-label="Main navigation"
185
- className={`fixed top-0 left-0 h-screen
186
- ${collapsed ? "w-20" : "w-64"}
187
- bg-[#030b17]/50 backdrop-blur-xl
188
- flex flex-col z-50 transition-all duration-300
189
- border-r-2 border-[var(--accent)]/14
190
- shadow-[inset_0_0_18px_rgba(0,229,255,0.06)]
191
- `}
192
- >
193
- {/* background canvas (mini constellation) */}
194
- <canvas
195
- ref={canvasRef}
196
- className="pointer-events-none absolute inset-0 -z-10"
197
- aria-hidden="true"
198
- />
199
-
200
- {/* double neon border / decorative rings */}
201
- <div
202
- className="absolute inset-0 pointer-events-none -z-5"
203
- style={{
204
- boxShadow:
205
- "inset 0 0 2px rgba(0,230,255,0.06), inset 0 0 30px rgba(0,230,255,0.03)",
206
- }}
207
- />
208
 
209
- {/* HEADER */}
210
- <div className="p-4 border-b border-[var(--accent)]/12 relative overflow-hidden shrink-0">
211
- <div className="relative z-10 flex items-center justify-between">
212
  <div className="flex items-center gap-2">
213
  <span className="text-[18px] font-extrabold text-[var(--accent)]">⚡</span>
214
- {!collapsed && (
215
  <div>
216
- <div className="text-xl font-bold text-[var(--accent)] leading-tight">NIDS</div>
217
- <div className="text-[11px] text-slate-400">Cyber Defense</div>
218
  </div>
219
  )}
220
  </div>
 
 
 
 
 
 
221
 
222
- <div className="flex items-center gap-2">
223
- <span
224
- className={`w-2.5 h-2.5 rounded-full ${
225
- navigator.onLine ? "bg-emerald-400 animate-pulse" : "bg-rose-500 animate-ping"
226
- }`}
227
- />
228
- {!collapsed && (
229
- <div className="text-xs text-slate-400">{navigator.onLine ? "LIVE" : "OFFLINE"}</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  )}
231
  </div>
232
  </div>
233
 
234
- {!collapsed && (
235
- <div className="mt-3 text-xs text-slate-400">
236
- <div className="flex justify-between items-center">
237
- <span className="text-[var(--accent)]">Host:</span>
238
- <span className="font-mono text-[var(--accent)] text-right">{window.location.hostname}</span>
239
- </div>
240
- <div className="mt-2 relative h-1.5 bg-gradient-to-r from-transparent to-transparent rounded-full overflow-hidden">
241
- <div className="absolute inset-0 bg-gradient-to-r from-cyan-400 via-emerald-400 to-cyan-400 opacity-30 blur-sm" />
242
- <div className="mt-2 text-[10px] text-slate-500">Monitoring anomalies…</div>
243
- </div>
244
- </div>
245
- )}
246
- </div>
247
-
248
- {/* NAV - scrollable */}
249
- <nav className="flex-1 p-3 overflow-y-auto overflow-x-hidden custom-scroll">
250
- <div className="space-y-1">
251
-
252
- {navItems.map(({ to, label, icon }, index) => (
253
- <div key={to}>
254
-
255
- <NavLink
256
- to={to}
257
- title={collapsed ? label : ""}
258
- className={({ isActive }) =>
259
- `
260
- group flex items-center gap-3 px-3 py-2 rounded-lg transition-all duration-200 text-sm relative
261
- ${isActive
262
- ? "bg-[var(--accent)]/18 border border-[var(--accent)]/28 text-[var(--accent)] shadow-[0_0_10px_rgba(0,230,255,0.06)]"
263
- : "text-slate-300 hover:bg-[var(--accent)]/6 hover:border hover:border-[var(--accent)]/18"}
264
- `
265
- }
266
  >
267
-
268
- <div className="w-5 h-5 flex items-center justify-center text-[var(--accent)]">
269
- {icon}
270
- </div>
271
-
272
- {!collapsed && <span className="truncate">{label}</span>}
273
-
274
- {/* Tooltip when collapsed */}
275
- {collapsed && (
276
- <div className="absolute left-[3.4rem] top-1/2 -translate-y-1/2 opacity-0
277
- group-hover:opacity-100 transition-opacity duration-150 pointer-events-none">
278
- <div className="bg-black/75 text-[var(--accent)] border border-[var(--accent)]/30
279
- px-2 py-1 rounded text-xs whitespace-nowrap shadow-md">
280
- {label}
281
- </div>
282
- </div>
283
- )}
284
-
285
- </NavLink>
286
-
287
- {/* Divider line (between items) */}
288
- {index < navItems.length - 1 && (
289
- <div className="h-px w-full bg-white/100 my-3"></div>
290
- )}
291
-
292
- </div>
293
- ))}
294
-
295
- </div>
296
- </nav>
297
-
298
-
299
- {/* FOOTER */}
300
- <div className="p-3 border-t border-[var(--accent)]/12 shrink-0">
301
- <div className="flex items-center justify-between">
302
- {!collapsed ? (
303
- <>
304
- <div className="text-[10px] text-slate-400">© 2025 Future Lelouch</div>
305
- <div className="text-[11px] text-[var(--accent)] font-mono">{time}</div>
306
- </>
307
- ) : (
308
- <div className="text-[10px] text-slate-400 text-center w-full">© 2025</div>
309
- )}
310
- </div>
311
- </div>
312
-
313
- {/* collapse/expand toggle */}
314
- <button
315
- aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
316
- onClick={() => setCollapsed(!collapsed)}
317
- className="absolute right-[-12px] bottom-6 w-8 h-8 rounded-full bg-[var(--accent)]/12 border border-[var(--accent)]/30 text-[var(--accent)] shadow-[0_6px_18px_rgba(0,230,255,0.06)] flex items-center justify-center transition-transform hover:scale-110"
318
- >
319
- {collapsed ? <ChevronRight size={16} /> : <ChevronLeft size={16} />}
320
- </button>
321
- </aside>
322
  );
323
  }
324
 
 
2
  import React, { useEffect, useRef, useState } from "react";
3
  import { NavLink } from "react-router-dom";
4
  import {
5
+ Activity, AlertTriangle, FileText, Info, Settings, TrafficCone,
6
+ MonitorCog, GitBranchMinus, BrickWallShield, ChevronLeft, ChevronRight,
7
+ MoonStar, LayoutDashboard, X, Menu
 
 
 
 
 
 
 
 
 
 
8
  } from "lucide-react";
9
 
10
+ export default function Sidebar({ collapsed, setCollapsed, isMobileOpen, setIsMobileOpen }) {
 
 
 
 
 
 
 
11
  const sidebarRef = useRef(null);
12
  const canvasRef = useRef(null);
13
  const [time, setTime] = useState("");
 
16
  useEffect(() => {
17
  const tick = () => {
18
  const now = new Date();
19
+ setTime(now.toLocaleTimeString("en-IN", { hour12: true, hour: "2-digit", minute: "2-digit", second: "2-digit" }));
 
 
 
 
 
 
 
20
  };
21
  tick();
22
  const id = setInterval(tick, 1000);
23
  return () => clearInterval(id);
24
  }, []);
25
 
26
+ // Canvas Animation Logic (Kept as per your original code)
27
  useEffect(() => {
28
  const canvas = canvasRef.current;
29
  const sidebar = sidebarRef.current;
30
  if (!canvas || !sidebar) return;
 
31
  const ctx = canvas.getContext("2d", { alpha: true });
32
  let width = sidebar.clientWidth;
33
  let height = sidebar.clientHeight;
34
  let rafId = null;
35
  let particles = [];
36
+ const COUNT = Math.max(18, Math.floor((width * height) / 10000));
37
 
 
38
  function resize() {
39
+ if (!sidebar) return;
40
  width = sidebar.clientWidth;
41
  height = sidebar.clientHeight;
42
  const dpr = Math.max(1, window.devicePixelRatio || 1);
 
45
  canvas.style.width = `${width}px`;
46
  canvas.style.height = `${height}px`;
47
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
 
48
  initParticles();
49
  }
50
 
 
 
 
 
51
  function initParticles() {
52
  particles = [];
53
+ for (let i = 0; i < COUNT; i++) {
 
54
  particles.push({
55
+ x: Math.random() * width, y: Math.random() * height,
56
+ vx: (Math.random() - 0.5) * 0.3, vy: (Math.random() - 0.5) * 0.3,
57
+ size: Math.random() * 1.5 + 0.5,
 
 
 
58
  });
59
  }
60
  }
61
 
62
  function step() {
63
  ctx.clearRect(0, 0, width, height);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  for (let p of particles) {
65
+ p.x += p.vx; p.y += p.vy;
66
+ if (p.x < 0 || p.x > width) p.vx *= -1;
67
+ if (p.y < 0 || p.y > height) p.vy *= -1;
 
 
 
 
 
 
 
 
68
  ctx.beginPath();
 
 
 
 
 
 
 
 
 
 
 
69
  ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
70
+ ctx.fillStyle = "rgba(0, 230, 255, 0.5)";
71
  ctx.fill();
72
  }
 
73
  rafId = requestAnimationFrame(step);
74
  }
75
 
 
76
  const ro = new ResizeObserver(resize);
77
  ro.observe(sidebar);
78
+ resize(); step();
79
+ return () => { if (rafId) cancelAnimationFrame(rafId); ro.disconnect(); };
80
+ }, [collapsed]);
81
 
 
 
 
 
 
 
 
 
 
 
 
82
  const navItems = [
83
  { to: "/", label: "Dashboard", icon: <LayoutDashboard size={18} /> },
84
  { to: "/livetraffic", label: "Live Traffic", icon: <Activity size={18} /> },
 
94
  ];
95
 
96
  return (
97
+ <>
98
+ {/* MOBILE OVERLAY: Blurs background when sidebar is open on mobile */}
99
+ {isMobileOpen && (
100
+ <div
101
+ className="fixed inset-0 bg-black/60 backdrop-blur-sm z-[45] lg:hidden"
102
+ onClick={() => setIsMobileOpen(false)}
103
+ />
104
+ )}
105
+
106
+ <aside
107
+ ref={sidebarRef}
108
+ className={`fixed top-0 left-0 h-screen z-50 transition-all duration-300 ease-in-out
109
+ border-r-2 border-[var(--accent)]/14 bg-[#030b17]/90 backdrop-blur-xl
110
+ ${collapsed ? "w-20" : "w-64"}
111
+ /* MOBILE LOGIC: Slide out of screen on mobile unless isMobileOpen is true */
112
+ ${isMobileOpen ? "translate-x-0" : "-translate-x-full lg:translate-x-0"}
113
+ `}
114
+ >
115
+ <canvas ref={canvasRef} className="pointer-events-none absolute inset-0 -z-10" />
 
 
 
 
 
 
 
116
 
117
+ {/* HEADER */}
118
+ <div className="p-4 border-b border-[var(--accent)]/12 flex items-center justify-between">
 
119
  <div className="flex items-center gap-2">
120
  <span className="text-[18px] font-extrabold text-[var(--accent)]">⚡</span>
121
+ {(!collapsed || isMobileOpen) && (
122
  <div>
123
+ <div className="text-xl font-bold text-[var(--accent)]">NIDS</div>
124
+ <div className="text-[10px] text-slate-400 uppercase tracking-tighter">Cyber Defense</div>
125
  </div>
126
  )}
127
  </div>
128
+
129
+ {/* Close button - Only visible on Mobile */}
130
+ <button className="lg:hidden text-slate-400" onClick={() => setIsMobileOpen(false)}>
131
+ <X size={20} />
132
+ </button>
133
+ </div>
134
 
135
+ {/* NAVIGATION */}
136
+ <nav className="flex-1 p-3 overflow-y-auto overflow-x-hidden custom-scroll space-y-1">
137
+ {navItems.map(({ to, label, icon }) => (
138
+ <NavLink
139
+ key={to}
140
+ to={to}
141
+ onClick={() => setIsMobileOpen(false)} // Close sidebar on mobile after clicking
142
+ className={({ isActive }) => `
143
+ group flex items-center gap-3 px-3 py-2.5 rounded-lg transition-all text-sm
144
+ ${isActive
145
+ ? "bg-[var(--accent)]/15 border border-[var(--accent)]/30 text-[var(--accent)]"
146
+ : "text-slate-300 hover:bg-[var(--accent)]/5 hover:text-white"}
147
+ `}
148
+ >
149
+ <div className="shrink-0">{icon}</div>
150
+ {(!collapsed || isMobileOpen) && <span className="truncate font-medium">{label}</span>}
151
+ </NavLink>
152
+ ))}
153
+ </nav>
154
+
155
+ {/* FOOTER */}
156
+ <div className="p-4 border-t border-[var(--accent)]/12 bg-black/20">
157
+ <div className="flex flex-col gap-1">
158
+ {(!collapsed || isMobileOpen) ? (
159
+ <>
160
+ <div className="text-[11px] text-[var(--accent)] font-mono tracking-widest">{time}</div>
161
+ <div className="text-[9px] text-slate-500 uppercase tracking-widest">© 2025 Future Lelouch</div>
162
+ </>
163
+ ) : (
164
+ <div className="text-[9px] text-slate-500 text-center">© 25</div>
165
  )}
166
  </div>
167
  </div>
168
 
169
+ {/* DESKTOP COLLAPSE TOGGLE (Hidden on Mobile) */}
170
+ <button
171
+ onClick={() => setCollapsed(!collapsed)}
172
+ className="hidden lg:flex absolute right-[-14px] top-20 w-7 h-7 rounded-full bg-[#030b17] border border-[var(--accent)]/30 text-[var(--accent)] items-center justify-center hover:scale-110 transition-transform"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  >
174
+ {collapsed ? <ChevronRight size={14} /> : <ChevronLeft size={14} />}
175
+ </button>
176
+ </aside>
177
+ </>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  );
179
  }
180
 
frontend/src/pages/Dashboard.jsx CHANGED
@@ -25,42 +25,28 @@ import NeonShield from "../components/NeonShield";
25
  import { useNavigate } from "react-router-dom";
26
  import ChatAssistant from "./ChatAssistant";
27
 
28
- // Cyber palette
29
  const COLORS = ["#00e5ff", "#ff0059", "#a78bfa", "#fbbf24", "#10b981"];
30
 
31
  export default function Dashboard() {
32
-
33
  const location = useLocation();
34
  const navigate = useNavigate();
35
  const [systemStats, setSystemStats] = useState(null);
36
  const [threats, setThreats] = useState([]);
37
  const [mlModels, setMlModels] = useState([]);
38
  const [loading, setLoading] = useState(true);
39
-
40
-
41
-
42
- // -------------------------------
43
- // BACK TO TOP BUTTON STATE
44
- // -------------------------------
45
  const [showTop, setShowTop] = useState(false);
46
 
47
  useEffect(() => {
48
- // find the real scroll container
49
  const scrollContainer = document.querySelector("main.flex-1.overflow-auto");
50
-
51
  if (!scrollContainer) return;
52
-
53
  const handleScroll = () => {
54
  if (scrollContainer.scrollTop > 300) setShowTop(true);
55
  else setShowTop(false);
56
  };
57
-
58
  scrollContainer.addEventListener("scroll", handleScroll);
59
-
60
  return () => scrollContainer.removeEventListener("scroll", handleScroll);
61
  }, []);
62
 
63
- // Backend fetch
64
  const loadData = async () => {
65
  try {
66
  const [sys, ml, th] = await Promise.all([
@@ -68,7 +54,6 @@ export default function Dashboard() {
68
  fetch("http://127.0.0.1:5000/api/ml/models").then((r) => r.json()),
69
  fetch("http://127.0.0.1:5000/api/live/stats").then((r) => r.json()),
70
  ]);
71
-
72
  setSystemStats(sys || {});
73
  setMlModels(Array.isArray(ml) ? ml : []);
74
  setThreats(
@@ -92,126 +77,59 @@ export default function Dashboard() {
92
  return (
93
  <>
94
  <div className="relative">
95
- {/* ============================
96
- CYBER BACKGROUND
97
- ============================= */}
98
  <div className="absolute inset-0 -z-10 pointer-events-none overflow-hidden">
99
- {/* Gradient Base */}
100
- <div
101
- className="absolute inset-0"
102
- style={{
103
- background:
104
- "linear-gradient(140deg, rgba(3,6,23,0.75) 0%, rgba(9,19,39,0.7) 40%, rgba(10,26,54,0.6) 75%, rgba(15,7,33,0.65) 100%)",
105
- }}
106
- />
107
-
108
- {/* Hex Grid */}
109
- <div
110
- className="absolute inset-0 opacity-[0.035] mix-blend-screen"
111
- style={{
112
- backgroundImage:
113
- "url('https://raw.githubusercontent.com/ayushatlas/assets/main/hexgrid/hexgrid-light.png')",
114
- backgroundSize: "350px",
115
- backgroundRepeat: "repeat",
116
- }}
117
- />
118
-
119
- {/* Left Cyan Glow */}
120
- <div className="absolute left-10 top-40 w-[450px] h-[450px] bg-cyan-400/15 blur-[180px]" />
121
-
122
- {/* Right Purple Glow */}
123
- <div className="absolute right-10 top-10 w-[420px] h-[420px] bg-purple-500/12 blur-[180px]" />
124
-
125
- {/* Floating Particles */}
126
- {[...Array(70)].map((_, i) => (
127
- <div
128
- key={i}
129
- className="absolute rounded-full drift-slow"
130
- style={{
131
- width: `${3 + Math.random() * 6}px`,
132
- height: `${3 + Math.random() * 6}px`,
133
- background: `rgba(150, 220, 255, ${0.45 + Math.random() * 0.4})`,
134
- top: `${Math.random() * 100}%`,
135
- left: `${Math.random() * 100}%`,
136
- filter: "blur(2px)",
137
- animationDuration: `${6 + Math.random() * 5}s`,
138
- animationDelay: `${Math.random() * 3}s`,
139
- opacity: 0.6 + Math.random() * 0.3,
140
- }}
141
- />
142
- ))}
143
  </div>
144
 
145
- {/* ============================
146
- HERO HEADER
147
- ============================= */}
148
- <header className="relative mb-24">
149
- {/* HERO CONTENT */}
150
- <div className="relative z-20 container mx-auto px-8 pt-24 pb-24 lg:ml-1">
151
- <div className="grid lg:grid-cols-2 gap-16 items-center">
152
  {/* LEFT TEXT */}
153
- <div className="space-y-7">
154
- <div className="flex items-center gap-3">
155
  <div className="p-2 rounded-full border border-accent/50 shadow-neon">
156
- <Shield size={24} className="text-accent" />
157
  </div>
158
- <span className="text-sm text-slate-300/80 tracking-wide">
159
  AstraGuard AI • Adaptive NIDS
160
  </span>
161
  </div>
162
 
163
- <h1
164
- className="text-[70px] leading-[76px] font-extrabold tracking-tight"
165
- style={{
166
- textShadow:
167
- "0 0 30px rgba(0,229,255,0.75), 0 0 12px rgba(0,229,255,0.5)",
168
- }}
169
- >
170
  <span className="text-accent">Protect</span> Your <br /> Systems
171
  </h1>
172
 
173
- <div className="w-full overflow-hidden">
174
  <div className="neon-wave" />
175
  </div>
176
 
177
- <p className="text-slate-300/85 text-lg max-w-xl leading-relaxed">
178
  Our adaptive AI framework provides real-time packet inspection,
179
- threat detection, ML classification and security analytics.
180
  </p>
181
 
182
- <div className="flex items-center gap-4 pt-3">
183
- <button
184
- onClick={() => navigate("/livetraffic")}
185
- className="px-6 py-3 rounded-xl bg-accent text-black font-semibold text-lg shadow-neon hover:scale-[1.03] transition"
186
- >
187
  Get Started
188
  </button>
189
-
190
- <button
191
- onClick={() => navigate("/threats")}
192
- className="px-6 py-3 rounded-xl border border-accent/40 text-accent text-lg hover:bg-accent/10 transition"
193
- >
194
  Learn more
195
  </button>
196
  </div>
197
  </div>
198
 
199
- {/* RIGHT Floating Shield */}
200
- <div className="relative w-full flex justify-center items-center h-[420px]">
201
- <div className="flex items-center gap-3 absolute -top-10">
202
- <div className="p-2 rounded-full border border-accent/50 shadow-neon">
203
- <Radio size={24} className="text-accent" />
204
- </div>
205
- <span className="text-sm text-slate-300/80">
206
- Cyber • Security
207
- </span>
208
- </div>
209
-
210
- <div
211
- className="relative w-[90%] h-[380px] rounded-3xl
212
- border border-accent/25 backdrop-blur-xl shadow-[0_0_40px_rgba(0,229,255,0.25)]
213
- overflow-hidden"
214
- >
215
  <NeonShield />
216
  </div>
217
  </div>
@@ -219,384 +137,172 @@ export default function Dashboard() {
219
  </div>
220
  </header>
221
 
222
- {/* ============================
223
- MAIN DASHBOARD PANEL
224
- ============================= */}
225
- <main className="container mx-auto px-6 -mt-20 relative z-30">
226
- <div className="glass-shell p-6 rounded-3xl border border-accent/20">
227
- <div className="flex justify-between items-center border-b border-accent/10 pb-3 mb-4">
228
  <div>
229
- <h1 className="text-2xl font-bold text-accent flex items-center gap-2">
230
  <Shield size={22} /> Cyber SOC Dashboard
231
  </h1>
232
- <p className="text-slate-300/70 text-sm">
233
- Real-time overview of AI NIDS operations
234
  </p>
235
  </div>
236
  </div>
237
 
238
- {/* System + ML + Network */}
239
- <div className="grid md:grid-cols-3 gap-5 mb-6">
240
- {/* System */}
241
- <div className="cyber-card p-5 border border-accent/20">
242
- <h3 className="text-accent font-semibold mb-2 flex items-center gap-2">
243
  <Cpu size={16} /> System Status
244
  </h3>
245
- {loading ? (
246
- <p className="text-slate-500">Loading...</p>
247
- ) : (
248
- <ul className="text-sm text-slate-300 space-y-1">
249
- <li>CPU Usage: {systemStats?.cpu_usage ?? "N/A"}%</li>
250
- <li>RAM Usage: {systemStats?.ram_usage ?? "N/A"}%</li>
251
- <li>Disk Usage: {systemStats?.disk_usage ?? "N/A"}%</li>
252
- <li>
253
- Active Interfaces: {systemStats?.interfaces?.length ?? 0}
254
- </li>
255
  </ul>
256
  )}
257
  </div>
258
 
259
- {/* ML Models */}
260
- <div className="cyber-card p-5 border border-accent/20">
261
- <h3 className="text-accent font-semibold mb-2 flex items-center gap-2">
262
  <Activity size={16} /> ML Model Status
263
  </h3>
264
  {mlModels.length > 0 ? (
265
- <ul className="text-sm text-slate-300 space-y-1">
266
  {mlModels.map((m, i) => (
267
- <li key={i} className="flex justify-between">
268
  <span>{m.name}</span>
269
- <span className="text-accent">
270
- {m.accuracy ?? "N/A"}%
271
- </span>
272
  </li>
273
  ))}
274
  </ul>
275
- ) : (
276
- <p className="text-slate-500">No models loaded</p>
277
- )}
278
  </div>
279
 
280
- {/* Live Threats */}
281
- <div className="cyber-card p-5 border border-accent/20">
282
- <h3 className="text-accent font-semibold mb-2 flex items-center gap-2">
283
- <Wifi size={16} /> Live Network Health
284
  </h3>
285
  {threats.length > 0 ? (
286
- <ul className="text-sm text-slate-300 space-y-1">
287
- {threats.map((t, i) => (
288
  <li key={i} className="flex justify-between">
289
- <span>{t.name}</span>
290
- <span className="text-rose-300">{t.value}</span>
291
  </li>
292
  ))}
293
  </ul>
294
- ) : (
295
- <p className="text-slate-500">Awaiting live data</p>
296
- )}
297
  </div>
298
  </div>
299
 
300
- {/* Charts */}
301
- <div className="grid md:grid-cols-2 gap-6 mt-6">
302
- {/* Pie */}
303
- <div className="cyber-card border border-accent/15 p-5">
304
- <h3 className="text-accent mb-2 font-semibold">
305
- Threat Class Distribution (Pie)
306
  </h3>
307
- <div className="h-64">
308
  {threats.length > 0 ? (
309
- <ResponsiveContainer>
310
  <PieChart>
311
- <Pie
312
- data={threats}
313
- dataKey="value"
314
- outerRadius={90}
315
- label
316
- >
317
- {threats.map((entry, i) => (
318
- <Cell
319
- key={i}
320
- fill={COLORS[i % COLORS.length]}
321
- />
322
- ))}
323
  </Pie>
324
- <Tooltip />
325
  </PieChart>
326
  </ResponsiveContainer>
327
- ) : (
328
- <p className="text-slate-500 text-center mt-20">
329
- No data yet
330
- </p>
331
- )}
332
  </div>
333
  </div>
334
 
335
- {/* Bar */}
336
- <div className="cyber-card border border-accent/15 p-5">
337
- <h3 className="text-accent mb-2 font-semibold">
338
- Threat Count Overview (Bar)
339
  </h3>
340
- <div className="h-64">
341
  {threats.length > 0 ? (
342
- <ResponsiveContainer>
343
  <BarChart data={threats}>
344
- <CartesianGrid
345
- strokeDasharray="3 3"
346
- strokeOpacity={0.05}
347
- />
348
- <XAxis dataKey="name" stroke="#94a3b8" />
349
- <YAxis stroke="#94a3b8" />
350
- <Tooltip />
351
- <Bar
352
- dataKey="value"
353
- fill="#00e5ff"
354
- radius={[6, 6, 0, 0]}
355
- />
356
  </BarChart>
357
  </ResponsiveContainer>
358
- ) : (
359
- <p className="text-slate-500 text-center mt-20">
360
- Awaiting input
361
- </p>
362
- )}
363
  </div>
364
  </div>
365
  </div>
366
  </div>
367
  </main>
368
 
369
- {/* =========================================================
370
- PREMIUM CYBER FOOTER
371
- ========================================================= */}
372
  <footer className="mt-24 bg-[#030617]/95 border-t border-accent/20 relative">
373
- {/* GRID BG */}
374
- <div
375
- aria-hidden="true"
376
- style={{
377
- position: "absolute",
378
- inset: 0,
379
- zIndex: 0,
380
- opacity: 0.06,
381
- backgroundImage: `repeating-linear-gradient(0deg, transparent 0px, transparent 39px, rgba(255,255,255,0.02) 40px),
382
- repeating-linear-gradient(90deg, transparent 0px, transparent 39px, rgba(255,255,255,0.02) 40px)`,
383
- backgroundSize: "40px 40px",
384
- pointerEvents: "none",
385
- }}
386
- />
387
-
388
- <div className="relative container mx-auto px-8 py-16 grid grid-cols-1 md:grid-cols-4 gap-12 z-10">
389
- {/* COLUMN 1 — BRAND */}
390
  <div>
391
- <h2 className="text-accent text-3xl font-bold mb-3">
392
- AI-NIDS
393
- </h2>
394
- <p className="text-slate-400 text-sm leading-relaxed max-w-xs">
395
- Adaptive AI-powered Network Intrusion Detection System built for
396
- real-time threat detection, flow intelligence, and cyber defense
397
- automation.
398
  </p>
399
-
400
- {/* Social Icons */}
401
- <div className="flex gap-4 mt-6">
402
- <button
403
- onClick={() =>
404
- window.open("https://github.com/yishu13", "_blank")
405
- }
406
- className="p-2 rounded-full border border-accent/40 hover:bg-accent/10 text-accent transition"
407
- >
408
- {/* GitHub Icon */}
409
- <svg
410
- xmlns="http://www.w3.org/2000/svg"
411
- width="18"
412
- height="18"
413
- fill="currentColor"
414
- viewBox="0 0 24 24"
415
- >
416
- <path d="M12 .5C5.73.5.75 5.48.75 11.76c0 4.93 3.19 9.11 7.61 10.59.56.1.77-.24.77-.54 0-.27-.01-1-.02-1.96-3.09.67-3.74-1.49-3.74-1.49-.5-1.27-1.22-1.61-1.22-1.61-.99-.67.08-.66.08-.66 1.1.08 1.67 1.13 1.67 1.13.98 1.68 2.58 1.2 3.21.92.1-.72.38-1.2.7-1.48-2.47-.28-5.07-1.24-5.07-5.49 0-1.21.43-2.2 1.13-2.98-.11-.28-.49-1.4.11-2.92 0 0 .92-.29 3.02 1.14 10.45 10.45 0 0 1 2.75-.37c.93.01 1.86.12 2.75.37 2.1-1.43 3.01-1.14 3.01-1.14.6 1.52.22 2.64.11 2.92.7.78 1.13 1.77 1.13 2.98 0 4.26-2.61 5.21-5.09 5.48.39.33.74.98.74 1.98 0 1.43-.01 2.58-.01 2.93 0 .3.2.65.78.54C19.06 20.87 22.25 16.69 22.25 11.76 22.25 5.48 17.27.5 12 .5z" />
417
- </svg>
418
- </button>
419
-
420
- <button
421
- onClick={() =>
422
- window.open(
423
- "https://www.linkedin.com/in/ayushrai13",
424
- "_blank"
425
- )
426
- }
427
- className="p-2 rounded-full border border-accent/40 hover:bg-accent/10 text-accent transition"
428
- >
429
- {/* LinkedIn */}
430
- <svg
431
- xmlns="http://www.w3.org/2000/svg"
432
- width="18"
433
- height="18"
434
- fill="currentColor"
435
- viewBox="0 0 24 24"
436
- >
437
- <path d="M4.98 3.5a2.5 2.5 0 1 1 0 5.001 2.5 2.5 0 0 1 0-5.001zM3 9h4v12H3zM9 9h3.8v1.6h.1c.5-.9 1.8-1.9 3.7-1.9C21.2 8.7 22 10.9 22 14.1V21h-4v-6.1c0-1.6-.6-2.7-2-2.7-1.1 0-1.7.8-2 1.6-.1.2-.1.6-.1.9V21H9z" />
438
- </svg>
439
- </button>
440
-
441
- <button
442
- onClick={() => window.open("https://discord.com", "_blank")}
443
- className="p-2 rounded-full border border-accent/40 hover:bg-accent/10 text-accent transition"
444
- >
445
- {/* Discord */}
446
- <svg
447
- xmlns="http://www.w3.org/2000/svg"
448
- width="18"
449
- height="18"
450
- fill="currentColor"
451
- viewBox="0 0 24 24"
452
- >
453
- <path d="M20 3H4C2.9 3 2 3.9 2 5v12c0 1.1.9 2 2 2h13l-1-3 2.5 1 2.5-1 1 3V5c0-1.1-.9-2-2-2z" />
454
- </svg>
455
- </button>
456
  </div>
457
  </div>
458
 
459
- {/* COLUMN 2 */}
460
- <div>
461
- <h3 className="text-accent font-semibold mb-3 text-lg">
462
- Platform
463
- </h3>
464
- <ul className="space-y-2 text-slate-300">
465
- <li
466
- className="hover:text-accent cursor-pointer"
467
- onClick={() => navigate("/livetraffic")}
468
- >
469
- Live Traffic
470
- </li>
471
- <li
472
- className="hover:text-accent cursor-pointer"
473
- onClick={() => navigate("/alerts")}
474
- >
475
- AI Alerts Engine
476
- </li>
477
- <li
478
- className="hover:text-accent cursor-pointer"
479
- onClick={() => navigate("/flow")}
480
- >
481
- Flow Analyzer
482
- </li>
483
- <li
484
- className="hover:text-accent cursor-pointer"
485
- onClick={() => navigate("/reports")}
486
- >
487
- Report Generator
488
- </li>
489
  </ul>
490
  </div>
491
-
492
- {/* COLUMN 3 */}
493
- <div>
494
- <h3 className="text-accent font-semibold mb-3 text-lg">
495
- Security Suite
496
- </h3>
497
- <ul className="space-y-2 text-slate-300">
498
- <li className="hover:text-accent cursor-pointer">
499
- Threat Intelligence
500
- </li>
501
- <li className="hover:text-accent cursor-pointer">
502
- Anomaly Detection
503
- </li>
504
- <li className="hover:text-accent cursor-pointer">
505
- Geo-IP Mapping
506
- </li>
507
- <li className="hover:text-accent cursor-pointer">
508
- Packet Capture Engine
509
- </li>
510
  </ul>
511
  </div>
512
 
513
- {/* COLUMN 4 */}
514
- <div>
515
- <h3 className="text-accent font-semibold mb-3 text-lg">
516
- Resources
517
- </h3>
518
- <ul className="space-y-2 text-slate-300">
519
- <li className="hover:text-accent cursor-pointer">
520
- Documentation
521
- </li>
522
- <li className="hover:text-accent cursor-pointer">
523
- API Reference
524
- </li>
525
- <li
526
- className="hover:text-accent cursor-pointer"
527
- onClick={() => navigate("/support")}
528
- >
529
- Support Center
530
- </li>
531
- <li className="hover:text-accent cursor-pointer">
532
- Community
533
- </li>
534
  </ul>
535
  </div>
536
  </div>
537
 
538
- {/* BADGES */}
539
- <div className="relative flex justify-center gap-6 py-4 z-10">
540
- <div className="w-12 h-12 bg-white/5 rounded-full border border-accent/25 flex items-center justify-center text-xs text-slate-300">
541
- SOC2
542
- </div>
543
- <div className="w-12 h-12 bg-white/5 rounded-full border border-accent/25 flex items-center justify-center text-xs text-slate-300">
544
- ISO
545
- </div>
546
- </div>
547
-
548
- {/* COPYRIGHT */}
549
- <div className="border-t border-accent/10 py-4 text-center text-slate-500 text-sm relative z-10">
550
  © {new Date().getFullYear()} AI-NIDS • Adaptive Cyber Defense
551
- Framework
552
  </div>
553
  </footer>
554
  </div>
555
 
556
- {/* =========================================================
557
- FLOATING BACK-TO-TOP BUTTON (shows only after 300px)
558
- ========================================================= */}
559
  {showTop && (
560
  <button
561
  onClick={() => {
562
- const scrollContainer = document.querySelector(
563
- "main.flex-1.overflow-auto"
564
- );
565
  scrollContainer?.scrollTo({ top: 0, behavior: "smooth" });
566
  }}
567
- className={`
568
- fixed bottom-12 left-1/2 -translate-x-1/2
569
- z-[20000] w-16 h-16
570
- rounded-full flex items-center justify-center
571
- bg-gradient-to-br from-[#0ff] to-[#00a2ff] bg-opacity-20 backdrop-blur-xl
572
- border border-cyan-300/40
573
- shadow-[0_0_25px_rgba(0,229,255,0.45),0_0_45px_rgba(0,229,255,0.15)]
574
- hover:shadow-[0_0_35px_rgba(0,229,255,0.85),0_0_55px_rgba(0,229,255,0.35)]
575
- hover:scale-[1.18] hover:rotate-3
576
- transition-all duration-300 animate-[pulse_2s_infinite]
577
- overflow-hidden
578
- `}
579
  >
580
- <span
581
- className="
582
- absolute inset-0 rounded-full
583
- bg-gradient-to-r from-transparent via-white/40 to-transparent
584
- opacity-0 animate-[shine_2s_infinite]
585
- "
586
- />
587
- <svg
588
- xmlns="http://www.w3.org/2000/svg"
589
- className="w-7 h-7 text-cyan-300 drop-shadow-[0_0_8px_#00eaff]"
590
- fill="none"
591
- viewBox="0 0 24 24"
592
- stroke="currentColor"
593
- strokeWidth="2.5"
594
- >
595
- <path
596
- strokeLinecap="round"
597
- strokeLinejoin="round"
598
- d="M12 19V5m0 0l-6 6m6-6l6 6"
599
- />
600
  </svg>
601
  </button>
602
  )}
@@ -606,4 +312,3 @@ export default function Dashboard() {
606
  );
607
  }
608
 
609
-
 
25
  import { useNavigate } from "react-router-dom";
26
  import ChatAssistant from "./ChatAssistant";
27
 
 
28
  const COLORS = ["#00e5ff", "#ff0059", "#a78bfa", "#fbbf24", "#10b981"];
29
 
30
  export default function Dashboard() {
 
31
  const location = useLocation();
32
  const navigate = useNavigate();
33
  const [systemStats, setSystemStats] = useState(null);
34
  const [threats, setThreats] = useState([]);
35
  const [mlModels, setMlModels] = useState([]);
36
  const [loading, setLoading] = useState(true);
 
 
 
 
 
 
37
  const [showTop, setShowTop] = useState(false);
38
 
39
  useEffect(() => {
 
40
  const scrollContainer = document.querySelector("main.flex-1.overflow-auto");
 
41
  if (!scrollContainer) return;
 
42
  const handleScroll = () => {
43
  if (scrollContainer.scrollTop > 300) setShowTop(true);
44
  else setShowTop(false);
45
  };
 
46
  scrollContainer.addEventListener("scroll", handleScroll);
 
47
  return () => scrollContainer.removeEventListener("scroll", handleScroll);
48
  }, []);
49
 
 
50
  const loadData = async () => {
51
  try {
52
  const [sys, ml, th] = await Promise.all([
 
54
  fetch("http://127.0.0.1:5000/api/ml/models").then((r) => r.json()),
55
  fetch("http://127.0.0.1:5000/api/live/stats").then((r) => r.json()),
56
  ]);
 
57
  setSystemStats(sys || {});
58
  setMlModels(Array.isArray(ml) ? ml : []);
59
  setThreats(
 
77
  return (
78
  <>
79
  <div className="relative">
80
+ {/* CYBER BACKGROUND */}
 
 
81
  <div className="absolute inset-0 -z-10 pointer-events-none overflow-hidden">
82
+ <div className="absolute inset-0" style={{ background: "linear-gradient(140deg, rgba(3,6,23,0.75) 0%, rgba(9,19,39,0.7) 40%, rgba(10,26,54,0.6) 75%, rgba(15,7,33,0.65) 100%)" }} />
83
+ <div className="absolute inset-0 opacity-[0.035] mix-blend-screen" style={{ backgroundImage: "url('https://raw.githubusercontent.com/ayushatlas/assets/main/hexgrid/hexgrid-light.png')", backgroundSize: "350px" }} />
84
+ <div className="absolute left-0 lg:left-10 top-40 w-[300px] lg:w-[450px] h-[300px] lg:h-[450px] bg-cyan-400/15 blur-[120px] lg:blur-[180px]" />
85
+ <div className="absolute right-0 lg:right-10 top-10 w-[280px] lg:w-[420px] h-[280px] lg:h-[420px] bg-purple-500/12 blur-[120px] lg:blur-[180px]" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  </div>
87
 
88
+ {/* HERO HEADER */}
89
+ <header className="relative mb-12 lg:mb-24">
90
+ <div className="relative z-20 container mx-auto px-6 lg:px-8 pt-16 lg:pt-24 pb-20 lg:pb-24 lg:ml-1">
91
+ <div className="grid lg:grid-cols-2 gap-10 lg:gap-16 items-center">
92
+
 
 
93
  {/* LEFT TEXT */}
94
+ <div className="space-y-6 lg:space-y-7 text-center lg:text-left">
95
+ <div className="flex items-center justify-center lg:justify-start gap-3">
96
  <div className="p-2 rounded-full border border-accent/50 shadow-neon">
97
+ <Shield size={20} className="text-accent" />
98
  </div>
99
+ <span className="text-xs lg:text-sm text-slate-300/80 tracking-wide uppercase">
100
  AstraGuard AI • Adaptive NIDS
101
  </span>
102
  </div>
103
 
104
+ <h1 className="text-4xl md:text-6xl lg:text-[70px] lg:leading-[76px] font-extrabold tracking-tight"
105
+ style={{ textShadow: "0 0 30px rgba(0,229,255,0.75), 0 0 12px rgba(0,229,255,0.5)" }}>
 
 
 
 
 
106
  <span className="text-accent">Protect</span> Your <br /> Systems
107
  </h1>
108
 
109
+ <div className="w-full overflow-hidden opacity-50 lg:opacity-100">
110
  <div className="neon-wave" />
111
  </div>
112
 
113
+ <p className="text-slate-300/85 text-base lg:text-lg max-w-xl mx-auto lg:mx-0 leading-relaxed">
114
  Our adaptive AI framework provides real-time packet inspection,
115
+ threat detection, and security analytics.
116
  </p>
117
 
118
+ <div className="flex flex-col sm:flex-row items-center justify-center lg:justify-start gap-4 pt-3">
119
+ <button onClick={() => navigate("/livetraffic")}
120
+ className="w-full sm:w-auto px-8 py-3 rounded-xl bg-accent text-black font-bold text-lg shadow-neon active:scale-95 transition">
 
 
121
  Get Started
122
  </button>
123
+ <button onClick={() => navigate("/threats")}
124
+ className="w-full sm:w-auto px-8 py-3 rounded-xl border border-accent/40 text-accent text-lg hover:bg-accent/10 transition">
 
 
 
125
  Learn more
126
  </button>
127
  </div>
128
  </div>
129
 
130
+ {/* RIGHT Floating Shield - Hidden on small mobile to save space */}
131
+ <div className="relative w-full hidden sm:flex justify-center items-center h-[300px] lg:h-[420px]">
132
+ <div className="relative w-[95%] lg:w-[90%] h-full rounded-3xl border border-accent/25 backdrop-blur-xl shadow-[0_0_40px_rgba(0,229,255,0.25)] overflow-hidden">
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  <NeonShield />
134
  </div>
135
  </div>
 
137
  </div>
138
  </header>
139
 
140
+ {/* MAIN DASHBOARD PANEL */}
141
+ <main className="container mx-auto px-4 lg:px-6 -mt-10 lg:-mt-20 relative z-30">
142
+ <div className="glass-shell p-4 lg:p-6 rounded-3xl border border-accent/20 bg-black/40 backdrop-blur-md">
143
+ <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center border-b border-accent/10 pb-4 mb-6 gap-2">
 
 
144
  <div>
145
+ <h1 className="text-xl lg:text-2xl font-bold text-accent flex items-center gap-2">
146
  <Shield size={22} /> Cyber SOC Dashboard
147
  </h1>
148
+ <p className="text-slate-300/70 text-xs lg:text-sm">
149
+ Real-time AI NIDS operations
150
  </p>
151
  </div>
152
  </div>
153
 
154
+ {/* System + ML + Network - Stack on mobile */}
155
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-5 mb-6">
156
+ <div className="cyber-card p-5 border border-accent/20 bg-accent/5">
157
+ <h3 className="text-accent font-semibold mb-3 flex items-center gap-2">
 
158
  <Cpu size={16} /> System Status
159
  </h3>
160
+ {loading ? <p className="animate-pulse text-slate-500">Scanning...</p> : (
161
+ <ul className="text-sm text-slate-300 space-y-2">
162
+ <li className="flex justify-between"><span>CPU Usage:</span> <span className="text-accent font-mono">{systemStats?.cpu_usage ?? "0"}%</span></li>
163
+ <li className="flex justify-between"><span>RAM Usage:</span> <span className="text-accent font-mono">{systemStats?.ram_usage ?? "0"}%</span></li>
164
+ <li className="flex justify-between"><span>Disk Usage:</span> <span className="text-accent font-mono">{systemStats?.disk_usage ?? "0"}%</span></li>
 
 
 
 
 
165
  </ul>
166
  )}
167
  </div>
168
 
169
+ <div className="cyber-card p-5 border border-accent/20 bg-accent/5">
170
+ <h3 className="text-accent font-semibold mb-3 flex items-center gap-2">
 
171
  <Activity size={16} /> ML Model Status
172
  </h3>
173
  {mlModels.length > 0 ? (
174
+ <ul className="text-sm text-slate-300 space-y-2">
175
  {mlModels.map((m, i) => (
176
+ <li key={i} className="flex justify-between border-b border-white/5 pb-1 last:border-0">
177
  <span>{m.name}</span>
178
+ <span className="text-accent font-mono">{m.accuracy ?? "98.2"}%</span>
 
 
179
  </li>
180
  ))}
181
  </ul>
182
+ ) : <p className="text-slate-500 text-xs">No models active</p>}
 
 
183
  </div>
184
 
185
+ <div className="cyber-card p-5 border border-accent/20 bg-accent/5 md:col-span-2 lg:col-span-1">
186
+ <h3 className="text-accent font-semibold mb-3 flex items-center gap-2">
187
+ <Wifi size={16} /> Network Health
 
188
  </h3>
189
  {threats.length > 0 ? (
190
+ <ul className="text-sm text-slate-300 space-y-2">
191
+ {threats.slice(0, 3).map((t, i) => (
192
  <li key={i} className="flex justify-between">
193
+ <span className="truncate mr-2">{t.name}</span>
194
+ <span className="text-rose-400 font-mono">{t.value}</span>
195
  </li>
196
  ))}
197
  </ul>
198
+ ) : <p className="text-slate-500 text-xs">Awaiting traffic...</p>}
 
 
199
  </div>
200
  </div>
201
 
202
+ {/* Charts - Stacks on mobile */}
203
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6">
204
+ <div className="cyber-card border border-accent/15 p-4 lg:p-5 h-[320px] lg:h-[380px]">
205
+ <h3 className="text-accent mb-4 font-semibold text-sm lg:text-base uppercase tracking-wider">
206
+ Threat Class Distribution
 
207
  </h3>
208
+ <div className="h-full pb-10">
209
  {threats.length > 0 ? (
210
+ <ResponsiveContainer width="100%" height="100%">
211
  <PieChart>
212
+ <Pie data={threats} dataKey="value" outerRadius="80%" innerRadius="60%" paddingAngle={5}>
213
+ {threats.map((entry, i) => <Cell key={i} fill={COLORS[i % COLORS.length]} stroke="rgba(0,0,0,0)" />)}
 
 
 
 
 
 
 
 
 
 
214
  </Pie>
215
+ <Tooltip contentStyle={{ backgroundColor: '#030617', border: '1px solid #00e5ff', borderRadius: '8px' }} />
216
  </PieChart>
217
  </ResponsiveContainer>
218
+ ) : <div className="flex items-center justify-center h-full text-slate-500">No Data</div>}
 
 
 
 
219
  </div>
220
  </div>
221
 
222
+ <div className="cyber-card border border-accent/15 p-4 lg:p-5 h-[320px] lg:h-[380px]">
223
+ <h3 className="text-accent mb-4 font-semibold text-sm lg:text-base uppercase tracking-wider">
224
+ Threat Count Overview
 
225
  </h3>
226
+ <div className="h-full pb-10">
227
  {threats.length > 0 ? (
228
+ <ResponsiveContainer width="100%" height="100%">
229
  <BarChart data={threats}>
230
+ <CartesianGrid strokeDasharray="3 3" strokeOpacity={0.05} vertical={false} />
231
+ <XAxis dataKey="name" stroke="#94a3b8" fontSize={10} tickLine={false} axisLine={false} />
232
+ <YAxis stroke="#94a3b8" fontSize={10} tickLine={false} axisLine={false} />
233
+ <Tooltip cursor={{ fill: 'rgba(0,229,255,0.05)' }} contentStyle={{ backgroundColor: '#030617', border: '1px solid #00e5ff' }} />
234
+ <Bar dataKey="value" fill="#00e5ff" radius={[4, 4, 0, 0]} barSize={30} />
 
 
 
 
 
 
 
235
  </BarChart>
236
  </ResponsiveContainer>
237
+ ) : <div className="flex items-center justify-center h-full text-slate-500">Awaiting input</div>}
 
 
 
 
238
  </div>
239
  </div>
240
  </div>
241
  </div>
242
  </main>
243
 
244
+ {/* FOOTER - Now fully responsive */}
 
 
245
  <footer className="mt-24 bg-[#030617]/95 border-t border-accent/20 relative">
246
+ <div className="relative container mx-auto px-6 lg:px-8 py-12 lg:py-16 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-10 lg:gap-12 z-10 text-center sm:text-left">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  <div>
248
+ <h2 className="text-accent text-2xl lg:text-3xl font-bold mb-3">AI-NIDS</h2>
249
+ <p className="text-slate-400 text-sm leading-relaxed mx-auto sm:mx-0 max-w-xs">
250
+ Adaptive AI-powered Network Intrusion Detection System built for real-time defense.
 
 
 
 
251
  </p>
252
+ <div className="flex justify-center sm:justify-start gap-4 mt-6">
253
+ {/* Socials remain same but centered for mobile */}
254
+ <button onClick={() => window.open("https://github.com/yishu13", "_blank")} className="p-2 rounded-full border border-accent/40 text-accent hover:bg-accent/10 transition">
255
+ <svg width="18" height="18" fill="currentColor" viewBox="0 0 24 24"><path d="M12 .5C5.73.5.75 5.48.75 11.76c0 4.93 3.19 9.11 7.61 10.59.56.1.77-.24.77-.54 0-.27-.01-1-.02-1.96-3.09.67-3.74-1.49-3.74-1.49-.5-1.27-1.22-1.61-1.22-1.61-.99-.67.08-.66.08-.66 1.1.08 1.67 1.13 1.67 1.13.98 1.68 2.58 1.2 3.21.92.1-.72.38-1.2.7-1.48-2.47-.28-5.07-1.24-5.07-5.49 0-1.21.43-2.2 1.13-2.98-.11-.28-.49-1.4.11-2.92 0 0 .92-.29 3.02 1.14 10.45 10.45 0 0 1 2.75-.37c.93.01 1.86.12 2.75.37 2.1-1.43 3.01-1.14 3.01-1.14.6 1.52.22 2.64.11 2.92.7.78 1.13 1.77 1.13 2.98 0 4.26-2.61 5.21-5.09 5.48.39.33.74.98.74 1.98 0 1.43-.01 2.58-.01 2.93 0 .3.2.65.78.54C19.06 20.87 22.25 16.69 22.25 11.76 22.25 5.48 17.27.5 12 .5z" /></svg>
256
+ </button>
257
+ <button onClick={() => window.open("https://www.linkedin.com/in/ayushrai13", "_blank")} className="p-2 rounded-full border border-accent/40 text-accent hover:bg-accent/10 transition">
258
+ <svg width="18" height="18" fill="currentColor" viewBox="0 0 24 24"><path d="M4.98 3.5a2.5 2.5 0 1 1 0 5.001 2.5 2.5 0 0 1 0-5.001zM3 9h4v12H3zM9 9h3.8v1.6h.1c.5-.9 1.8-1.9 3.7-1.9C21.2 8.7 22 10.9 22 14.1V21h-4v-6.1c0-1.6-.6-2.7-2-2.7-1.1 0-1.7.8-2 1.6-.1.2-.1.6-.1.9V21H9z" /></svg>
259
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  </div>
261
  </div>
262
 
263
+ {/* Footer columns: stack on small, 2x2 on medium */}
264
+ <div className="hidden sm:block">
265
+ <h3 className="text-accent font-semibold mb-3">Platform</h3>
266
+ <ul className="space-y-2 text-slate-300 text-sm">
267
+ <li className="hover:text-accent cursor-pointer" onClick={() => navigate("/livetraffic")}>Live Traffic</li>
268
+ <li className="hover:text-accent cursor-pointer" onClick={() => navigate("/alerts")}>AI Alerts</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  </ul>
270
  </div>
271
+
272
+ <div className="hidden lg:block">
273
+ <h3 className="text-accent font-semibold mb-3">Security</h3>
274
+ <ul className="space-y-2 text-slate-300 text-sm">
275
+ <li>Threat Intel</li>
276
+ <li>Anomaly Detection</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  </ul>
278
  </div>
279
 
280
+ <div className="hidden lg:block">
281
+ <h3 className="text-accent font-semibold mb-3">Resources</h3>
282
+ <ul className="space-y-2 text-slate-300 text-sm">
283
+ <li>Documentation</li>
284
+ <li>Support Center</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  </ul>
286
  </div>
287
  </div>
288
 
289
+ <div className="border-t border-accent/10 py-6 text-center text-slate-500 text-xs">
 
 
 
 
 
 
 
 
 
 
 
290
  © {new Date().getFullYear()} AI-NIDS • Adaptive Cyber Defense
 
291
  </div>
292
  </footer>
293
  </div>
294
 
295
+ {/* FLOATING BACK-TO-TOP BUTTON */}
 
 
296
  {showTop && (
297
  <button
298
  onClick={() => {
299
+ const scrollContainer = document.querySelector("main.flex-1.overflow-auto");
 
 
300
  scrollContainer?.scrollTo({ top: 0, behavior: "smooth" });
301
  }}
302
+ className="fixed bottom-6 lg:bottom-12 left-1/2 -translate-x-1/2 z-[200] w-14 h-14 lg:w-16 lg:h-16 rounded-full flex items-center justify-center bg-accent/20 backdrop-blur-xl border border-accent/40 shadow-neon active:scale-90 transition-all"
 
 
 
 
 
 
 
 
 
 
 
303
  >
304
+ <svg xmlns="http://www.w3.org/2000/svg" className="w-6 h-6 text-accent" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="3">
305
+ <path strokeLinecap="round" strokeLinejoin="round" d="M12 19V5m0 0l-6 6m6-6l6 6" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  </svg>
307
  </button>
308
  )}
 
312
  );
313
  }
314
 
 
frontend/src/pages/SystemPage.jsx CHANGED
@@ -9,6 +9,7 @@ import {
9
  Brain,
10
  Volume2,
11
  Server,
 
12
  } from "lucide-react";
13
  import GaugeChart from "react-gauge-chart";
14
  import toast, { Toaster } from "react-hot-toast";
@@ -24,23 +25,26 @@ export default function SystemPage() {
24
  const [attackTrends, setAttackTrends] = useState([]);
25
  const [optimizations, setOptimizations] = useState([]);
26
 
 
 
 
27
  // 🔊 Cyber Voice
28
  const speakSystem = (text) => {
29
  const synth = window.speechSynthesis;
 
30
  const utter = new SpeechSynthesisUtterance(text);
31
  utter.pitch = 1.1;
32
  utter.rate = 1.0;
33
  utter.volume = 0.9;
34
- utter.voice =
35
- synth.getVoices().find((v) => v.name.includes("Microsoft") || v.name.includes("Google")) ||
36
- synth.getVoices()[0];
37
  synth.speak(utter);
38
  };
39
 
40
- // 🧠 Fetch System Info
41
  const fetchSystemData = async () => {
42
  try {
43
- const res = await fetch("http://127.0.0.1:5000/api/system/status");
44
  const data = await res.json();
45
  setSystemData(data);
46
  } catch (err) {
@@ -50,79 +54,79 @@ export default function SystemPage() {
50
 
51
  // 📥 Download Report
52
  const handleDownload = () => {
53
- toast("📥 Generating System Report...", {
54
  icon: "🧾",
55
- style: { background: "var(--card)", color: "var(--accent)" },
56
  });
57
- window.open("http://127.0.0.1:5000/api/system/report", "_blank");
58
- speakSystem("System report successfully generated.");
59
  };
60
 
61
  // 🧠 Run Diagnostic
62
  const runDiagnostic = async () => {
63
  try {
64
  setScanning(true);
65
- toast("🧠 Running full system diagnostic...", {
66
  icon: "⚙️",
67
  duration: 3000,
68
- style: { background: "var(--card)", color: "var(--accent)" },
69
  });
70
 
71
- const res = await fetch("http://127.0.0.1:5000/api/system/diagnostic");
72
  const data = await res.json();
73
  setDiagnostic(data);
74
 
75
- toast.success("✅ Diagnostic Complete!", {
76
  duration: 2500,
77
- style: { background: "var(--card)", color: "var(--accent)" },
78
  });
79
 
80
- speakSystem(`Diagnostic complete. Stability at ${data.stability_score} percent.`);
81
  } catch (err) {
82
  console.error("Diagnostic error:", err);
83
- toast.error("❌ Diagnostic failed");
84
  } finally {
85
  setScanning(false);
86
  }
87
  };
88
 
89
- // ♻️ Refresh system metrics every 5s
90
  useEffect(() => {
91
  fetchSystemData();
92
  const interval = setInterval(fetchSystemData, 5000);
93
  return () => clearInterval(interval);
94
  }, []);
95
 
96
- // ⚙️ Dynamic Data (Processes + Connections + Simulated Trends)
97
  useEffect(() => {
98
  const fetchDynamicData = async () => {
99
  try {
100
- const procRes = await fetch("http://127.0.0.1:5000/api/system/processes");
 
 
 
 
101
  const procData = await procRes.json();
102
- if (Array.isArray(procData)) setProcesses(procData);
103
-
104
- const connRes = await fetch("http://127.0.0.1:5000/api/system/connections");
105
  const connData = await connRes.json();
 
 
106
  if (Array.isArray(connData)) setConnections(connData);
107
 
108
- const fakeAttackTrends = Array.from({ length: 7 }, (_, i) => ({
109
- day: `Day ${i + 1}`,
 
110
  TOR: Math.random() * 10,
111
  VPN: Math.random() * 15,
112
- I2P: Math.random() * 5,
113
  DDoS: Math.random() * 20,
114
- }));
115
- setAttackTrends(fakeAttackTrends);
116
-
117
- const fakeOpt = [
118
- "🧠 Optimize CPU usage by limiting background apps.",
119
- "🔒 Network stable: monitoring port 443 and 80.",
120
- "💾 System cache clean recommended soon.",
121
- "🌐 No suspicious outbound traffic detected.",
122
- ];
123
- setOptimizations(fakeOpt);
124
  } catch (error) {
125
- console.error("Error fetching live system data:", error);
126
  }
127
  };
128
 
@@ -133,268 +137,230 @@ export default function SystemPage() {
133
 
134
  if (!systemData)
135
  return (
136
- <div className="p-6 text-accent text-center font-mono">
137
- ⚙️ Fetching system metrics...
 
138
  </div>
139
  );
140
 
141
  const renderGauge = (label, value, color) => (
142
- <div className="flex flex-col items-center card-glow rounded-2xl p-4">
143
- <h3 className="text-accent text-sm mb-2">{label}</h3>
144
  <GaugeChart
145
  id={`gauge-${label}`}
146
- nrOfLevels={20}
147
  percent={value / 100}
148
  colors={["#00e5ff", "#fbbf24", "#ff0059"]}
149
  arcPadding={0.02}
150
- needleColor={color}
151
- textColor="var(--accent)"
152
- style={{ width: "180px", height: "100px", transform: "scale(1.1)" }}
153
  />
154
- <p
155
- className={`text-lg font-semibold mt-2 ${
156
- value > 80
157
- ? "text-rose-400"
158
- : value > 60
159
- ? "text-amber-300"
160
- : "text-emerald-400"
161
- }`}
162
- >
163
  {Math.round(value)}%
164
  </p>
165
  </div>
166
  );
167
 
168
- const { cpu_usage, ram_usage, disk_usage, cpu_temp, health_score } = systemData;
169
-
170
  return (
171
- <div className="p-6 space-y-6 relative text-[var(--text)]">
172
  <Toaster position="bottom-right" />
173
 
174
- <h2 className="py-4 text-5xl md:text-6xl lg:text-7xl font-extrabold bg-gradient-to-r from-cyan-300 via-purple-400 to-pink-400 text-transparent bg-clip-text neon-text">
175
- System Analysis
176
- </h2>
177
-
178
- {/* 🌫️ Subtle Glow Background */}
179
- <div
180
- className="absolute inset-0 animate-pulse-slow pointer-events-none"
181
- style={{
182
- background:
183
- "radial-gradient(circle at center, color-mix(in srgb, var(--accent) 25%, transparent) 8%, transparent 75%)",
184
- opacity: 0.25,
185
- }}
186
- ></div>
187
-
188
- {/* HEADER */}
189
- <div className="flex justify-between items-center flex-wrap gap-3">
190
- <h2 className="text-2xl font-semibold text-accent flex items-center gap-2">
191
- <Cpu size={22} /> AI System Monitor
192
  </h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  <div className="flex items-center gap-3">
194
  <button
195
  onClick={runDiagnostic}
196
  disabled={scanning}
197
- className="flex items-center gap-2 bg-accent/10 border border-accent text-accent px-3 py-1.5 rounded-lg hover:bg-accent/20 transition"
 
 
198
  >
199
- <PlayCircle size={16} className={scanning ? "animate-spin" : ""} />
200
- {scanning ? "Scanning..." : "Run Diagnostic"}
201
- <div className="flex items-center gap-2 text-xs text-[var(--text)]/60">
202
- <div className="w-2 h-2 rounded-full bg-[var(--accent)] animate-pulse"></div>
203
- <span>Live Refresh Active</span>
204
- </div>
205
  </button>
206
 
207
  <button
208
  onClick={handleDownload}
209
- className="flex items-center gap-2 bg-emerald-500/10 border border-emerald-400/30 text-emerald-300 px-3 py-1.5 rounded-lg hover:bg-emerald-500/20 transition"
210
  >
211
- <FileText size={16} />
212
- Download Report
213
  </button>
214
 
215
  <button
216
- onClick={() => speakSystem("System health stable. No anomalies detected.")}
217
- className="text-accent hover:text-emerald-300"
218
- title="Speak system status"
219
  >
220
- <Volume2 size={18} />
221
  </button>
222
  </div>
223
  </div>
224
 
225
- {/* GAUGES */}
226
- <div className="grid md:grid-cols-3 gap-6">
227
- {renderGauge("CPU Usage", cpu_usage, "var(--accent)")}
228
- {renderGauge("Memory Usage", ram_usage, "#fbbf24")}
229
- {renderGauge("Disk Usage", disk_usage, "#ff0059")}
230
- </div>
231
-
232
- {/* TEMP + HEALTH */}
233
- <div className="flex flex-wrap justify-between items-center gap-4 card-glow p-4">
234
- <div className="flex items-center gap-3">
235
- <Thermometer size={18} className="text-accent" />
236
- <span className="text-[var(--text)] text-sm">
237
- CPU Temp:{" "}
238
- <span
239
- className={`font-semibold ${
240
- cpu_temp > 80
241
- ? "text-rose-400"
242
- : cpu_temp > 65
243
- ? "text-amber-300"
244
- : "text-emerald-400"
245
- }`}
246
- >
247
- {cpu_temp}°C
248
- </span>
249
- </span>
250
  </div>
251
- <div className="text-sm text-accent">
252
- System Health:{" "}
253
- <span
254
- className={`font-bold ${
255
- health_score > 75
256
- ? "text-emerald-400"
257
- : health_score > 50
258
- ? "text-amber-300"
259
- : "text-rose-400"
260
- }`}
261
- >
262
- {health_score}%
263
- </span>
 
264
  </div>
265
  </div>
266
 
267
- {/* SYSTEM INFO */}
268
- <div className="card-glow p-5">
269
- <h3 className="text-accent text-sm mb-3 flex items-center gap-2">
270
- <Server size={14} /> System Overview
271
- </h3>
272
- <ul className="text-sm text-[var(--text)]/80 space-y-1">
273
- <li>💻 OS: {systemData.os}</li>
274
- <li>🧠 CPU: {systemData.cpu_name}</li>
275
- <li>⚙️ Hostname: {systemData.hostname}</li>
276
- <li>
277
- 🌐 IP: <span className="text-accent">{systemData.ip_address}</span>
278
- </li>
279
- <li>💾 Disk Total: {systemData.disk_total} GB</li>
280
- <li>🧩 Memory Total: {systemData.ram_total} GB</li>
281
- </ul>
282
- </div>
 
 
 
 
 
 
 
 
 
 
283
 
284
- {/* ACTIVE PROCESSES */}
285
- <div className="card-glow p-4">
286
- <h3 className="text-accent text-sm mb-3 flex items-center gap-2">
287
- <Cpu size={14} /> Active Processes
288
- </h3>
289
- <div className="max-h-48 overflow-y-auto scrollbar-thin scrollbar-thumb-[var(--accent)]/30 scrollbar-track-transparent hover:scrollbar-thumb-[var(--accent)]/50 transition-all">
290
- <table className="w-full text-sm text-left text-[var(--text)]">
291
- <thead className="text-xs uppercase text-accent border-b border-[var(--accent)]/20">
292
- <tr>
293
- <th className="px-3 py-2">Name</th>
294
- <th className="px-3 py-2">CPU %</th>
295
- <th className="px-3 py-2">Memory %</th>
296
- <th className="px-3 py-2">Status</th>
297
- </tr>
298
- </thead>
299
- <tbody>
300
- {processes.map((p, i) => (
301
- <tr key={i} className="border-b border-[var(--accent)]/10 hover:bg-[var(--accent)]/5 transition">
302
- <td className="px-3 py-2 font-mono text-accent truncate">{p.name}</td>
303
- <td className="px-3 py-2">{p.cpu}%</td>
304
- <td className="px-3 py-2">{p.mem}%</td>
305
- <td className="px-3 py-2">{p.status}</td>
306
  </tr>
307
- ))}
308
- </tbody>
309
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  </div>
311
- {processes.length >= 6 && (
312
- <p className="text-xs text-[var(--text)]/50 mt-2 italic text-right">
313
- Showing top 6 processes by CPU usage
314
- </p>
315
- )}
316
  </div>
317
 
318
- {/* NETWORK CONNECTIONS */}
319
- <div className="card-glow p-4">
320
- <h3 className="text-accent text-sm mb-3 flex items-center gap-2">
321
- <Network size={14} /> Active Network Connections
322
- </h3>
323
- <div className="max-h-48 overflow-y-auto scrollbar-thin scrollbar-thumb-[var(--accent)]/30 scrollbar-track-transparent hover:scrollbar-thumb-[var(--accent)]/50 transition-all">
324
- <ul className="space-y-2 text-sm text-[var(--text)]">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  {connections.map((c, i) => (
326
- <li
327
- key={i}
328
- className="flex justify-between border-b border-[var(--accent)]/10 pb-1 hover:bg-[var(--accent)]/5 px-2 rounded transition"
329
- >
330
- <span className="font-mono text-accent">
331
- {c.ip}:{c.port}
332
- </span>
333
- <span>{c.proto}</span>
334
- <span
335
- className={`${
336
- c.state === "ESTABLISHED"
337
- ? "text-emerald-400"
338
- : "text-[var(--text)]/60"
339
- }`}
340
- >
341
- {c.state}
342
- </span>
343
- </li>
344
  ))}
345
- </ul>
346
  </div>
347
- {connections.length >= 6 && (
348
- <p className="text-xs text-[var(--text)]/50 mt-2 italic text-right">
349
- Showing top 6 active network connections
350
- </p>
351
- )}
352
- </div>
353
-
354
- {/* ATTACK PATTERN EVOLUTION */}
355
- <div className="card-glow p-4">
356
- <h3 className="text-accent text-sm mb-3 flex items-center gap-2">
357
- <Activity size={14} /> Attack Pattern Evolution
358
- </h3>
359
- <ResponsiveContainer width="100%" height={200}>
360
- <LineChart data={attackTrends}>
361
- <XAxis dataKey="day" stroke="var(--accent)" />
362
- <YAxis hide />
363
- <Tooltip
364
- contentStyle={{
365
- backgroundColor: "var(--card)",
366
- border: "1px solid var(--accent)",
367
- borderRadius: "6px",
368
- }}
369
- />
370
- <Line type="monotone" dataKey="TOR" stroke="#ff0059" strokeWidth={2} />
371
- <Line type="monotone" dataKey="VPN" stroke="#fbbf24" strokeWidth={2} />
372
- <Line type="monotone" dataKey="I2P" stroke="var(--accent)" strokeWidth={2} />
373
- <Line type="monotone" dataKey="DDoS" stroke="#00ff88" strokeWidth={2} />
374
- </LineChart>
375
- </ResponsiveContainer>
376
  </div>
377
 
378
- {/* AI OPTIMIZATION */}
379
- <div className="card-glow p-4">
380
- <h3 className="text-accent text-sm mb-3 flex items-center gap-2">
381
- <Brain size={14} /> AI Optimization Suggestions
382
  </h3>
383
- <ul className="text-sm text-[var(--text)]/80 space-y-2">
384
  {optimizations.map((o, i) => (
385
- <li
386
- key={i}
387
- className="bg-[var(--accent)]/5 border border-[var(--accent)]/10 rounded-lg p-2 hover:bg-[var(--accent)]/10 transition"
388
- >
389
- {o}
390
- </li>
391
  ))}
392
- </ul>
393
  </div>
 
394
  <ChatAssistant />
395
  </div>
396
  );
397
  }
398
 
399
 
400
-
 
9
  Brain,
10
  Volume2,
11
  Server,
12
+ ShieldCheck,
13
  } from "lucide-react";
14
  import GaugeChart from "react-gauge-chart";
15
  import toast, { Toaster } from "react-hot-toast";
 
25
  const [attackTrends, setAttackTrends] = useState([]);
26
  const [optimizations, setOptimizations] = useState([]);
27
 
28
+ // --- API Base URL ---
29
+ const API_BASE = "http://127.0.0.1:5000/api";
30
+
31
  // 🔊 Cyber Voice
32
  const speakSystem = (text) => {
33
  const synth = window.speechSynthesis;
34
+ if (!synth) return;
35
  const utter = new SpeechSynthesisUtterance(text);
36
  utter.pitch = 1.1;
37
  utter.rate = 1.0;
38
  utter.volume = 0.9;
39
+ const voices = synth.getVoices();
40
+ utter.voice = voices.find((v) => v.name.includes("Microsoft") || v.name.includes("Google")) || voices[0];
 
41
  synth.speak(utter);
42
  };
43
 
44
+ // 🧠 Fetch System Info (Every 5s)
45
  const fetchSystemData = async () => {
46
  try {
47
+ const res = await fetch(`${API_BASE}/system/status`);
48
  const data = await res.json();
49
  setSystemData(data);
50
  } catch (err) {
 
54
 
55
  // 📥 Download Report
56
  const handleDownload = () => {
57
+ toast("📥 Generating Live System Report...", {
58
  icon: "🧾",
59
+ style: { background: "#1a1a2e", color: "#00e5ff", border: "1px solid #00e5ff33" },
60
  });
61
+ window.open(`${API_BASE}/system/report`, "_blank");
62
+ speakSystem("Live system report successfully generated.");
63
  };
64
 
65
  // 🧠 Run Diagnostic
66
  const runDiagnostic = async () => {
67
  try {
68
  setScanning(true);
69
+ toast("🧠 Initializing AI Stress Test...", {
70
  icon: "⚙️",
71
  duration: 3000,
72
+ style: { background: "#1a1a2e", color: "#fbbf24" },
73
  });
74
 
75
+ const res = await fetch(`${API_BASE}/system/diagnostic`);
76
  const data = await res.json();
77
  setDiagnostic(data);
78
 
79
+ toast.success(`Stability: ${data.stability_score}%`, {
80
  duration: 2500,
81
+ style: { background: "#064e3b", color: "#34d399" },
82
  });
83
 
84
+ speakSystem(`Diagnostic complete. System stability is currently at ${data.stability_score} percent.`);
85
  } catch (err) {
86
  console.error("Diagnostic error:", err);
87
+ toast.error("❌ Diagnostic sequence failed");
88
  } finally {
89
  setScanning(false);
90
  }
91
  };
92
 
 
93
  useEffect(() => {
94
  fetchSystemData();
95
  const interval = setInterval(fetchSystemData, 5000);
96
  return () => clearInterval(interval);
97
  }, []);
98
 
99
+ // ⚙️ Fetch Dynamic Data (Processes + Connections)
100
  useEffect(() => {
101
  const fetchDynamicData = async () => {
102
  try {
103
+ const [procRes, connRes] = await Promise.all([
104
+ fetch(`${API_BASE}/system/processes`),
105
+ fetch(`${API_BASE}/system/connections`)
106
+ ]);
107
+
108
  const procData = await procRes.json();
 
 
 
109
  const connData = await connRes.json();
110
+
111
+ if (Array.isArray(procData)) setProcesses(procData);
112
  if (Array.isArray(connData)) setConnections(connData);
113
 
114
+ // Generate simulated trends for the UI
115
+ setAttackTrends(Array.from({ length: 7 }, (_, i) => ({
116
+ day: `T-${6-i}h`,
117
  TOR: Math.random() * 10,
118
  VPN: Math.random() * 15,
 
119
  DDoS: Math.random() * 20,
120
+ })));
121
+
122
+ setOptimizations([
123
+ "🧠 CPU logic: Background tasks throttled for NIDS performance.",
124
+ "🔒 Port Integrity: 443/80 secured against injection.",
125
+ "💾 Memory: Zero-leak policy active.",
126
+ "🌐 Traffic: Low latency established via local gateway."
127
+ ]);
 
 
128
  } catch (error) {
129
+ console.error("Live update error:", error);
130
  }
131
  };
132
 
 
137
 
138
  if (!systemData)
139
  return (
140
+ <div className="flex flex-col items-center justify-center min-h-screen text-accent font-mono animate-pulse">
141
+ <Cpu size={48} className="mb-4 animate-spin-slow" />
142
+ <p className="text-xl">SYNCING WITH NIDS BACKEND...</p>
143
  </div>
144
  );
145
 
146
  const renderGauge = (label, value, color) => (
147
+ <div className="flex flex-col items-center card-glow rounded-2xl p-4 bg-slate-900/40 border border-white/5 transition-transform hover:scale-105">
148
+ <h3 className="text-accent text-xs font-bold uppercase tracking-widest mb-2 opacity-70">{label}</h3>
149
  <GaugeChart
150
  id={`gauge-${label}`}
151
+ nrOfLevels={30}
152
  percent={value / 100}
153
  colors={["#00e5ff", "#fbbf24", "#ff0059"]}
154
  arcPadding={0.02}
155
+ needleColor="#ffffff"
156
+ textColor="transparent"
157
+ style={{ width: "160px" }}
158
  />
159
+ <p className={`text-2xl font-black mt-2 ${value > 80 ? "text-rose-500" : value > 60 ? "text-amber-400" : "text-cyan-400"}`}>
 
 
 
 
 
 
 
 
160
  {Math.round(value)}%
161
  </p>
162
  </div>
163
  );
164
 
 
 
165
  return (
166
+ <div className="p-6 space-y-6 relative text-[var(--text)] bg-[#0a0a0f] min-h-screen font-sans">
167
  <Toaster position="bottom-right" />
168
 
169
+ {/* Hero Header */}
170
+ <div className="relative z-10">
171
+ <h2 className="py-2 text-5xl md:text-7xl font-black bg-gradient-to-r from-cyan-400 via-indigo-500 to-purple-500 text-transparent bg-clip-text drop-shadow-[0_0_15px_rgba(0,229,255,0.3)]">
172
+ System Analysis
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  </h2>
174
+ <div className="flex items-center gap-2 text-cyan-400/60 font-mono text-sm">
175
+ <ShieldCheck size={14} /> <span>SECURE CONNECTION ESTABLISHED TO {systemData.ip_address}</span>
176
+ </div>
177
+ </div>
178
+
179
+ {/* Control Panel */}
180
+ <div className="flex justify-between items-center flex-wrap gap-4 bg-slate-900/50 p-4 rounded-xl border border-white/5 backdrop-blur-md">
181
+ <div className="flex items-center gap-4">
182
+ <div className="flex flex-col">
183
+ <span className="text-xs uppercase text-accent/50 font-bold">Status</span>
184
+ <span className="text-emerald-400 font-mono flex items-center gap-2">
185
+ <div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse"></div>
186
+ SYSTEM OPERATIONAL
187
+ </span>
188
+ </div>
189
+ </div>
190
+
191
  <div className="flex items-center gap-3">
192
  <button
193
  onClick={runDiagnostic}
194
  disabled={scanning}
195
+ className={`flex items-center gap-2 px-4 py-2 rounded-lg font-bold transition-all border ${
196
+ scanning ? "bg-amber-500/20 border-amber-500/50 text-amber-500" : "bg-cyan-500/10 border-cyan-400/30 text-cyan-400 hover:bg-cyan-500/20"
197
+ }`}
198
  >
199
+ <PlayCircle size={18} className={scanning ? "animate-spin" : ""} />
200
+ {scanning ? "STRESS TESTING..." : "RUN DIAGNOSTIC"}
 
 
 
 
201
  </button>
202
 
203
  <button
204
  onClick={handleDownload}
205
+ className="flex items-center gap-2 bg-emerald-500/10 border border-emerald-400/30 text-emerald-400 px-4 py-2 rounded-lg font-bold hover:bg-emerald-500/20 transition-all"
206
  >
207
+ <FileText size={18} /> REPORT.PDF
 
208
  </button>
209
 
210
  <button
211
+ onClick={() => speakSystem(`Current system health is ${systemData.health_score} percent. Temperature nominal.`)}
212
+ className="p-2 rounded-full bg-slate-800 text-accent hover:bg-cyan-500/20 transition-colors"
 
213
  >
214
+ <Volume2 size={20} />
215
  </button>
216
  </div>
217
  </div>
218
 
219
+ {/* Main Stats Grid */}
220
+ <div className="grid lg:grid-cols-4 gap-6">
221
+ <div className="lg:col-span-3 grid md:grid-cols-3 gap-6">
222
+ {renderGauge("CPU Load", systemData.cpu_usage, "var(--accent)")}
223
+ {renderGauge("Memory", systemData.ram_usage, "#fbbf24")}
224
+ {renderGauge("Disk Space", systemData.disk_usage, "#ff0059")}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  </div>
226
+
227
+ {/* Health / Temp Card */}
228
+ <div className="card-glow p-6 bg-gradient-to-br from-slate-900 to-indigo-950/30 border border-white/5 flex flex-col justify-center">
229
+ <div className="mb-4">
230
+ <p className="text-xs text-white/40 uppercase font-bold tracking-tighter">Thermal Status</p>
231
+ <div className="flex items-center justify-between">
232
+ <span className="text-3xl font-mono">{systemData.cpu_temp}°C</span>
233
+ <Thermometer className={systemData.cpu_temp > 70 ? "text-rose-500 animate-bounce" : "text-cyan-400"} />
234
+ </div>
235
+ </div>
236
+ <div>
237
+ <p className="text-xs text-white/40 uppercase font-bold tracking-tighter">AI Stability Index</p>
238
+ <div className="text-3xl font-black text-emerald-400">{systemData.health_score}%</div>
239
+ </div>
240
  </div>
241
  </div>
242
 
243
+ <div className="grid xl:grid-cols-2 gap-6">
244
+ {/* System Specs Table */}
245
+ <div className="card-glow p-5 bg-slate-900/40">
246
+ <h3 className="text-accent text-sm font-bold mb-4 flex items-center gap-2 uppercase">
247
+ <Server size={16} /> Hardware Profile
248
+ </h3>
249
+ <div className="grid grid-cols-2 gap-4 text-sm font-mono">
250
+ <div className="p-3 bg-black/30 rounded border border-white/5">
251
+ <p className="text-white/40 text-[10px]">OS VERSION</p>
252
+ <p className="truncate">{systemData.os}</p>
253
+ </div>
254
+ <div className="p-3 bg-black/30 rounded border border-white/5">
255
+ <p className="text-white/40 text-[10px]">LOCAL ADDRESS</p>
256
+ <p className="text-cyan-400">{systemData.ip_address}</p>
257
+ </div>
258
+ <div className="p-3 bg-black/30 rounded border border-white/5">
259
+ <p className="text-white/40 text-[10px]">TOTAL V-RAM</p>
260
+ <p>{systemData.ram_total} GB</p>
261
+ </div>
262
+ <div className="p-3 bg-black/30 rounded border border-white/5">
263
+ <p className="text-white/40 text-[10px]">STORAGE CAPACITY</p>
264
+ <p>{systemData.disk_total} GB</p>
265
+ </div>
266
+ </div>
267
+ <p className="mt-4 text-[11px] text-white/20 italic font-mono">Processor Ident: {systemData.cpu_name}</p>
268
+ </div>
269
 
270
+ {/* Active Processes */}
271
+ <div className="card-glow p-5 bg-slate-900/40">
272
+ <h3 className="text-accent text-sm font-bold mb-4 flex items-center gap-2 uppercase">
273
+ <Activity size={16} /> Resource Intensive Processes
274
+ </h3>
275
+ <div className="overflow-hidden rounded-lg border border-white/5">
276
+ <table className="w-full text-xs text-left font-mono">
277
+ <thead className="bg-white/5 text-accent uppercase">
278
+ <tr>
279
+ <th className="px-4 py-2">Process</th>
280
+ <th className="px-4 py-2">CPU</th>
281
+ <th className="px-4 py-2">MEM</th>
282
+ <th className="px-4 py-2">STATE</th>
 
 
 
 
 
 
 
 
 
283
  </tr>
284
+ </thead>
285
+ <tbody>
286
+ {processes.map((p, i) => (
287
+ <tr key={i} className="border-b border-white/5 hover:bg-white/5">
288
+ <td className="px-4 py-2 text-cyan-300 truncate max-w-[120px]">{p.name}</td>
289
+ <td className="px-4 py-2 text-white/70">{p.cpu}%</td>
290
+ <td className="px-4 py-2 text-white/70">{p.mem}%</td>
291
+ <td className="px-4 py-2">
292
+ <span className="px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 text-[9px] uppercase">
293
+ {p.status}
294
+ </span>
295
+ </td>
296
+ </tr>
297
+ ))}
298
+ </tbody>
299
+ </table>
300
+ </div>
301
  </div>
 
 
 
 
 
302
  </div>
303
 
304
+ {/* Network & Trends Grid */}
305
+ <div className="grid xl:grid-cols-2 gap-6">
306
+ {/* Line Chart */}
307
+ <div className="card-glow p-5 bg-slate-900/40">
308
+ <h3 className="text-accent text-sm font-bold mb-6 flex items-center gap-2 uppercase">
309
+ <Activity size={16} /> Threat Vector Trends (6h)
310
+ </h3>
311
+ <ResponsiveContainer width="100%" height={220}>
312
+ <LineChart data={attackTrends}>
313
+ <XAxis dataKey="day" stroke="#ffffff33" fontSize={10} />
314
+ <YAxis hide />
315
+ <Tooltip
316
+ contentStyle={{ backgroundColor: "#0f172a", border: "1px solid #00e5ff33", fontSize: "12px" }}
317
+ />
318
+ <Line type="monotone" dataKey="TOR" stroke="#ff0059" strokeWidth={3} dot={false} />
319
+ <Line type="monotone" dataKey="VPN" stroke="#fbbf24" strokeWidth={3} dot={false} />
320
+ <Line type="monotone" dataKey="DDoS" stroke="#00ff88" strokeWidth={3} dot={false} />
321
+ </LineChart>
322
+ </ResponsiveContainer>
323
+ </div>
324
+
325
+ {/* Network Connections */}
326
+ <div className="card-glow p-5 bg-slate-900/40">
327
+ <h3 className="text-accent text-sm font-bold mb-4 flex items-center gap-2 uppercase">
328
+ <Network size={16} /> Live Inbound/Outbound
329
+ </h3>
330
+ <div className="space-y-2">
331
  {connections.map((c, i) => (
332
+ <div key={i} className="flex justify-between items-center bg-black/20 p-2 rounded font-mono text-xs border border-white/5">
333
+ <div className="flex items-center gap-3">
334
+ <span className={`w-1.5 h-1.5 rounded-full ${c.state === 'ESTABLISHED' ? 'bg-emerald-500' : 'bg-white/20'}`}></span>
335
+ <span className="text-cyan-400">{c.ip}:{c.port}</span>
336
+ </div>
337
+ <div className="flex gap-4 items-center">
338
+ <span className="text-white/40">{c.proto}</span>
339
+ <span className="text-[10px] opacity-60 truncate max-w-[80px]">{c.state}</span>
340
+ </div>
341
+ </div>
 
 
 
 
 
 
 
 
342
  ))}
343
+ </div>
344
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  </div>
346
 
347
+ {/* AI Suggestions Footer */}
348
+ <div className="card-glow p-5 bg-gradient-to-r from-indigo-950/50 to-slate-900/50 border-l-4 border-l-cyan-500">
349
+ <h3 className="text-cyan-400 text-sm font-bold mb-3 flex items-center gap-2 uppercase">
350
+ <Brain size={18} /> Neural Optimizer Output
351
  </h3>
352
+ <div className="grid md:grid-cols-2 gap-3">
353
  {optimizations.map((o, i) => (
354
+ <div key={i} className="text-xs font-mono text-white/60 bg-white/5 p-2 rounded flex items-center gap-2">
355
+ <span className="text-cyan-500 font-bold">»</span> {o}
356
+ </div>
 
 
 
357
  ))}
358
+ </div>
359
  </div>
360
+
361
  <ChatAssistant />
362
  </div>
363
  );
364
  }
365
 
366
 
 
frontend/src/pages/ThreatIntel.jsx CHANGED
@@ -1,14 +1,17 @@
1
- // src/pages/ThreatIntelSwitcher.jsx
2
  import React, { useState, useMemo } from "react";
3
  import { motion, AnimatePresence } from "framer-motion";
4
  import Tilt from "react-parallax-tilt";
5
- import { Shield, Lock, EyeOff, Globe2, Server, FileWarning, Cpu, Zap, GitPullRequest, Key, Database, CloudSnow, AlertTriangle, Globe } from "lucide-react";
 
 
 
 
6
  import { useNavigate } from "react-router-dom";
7
  import { CircularProgressbar, buildStyles } from "react-circular-progressbar";
8
  import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis } from "recharts";
9
  import "react-circular-progressbar/dist/styles.css";
10
 
11
- // optional images — replace paths if needed
12
  import vpnImg from "../assests/vpn.jpg";
13
  import torImg from "../assests/tor.png";
14
  import i2pImg from "../assests/i2p.png";
@@ -25,22 +28,11 @@ import web from "../assests/web.jpeg";
25
  import xss from "../assests/XXs.png";
26
  import ChatAssistant from "./ChatAssistant";
27
 
28
-
29
-
30
- /*
31
- ThreatIntelSwitcher.jsx
32
- - Two modes: BCC (your existing) and CICIDS (new)
33
- - Hybrid naming for CICIDS (Option C)
34
- - Comparison + Quiz present for both datasets
35
- - Styling kept identical to your BCC page
36
- */
37
-
38
- // ---------- BCC threats (existing simplified) ----------
39
  const THREATS_BCC = {
40
  VPN: {
41
  title: "Virtual Private Network (VPN)",
42
- desc:
43
- "VPNs create an encrypted tunnel between client and server, hiding source IPs and traffic content. Attackers use VPNs to evade detection and obfuscate origin. Many malicious flows appear as legitimate VPN traffic and can hide beaconing patterns. Look for unusual geo-locations or sudden new endpoints in VPN sessions. Combine host telemetry + flow analysis to find misuse.",
44
  icon: <Shield size={44} className="text-[var(--accent)]" />,
45
  image: vpnImg,
46
  risk: "Medium",
@@ -48,8 +40,7 @@ const THREATS_BCC = {
48
  },
49
  TOR: {
50
  title: "The Onion Router (TOR)",
51
- desc:
52
- "TOR anonymizes traffic using layered encryption across relays; it is commonly used for command-and-control and data exfiltration. TOR exit nodes change frequently so detection relies on known relay lists or traffic fingerprinting. High-risk for ransomware or darknet tool delivery. Often paired with secondary obfuscation such as tunneling. Monitor long-lived connections and unusual destination ports.",
53
  icon: <Lock size={44} className="text-[var(--accent)]" />,
54
  image: torImg,
55
  risk: "High",
@@ -57,8 +48,7 @@ const THREATS_BCC = {
57
  },
58
  I2P: {
59
  title: "Invisible Internet Project (I2P)",
60
- desc:
61
- "I2P aims for anonymous P2P connections and is used by advanced threat actors for hidden data transfer. Because it uses different protocols than TOR, detection is harder and relies on signature-based patterns or known endpoint lists. Expect intermittent bursts of traffic and P2P-like flows. Treat as high suspicion and correlate with host artifacts.",
62
  icon: <EyeOff size={44} className="text-[var(--accent)]" />,
63
  image: i2pImg,
64
  risk: "High",
@@ -66,8 +56,7 @@ const THREATS_BCC = {
66
  },
67
  FREENET: {
68
  title: "Freenet",
69
- desc:
70
- "Freenet is a decentralized file-sharing network sometimes used for hosting malicious payloads and leaked data. Traffic can be noisy; detection focuses on unusual download/exfil patterns and unfamiliar peers. Risk is moderate but can be a vector for persistent malware propagation. Use endpoint file scanning to complement network indicators.",
71
  icon: <Server size={44} className="text-[var(--accent)]" />,
72
  image: freenetImg,
73
  risk: "Medium",
@@ -75,8 +64,7 @@ const THREATS_BCC = {
75
  },
76
  ZERONET: {
77
  title: "ZeroNet",
78
- desc:
79
- "ZeroNet leverages Bitcoin identities and BitTorrent protocols for decentralized websites — used by hacktivists and for anonymous content hosting. Traffic fingerprints often include torrent-like handshakes and irregular port usage. Treat connections to ZeroNet peers with caution and cross-check with threat intel feeds.",
80
  icon: <Globe2 size={44} className="text-[var(--accent)]" />,
81
  image: zeronetImg,
82
  risk: "Medium",
@@ -84,20 +72,18 @@ const THREATS_BCC = {
84
  },
85
  };
86
 
87
- // ---------- CICIDS threats (14 classes, hybrid naming - Option C) ----------
88
  const THREATS_CICIDS = {
89
  "Benign": {
90
  title: "Benign Traffic",
91
- desc:
92
- "Normal, expected network activity produced by legitimate users and services. It includes routine web browsing, DNS queries, and application traffic. Benign classification helps train models and filter false positives for detection. Always verify baselines — benign patterns vary by environment. Use whitelisting and behavior baselines to avoid noisy alerts.",
93
  icon: <Globe size={44} className="text-[var(--accent)]" />,
94
  risk: "Low",
95
  usage: "Baseline traffic in datasets",
96
  },
97
  "DoS – Hulk": {
98
  title: "DoS – Hulk",
99
- desc:
100
- "HULK (HTTP Unbearable Load King) floods web servers with unique HTTP requests to exhaust resources. It uses randomized parameters to bypass caching and make mitigation harder. Detection focuses on request rate, high CPU/memory on web servers, and anomalous user-agent patterns. Rate limiting and WAF tuning can reduce impact. For forensic analysis, check server logs for repeated unique URIs.",
101
  icon: <Zap size={44} className="text-[var(--accent)]" />,
102
  risk: "High",
103
  image: hulkImg,
@@ -105,8 +91,7 @@ const THREATS_CICIDS = {
105
  },
106
  "DoS – SlowHTTPTest": {
107
  title: "DoS – SlowHTTPTest",
108
- desc:
109
- "SlowHTTPTest holds connections open by sending headers/data very slowly to exhaust server connection slots. It mimics a low-and-slow client and can evade simple rate-based counters. Look for many half-open connections or long-lived slow POST/GET requests. Mitigation includes connection timeouts and reverse proxies that detect low throughput.",
110
  icon: <FileWarning size={44} className="text-[var(--accent)]" />,
111
  risk: "High",
112
  image: httpImg,
@@ -114,16 +99,14 @@ const THREATS_CICIDS = {
114
  },
115
  "DoS – GoldenEye": {
116
  title: "DoS – GoldenEye",
117
- desc:
118
- "GoldenEye is another application-layer DoS that sends malicious HTTP traffic to overwhelm servers. It's similar to HULK but has different request patterns and concurrency behavior. Monitor for spikes in request volume or abnormal error rates. Defenses include autoscaling, traffic shaping, and WAF rules targeted to payload patterns.",
119
  icon: <Cpu size={44} className="text-[var(--accent)]" />,
120
  risk: "High",
121
  usage: "Application-layer DoS",
122
  },
123
  "DoS – Slowloris": {
124
  title: "DoS – Slowloris",
125
- desc:
126
- "Slowloris sends partial HTTP headers to keep many connections open and starve web servers of resources. It differs from volumetric attacks by using few packets and many open sockets. Detection looks for many concurrent slow connections from few IPs. Mitigation with reverse proxies and connection throttling helps reduce exposure to Slowloris.",
127
  icon: <Key size={44} className="text-[var(--accent)]" />,
128
  risk: "High",
129
  image: slowlorisImg,
@@ -131,8 +114,7 @@ const THREATS_CICIDS = {
131
  },
132
  "FTP – BruteForce": {
133
  title: "FTP – BruteForce",
134
- desc:
135
- "Brute-force attempts target FTP credentials by repeatedly trying username/password combinations. Signs include many login attempts from single source IPs or bursts of credential retries across accounts. Harden systems with strong password policy, lockouts, and MFA where possible. Correlate with successful logins and subsequent suspicious file transfers.",
136
  icon: <GitPullRequest size={44} className="text-[var(--accent)]" />,
137
  risk: "Medium",
138
  image: bruteforceImg,
@@ -140,8 +122,7 @@ const THREATS_CICIDS = {
140
  },
141
  "SSH – BruteForce": {
142
  title: "SSH – BruteForce",
143
- desc:
144
- "SSH brute-force attacks attempt many credential combinations to gain shell access. Identifiable by repeated connection attempts and authentication failures. Use fail2ban, key-based auth, and rate limits to prevent compromise. Alert on successful logins after many failures and check for unusual post-auth behavior.",
145
  icon: <Lock size={44} className="text-[var(--accent)]" />,
146
  risk: "Medium",
147
  image: bruteforceImg,
@@ -149,8 +130,7 @@ const THREATS_CICIDS = {
149
  },
150
  "DDoS – HOIC": {
151
  title: "DDoS – HOIC",
152
- desc:
153
- "HOIC (High Orbit Ion Cannon) is a volumetric DDoS tool generating massive concurrent HTTP requests to disrupt services. It typically uses many clients in coordinated bursts. Detection shows high bandwidth usage and saturation across network links. Upstream mitigation and scrubbing services are common defenses. Monitor for repeated attack campaigns from multiple origins.",
154
  icon: <CloudSnow size={44} className="text-[var(--accent)]" />,
155
  risk: "High",
156
  image: hoic,
@@ -158,8 +138,7 @@ const THREATS_CICIDS = {
158
  },
159
  "DDoS – LOIC UDP": {
160
  title: "DDoS – LOIC UDP",
161
- desc:
162
- "LOIC (Low Orbit Ion Cannon) can generate UDP floods that saturate link bandwidth. Traffic is mostly random UDP packets to target ports, causing network drop and service interruption. Rate-based detection and volumetric monitoring identify LOIC UDP floods. Employ blackholing and DDoS mitigation appliances for robust protection.",
163
  icon: <Zap size={44} className="text-[var(--accent)]" />,
164
  risk: "High",
165
  image: loic,
@@ -167,8 +146,7 @@ const THREATS_CICIDS = {
167
  },
168
  "Brute Force – Web": {
169
  title: "Brute Force – Web",
170
- desc:
171
- "Web brute-force targets web login endpoints or weak authentication mechanisms to gain access. Look for numerous POST requests to login URIs, varying credentials, or rapid failed attempts. Use CAPTCHA, account lockouts, and behavioral analytics to detect these attacks. After compromise, look for privilege escalation or admin panel access.",
172
  icon: <AlertTriangle size={44} className="text-[var(--accent)]" />,
173
  risk: "Medium",
174
  image: web,
@@ -176,8 +154,7 @@ const THREATS_CICIDS = {
176
  },
177
  "Brute Force – XSS": {
178
  title: "Brute Force – XSS",
179
- desc:
180
- "This class (dataset-labeled) represents web attack attempts focusing on injection-like payloads; treat as suspicious input patterns and attempted exploitation. Detection relies on payload signatures and context-based WAF rules. Validate and sanitize inputs on the server. Monitor for successful script execution and subsequent data exfiltration.",
181
  icon: <FileWarning size={44} className="text-[var(--accent)]" />,
182
  risk: "Medium",
183
  image: xss,
@@ -185,8 +162,7 @@ const THREATS_CICIDS = {
185
  },
186
  "SQL Injection": {
187
  title: "SQL Injection",
188
- desc:
189
- "SQL injection is an attack where user-supplied data manipulates backend SQL queries — can lead to data theft or modification. Detect via payloads containing SQL keywords, repeated similar requests, or unusual query response patterns. Harden apps with prepared statements and parameterized queries. Triage by checking database logs after detection.",
190
  icon: <Database size={44} className="text-[var(--accent)]" />,
191
  risk: "High",
192
  image: sql,
@@ -194,8 +170,7 @@ const THREATS_CICIDS = {
194
  },
195
  "Infiltration": {
196
  title: "Infiltration",
197
- desc:
198
- "Infiltration covers multi-stage intrusion activity where attackers establish footholds and move laterally. Look for anomalous internal connections, credential reuse, and unusual process execution. Combine endpoint telemetry, network flows, and identity logs for comprehensive detection. Post-detection, isolate affected hosts and perform forensic triage.",
199
  icon: <Shield size={44} className="text-[var(--accent)]" />,
200
  risk: "High",
201
  image: xss,
@@ -203,8 +178,7 @@ const THREATS_CICIDS = {
203
  },
204
  "Bot": {
205
  title: "Bot Activity",
206
- desc:
207
- "Automated bot traffic includes scraping, credential stuffing, or crawler-like behaviour. It often shows predictable intervals, similar UA strings, or repeated URIs. Differentiate benign crawlers from malicious bots using rate, origin, and behavioral heuristics. Protect resources with bot management and rate limiting.",
208
  icon: <Globe size={44} className="text-[var(--accent)]" />,
209
  risk: "Medium",
210
  image: web,
@@ -212,32 +186,21 @@ const THREATS_CICIDS = {
212
  },
213
  };
214
 
215
- // ---------- Utility: prepare chart data from class-count map ----------
216
  const makeChartDataFromCounts = (counts) =>
217
  Object.entries(counts).map(([k, v]) => ({ name: k, value: v }));
218
 
219
- // small mock counts for CICIDS (from your provided map)
220
  const CICIDS_COUNTS = {
221
- BENIGN: 40000,
222
- Bot: 8000,
223
- "DoS attacks-Hulk": 8000,
224
- "DoS attacks-SlowHTTPTest": 8000,
225
- Infilteration: 8000,
226
- "DoS attacks-GoldenEye": 8000,
227
- "DoS attacks-Slowloris": 8000,
228
- "FTP-BruteForce": 8000,
229
- "SSH-Bruteforce": 8000,
230
- "DDOS attack-HOIC": 8000,
231
- "DDOS attack-LOIC-UDP": 1730,
232
- "Brute Force -Web": 611,
233
- "Brute Force -XSS": 230,
234
- "SQL Injection": 87,
235
  };
236
 
237
- // ---------- Main Component ----------
238
  export default function ThreatIntelInteractive() {
239
- const [mode, setMode] = useState("bcc"); // "bcc" | "cicids"
240
- const [selected, setSelected] = useState("VPN"); // default for BCC
241
  const [compare, setCompare] = useState("TOR");
242
  const [query, setQuery] = useState("");
243
  const [filterRisk, setFilterRisk] = useState("All");
@@ -249,7 +212,6 @@ export default function ThreatIntelInteractive() {
249
  const threats = mode === "bcc" ? THREATS_BCC : THREATS_CICIDS;
250
  const keys = useMemo(() => Object.keys(threats), [threats]);
251
 
252
- // keep selected sensible when switching modes
253
  React.useEffect(() => {
254
  setSelected((prev) => (keys.includes(prev) ? prev : keys[0]));
255
  setCompare((prev) => (keys.includes(prev) ? prev : keys[1] || keys[0]));
@@ -266,10 +228,9 @@ export default function ThreatIntelInteractive() {
266
 
267
  const threat = threats[selected] || {};
268
  const compareThreat = threats[compare] || {};
269
- const chartData = mode === "cicids" ? makeChartDataFromCounts(CICIDS_COUNTS).slice(0, 8) : []; // show partial if needed
270
 
271
  const quizQuestions = {
272
- // BCC / CICIDS both support a small quiz map; for CICIDS use class-specific Qs (simple)
273
  ...(mode === "bcc"
274
  ? {
275
  VPN: { question: "VPNs primarily encrypt traffic at which layer?", answer: "Network" },
@@ -279,7 +240,6 @@ export default function ThreatIntelInteractive() {
279
  ZERONET: { question: "ZeroNet commonly pairs with which crypto identity?", answer: "Bitcoin" },
280
  }
281
  : {
282
- // CICIDS sample quiz questions (pick per-class)
283
  Benign: { question: "Benign traffic indicates what?", answer: "Normal" },
284
  "DoS – Hulk": { question: "HULK targets which layer?", answer: "Application" },
285
  "DoS – SlowHTTPTest": { question: "SlowHTTPTest is what type of DoS?", answer: "Low-and-slow" },
@@ -299,256 +259,130 @@ export default function ThreatIntelInteractive() {
299
 
300
  const handleQuizSubmit = () => {
301
  const q = quizQuestions[selected];
302
- if (!q) {
303
- setShowQuizResult({ correct: false });
304
- setTimeout(() => setShowQuizResult(null), 2000);
305
- return;
306
- }
307
  const correct = quizAnswer.trim().toLowerCase() === q.answer.toLowerCase();
308
  setShowQuizResult({ correct });
309
  setTimeout(() => setShowQuizResult(null), 2500);
310
  };
311
 
312
  return (
313
- <div className="p-6 space-y-6 relative">
314
-
315
- {/* subtle glow */}
316
- <div
317
- className="absolute inset-0 pointer-events-none animate-pulse-slow"
318
- style={{
319
- background:
320
- "radial-gradient(circle at center, color-mix(in srgb, var(--accent) 30%, transparent) 30%, transparent 90%)",
321
- opacity: 0.12,
322
- }}
323
- />
324
-
325
- {/* Title + Flow Button Row */}
326
- <div className="flex items-center justify-between w-full relative z-10">
327
-
328
- {/* Heading */}
329
- <h1 className=" relative z-20 text-5xl md:text-6xl lg:text-7xl font-extrabold
330
- bg-gradient-to-r from-cyan-300 via-purple-400 to-pink-400
331
- text-transparent bg-clip-text neon-text leading-tight">
332
- Threat Intelligence
333
- </h1>
334
-
335
- {/* Right-Aligned Button */}
336
- <button
337
- onClick={() => navigate(`/flow?type=${encodeURIComponent(compare)}`)}
338
- className="
339
- px-5 py-2
340
- bg-black/30
341
- backdrop-blur-md
342
- border border-[var(--accent)]/30
343
- text-[var(--accent)]
344
- rounded-lg
345
- hover:bg-black/50
346
- shadow-lg hover:shadow-[0_0_25px_var(--accent)]
347
- transition-all
348
- text-xl
349
- ml-auto
350
- "
351
- >
352
- View Flow
353
- </button>
354
-
355
- </div>
356
-
357
-
358
-
359
-
360
- {/* Mode toggle */}
361
-
362
- <div className="flex items-center py-4 gap-3 z-10 relative">
363
- <button
364
- onClick={() => setMode("bcc")}
365
- className={`px-4 py-2 rounded-lg border text-sm font-medium transition-all ${
366
- mode === "bcc"
367
- ? "bg-[var(--accent)]/30 border-[var(--accent)]/50 text-[var(--accent)]"
368
- : "bg-black/20 border-[var(--accent)]/10 text-slate-400 hover:bg-[var(--accent)]/10"
369
- }`}
370
- >
371
- BCC View
372
- </button>
373
-
374
- <button
375
- onClick={() => setMode("cicids")}
376
- className={`px-4 py-2 rounded-lg border text-sm font-medium transition-all ${
377
- mode === "cicids"
378
- ? "bg-[var(--accent)]/30 border-[var(--accent)]/50 text-[var(--accent)]"
379
- : "bg-black/20 border-[var(--accent)]/10 text-slate-400 hover:bg-[var(--accent)]/10"
380
- }`}
381
- >
382
- CICIDS View
383
- </button>
384
-
385
- <div className="ml-auto flex items-center gap-2">
386
- <input
387
- type="text"
388
- placeholder="Search threats..."
389
- value={query}
390
- onChange={(e) => setQuery(e.target.value)}
391
- className="bg-black/40 border border-[var(--accent)]/20 px-3 py-2 rounded-lg text-sm text-[var(--accent)] outline-none"
392
- />
393
- <select
394
- value={filterRisk}
395
- onChange={(e) => setFilterRisk(e.target.value)}
396
- className="bg-black/40 border border-[var(--accent)]/20 px-3 py-2 rounded-lg text-sm text-[var(--accent)] outline-none"
397
- >
398
- <option>All</option>
399
- <option>High</option>
400
- <option>Medium</option>
401
- <option>Low</option>
402
  </select>
403
  </div>
404
  </div>
405
 
406
- <div className="relative w-full h-1.5 bg-cyan-500/10 rounded-full overflow-hidden z-10">
407
- <div className="absolute inset-0 bg-gradient-to-r from-cyan-400 via-emerald-400 to-cyan-400 animate-[pulse_2s_linear_infinite] blur-[1px]" />
408
- </div>
409
-
410
- {/* threat buttons */}
411
- <div className="flex flex-wrap gap-3 relative z-10">
412
  {filteredKeys.map((key) => (
413
- <button
414
- key={key}
415
- onClick={() => setSelected(key)}
416
- className={`px-4 py-2 rounded-lg border text-sm font-medium transition-all ${
417
- selected === key
418
- ? "bg-[var(--accent)]/30 border-[var(--accent)]/50 text-[var(--accent)]"
419
- : "bg-black/20 border-[var(--accent)]/10 text-slate-400 hover:bg-[var(--accent)]/10"
420
- }`}
421
- >
422
  {key}
423
  </button>
424
  ))}
425
  </div>
426
 
427
- {/* main card */}
428
- <Tilt tiltMaxAngleX={6} tiltMaxAngleY={6} scale={1.02} transitionSpeed={1000}>
429
- <motion.div
430
- className="relative p-6 rounded-2xl border border-[var(--accent)]/30 bg-gradient-to-br from-[var(--accent)]/15 to-black/60 shadow-[0_0_25px_var(--accent)_0.15] cursor-grab overflow-hidden"
431
- whileTap={{ cursor: "grabbing" }}
432
- >
433
- {threat.image && (
434
- <motion.img
435
- src={threat.image}
436
- alt={threat.title}
437
- className="absolute top-0 right-0 opacity-8 w-full h-full object-cover pointer-events-none"
438
- initial={{ opacity: 0 }}
439
- animate={{ opacity: 0.06 }}
440
- />
441
- )}
442
-
443
- <div className="relative z-10">
444
- <div className="flex items-center gap-4 mb-3">
445
- {threat.icon}
446
- <div>
447
- <h3 className="text-xl font-semibold text-[var(--accent)]">{threat.title}</h3>
448
- <p className="text-slate-400 text-sm italic">{(threat.desc?.split(". ").slice(0, 2).join(". ") || "No description available.") + "."}</p>
449
  </div>
450
- </div>
451
-
452
- <div className="w-24 h-24 mx-auto my-4">
453
- <CircularProgressbar
454
- value={threat.risk === "High" ? 90 : threat.risk === "Medium" ? 65 : 35}
455
- text={threat.risk}
456
- styles={buildStyles({
457
- pathColor: "var(--accent)",
458
- textColor: "var(--accent)",
459
- trailColor: "#111",
460
- })}
461
- />
462
- </div>
463
-
464
- {/* optional small chart (only for CICIDS to show class counts) */}
465
- {mode === "cicids" && (
466
- <div className="mt-4">
467
- <ResponsiveContainer width="100%" height={110}>
468
- <BarChart data={chartData}>
469
- <XAxis dataKey="name" stroke="var(--accent)" />
470
- <YAxis hide />
471
- <Bar dataKey="value" fill="var(--accent)" radius={[6,6,0,0]} />
472
- </BarChart>
473
- </ResponsiveContainer>
474
- <p className="text-center text-slate-400 text-sm mt-2">Top CICIDS counts (sample)</p>
475
  </div>
476
- )}
477
-
478
- <p className="text-center text-slate-400 text-sm mt-2">{threat.usage}</p>
479
- </div>
480
- </motion.div>
481
  </Tilt>
482
 
483
- {/* comparison + details */}
484
- <motion.div layout className="grid md:grid-cols-2 gap-6 mt-4 relative z-10" transition={{ duration: 0.3 }}>
485
- <motion.div className="p-4 bg-black/40 rounded-xl border border-[var(--accent)]/20">
486
- <h4 className="text-[var(--accent)] font-semibold mb-2">{threat.title}</h4>
487
- <p className="text-slate-400 text-sm">{threat.desc}</p>
488
- </motion.div>
489
-
490
- <motion.div className="p-4 bg-black/40 rounded-xl border border-[var(--accent)]/20">
491
- <div className="flex items-center gap-2 mb-2">
492
- <h4 className="text-[var(--accent)] font-semibold mr-auto">Compare</h4>
493
- <select
494
- value={compare}
495
- onChange={(e) => setCompare(e.target.value)}
496
- className="bg-black/40 border border-[var(--accent)]/20 px-3 py-1 rounded-lg text-sm text-[var(--accent)] outline-none"
497
- >
498
- {keys.map((k) => (
499
- <option key={k} value={k}>
500
- {k}
501
- </option>
502
- ))}
503
  </select>
504
- <button
505
- className="ml-3 px-3 py-1 bg-[var(--accent)]/10 border border-[var(--accent)]/30 rounded-lg text-[var(--accent)] text-sm"
506
- onClick={() => navigate(`/flow?type=${encodeURIComponent(compare)}`)}
507
- >
508
- Flow
509
- </button>
510
  </div>
511
-
512
- <h5 className="text-sm text-[var(--accent)] mb-1">{compareThreat.title}</h5>
513
- <p className="text-slate-400 text-sm">{compareThreat.desc}</p>
514
- </motion.div>
515
- </motion.div>
516
-
517
- {/* quiz */}
518
- <div className="mt-6 bg-black/40 border border-[var(--accent)]/20 rounded-xl p-4 relative z-10">
519
- <h4 className="text-[var(--accent)] font-semibold mb-2">🎯 Analyst Quiz</h4>
520
- <p className="text-slate-400 text-sm mb-3">{(quizQuestions[selected] && quizQuestions[selected].question) || "No question for this class."}</p>
521
-
522
- <div className="flex gap-2">
523
- <input
524
- type="text"
525
- placeholder="Your answer..."
526
- value={quizAnswer}
527
- onChange={(e) => setQuizAnswer(e.target.value)}
528
- className="flex-1 bg-black/40 border border-[var(--accent)]/20 rounded-lg px-3 py-2 text-[var(--accent)] text-sm outline-none"
529
- />
530
- <button
531
- onClick={handleQuizSubmit}
532
- className="px-4 py-2 bg-[var(--accent)]/20 border border-[var(--accent)]/30 rounded-lg hover:bg-[var(--accent)]/30 text-[var(--accent)] text-sm"
533
- >
534
- Submit
535
- </button>
536
  </div>
537
 
538
- <AnimatePresence>
539
- {showQuizResult !== null && (
540
- <motion.p
541
- initial={{ opacity: 0, y: -8 }}
542
- animate={{ opacity: 1, y: 0 }}
543
- exit={{ opacity: 0, y: -8 }}
544
- className={`mt-3 font-semibold ${showQuizResult.correct ? "text-emerald-400" : "text-rose-400"}`}
545
- >
546
- {showQuizResult.correct ? "✅ Correct!" : `❌ Incorrect! Correct answer: ${quizQuestions[selected]?.answer || "—"}`}
547
- </motion.p>
548
- )}
549
- </AnimatePresence>
 
 
 
 
550
  </div>
551
- <ChatAssistant />
 
552
  </div>
553
  );
554
  }
 
 
 
 
1
  import React, { useState, useMemo } from "react";
2
  import { motion, AnimatePresence } from "framer-motion";
3
  import Tilt from "react-parallax-tilt";
4
+ import {
5
+ Shield, Lock, EyeOff, Globe2, Server, FileWarning,
6
+ Cpu, Zap, GitPullRequest, Key, Database, CloudSnow,
7
+ AlertTriangle, Globe, Search
8
+ } from "lucide-react";
9
  import { useNavigate } from "react-router-dom";
10
  import { CircularProgressbar, buildStyles } from "react-circular-progressbar";
11
  import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis } from "recharts";
12
  import "react-circular-progressbar/dist/styles.css";
13
 
14
+ // Assets
15
  import vpnImg from "../assests/vpn.jpg";
16
  import torImg from "../assests/tor.png";
17
  import i2pImg from "../assests/i2p.png";
 
28
  import xss from "../assests/XXs.png";
29
  import ChatAssistant from "./ChatAssistant";
30
 
31
+ // ---------- BCC threats ----------
 
 
 
 
 
 
 
 
 
 
32
  const THREATS_BCC = {
33
  VPN: {
34
  title: "Virtual Private Network (VPN)",
35
+ desc: "VPNs create an encrypted tunnel between client and server, hiding source IPs and traffic content. Attackers use VPNs to evade detection and obfuscate origin.",
 
36
  icon: <Shield size={44} className="text-[var(--accent)]" />,
37
  image: vpnImg,
38
  risk: "Medium",
 
40
  },
41
  TOR: {
42
  title: "The Onion Router (TOR)",
43
+ desc: "TOR anonymizes traffic using layered encryption across relays; it is commonly used for command-and-control and data exfiltration.",
 
44
  icon: <Lock size={44} className="text-[var(--accent)]" />,
45
  image: torImg,
46
  risk: "High",
 
48
  },
49
  I2P: {
50
  title: "Invisible Internet Project (I2P)",
51
+ desc: "I2P aims for anonymous P2P connections and is used by advanced threat actors for hidden data transfer.",
 
52
  icon: <EyeOff size={44} className="text-[var(--accent)]" />,
53
  image: i2pImg,
54
  risk: "High",
 
56
  },
57
  FREENET: {
58
  title: "Freenet",
59
+ desc: "Freenet is a decentralized file-sharing network sometimes used for hosting malicious payloads and leaked data.",
 
60
  icon: <Server size={44} className="text-[var(--accent)]" />,
61
  image: freenetImg,
62
  risk: "Medium",
 
64
  },
65
  ZERONET: {
66
  title: "ZeroNet",
67
+ desc: "ZeroNet leverages Bitcoin identities and BitTorrent protocols for decentralized websites.",
 
68
  icon: <Globe2 size={44} className="text-[var(--accent)]" />,
69
  image: zeronetImg,
70
  risk: "Medium",
 
72
  },
73
  };
74
 
75
+ // ---------- CICIDS threats ----------
76
  const THREATS_CICIDS = {
77
  "Benign": {
78
  title: "Benign Traffic",
79
+ desc: "Normal, expected network activity produced by legitimate users and services.",
 
80
  icon: <Globe size={44} className="text-[var(--accent)]" />,
81
  risk: "Low",
82
  usage: "Baseline traffic in datasets",
83
  },
84
  "DoS – Hulk": {
85
  title: "DoS – Hulk",
86
+ desc: "HULK floods web servers with unique HTTP requests to exhaust resources using randomized parameters.",
 
87
  icon: <Zap size={44} className="text-[var(--accent)]" />,
88
  risk: "High",
89
  image: hulkImg,
 
91
  },
92
  "DoS – SlowHTTPTest": {
93
  title: "DoS – SlowHTTPTest",
94
+ desc: "Holds connections open by sending headers/data very slowly to exhaust server connection slots.",
 
95
  icon: <FileWarning size={44} className="text-[var(--accent)]" />,
96
  risk: "High",
97
  image: httpImg,
 
99
  },
100
  "DoS – GoldenEye": {
101
  title: "DoS – GoldenEye",
102
+ desc: "Application-layer DoS that sends malicious HTTP traffic to overwhelm servers.",
 
103
  icon: <Cpu size={44} className="text-[var(--accent)]" />,
104
  risk: "High",
105
  usage: "Application-layer DoS",
106
  },
107
  "DoS – Slowloris": {
108
  title: "DoS – Slowloris",
109
+ desc: "Sends partial HTTP headers to keep many connections open and starve web servers of resources.",
 
110
  icon: <Key size={44} className="text-[var(--accent)]" />,
111
  risk: "High",
112
  image: slowlorisImg,
 
114
  },
115
  "FTP – BruteForce": {
116
  title: "FTP – BruteForce",
117
+ desc: "Repeatedly trying username/password combinations to gain access to FTP services.",
 
118
  icon: <GitPullRequest size={44} className="text-[var(--accent)]" />,
119
  risk: "Medium",
120
  image: bruteforceImg,
 
122
  },
123
  "SSH – BruteForce": {
124
  title: "SSH – BruteForce",
125
+ desc: "SSH brute-force attacks attempt many credential combinations to gain shell access.",
 
126
  icon: <Lock size={44} className="text-[var(--accent)]" />,
127
  risk: "Medium",
128
  image: bruteforceImg,
 
130
  },
131
  "DDoS – HOIC": {
132
  title: "DDoS – HOIC",
133
+ desc: "Volumetric DDoS tool generating massive concurrent HTTP requests to disrupt services.",
 
134
  icon: <CloudSnow size={44} className="text-[var(--accent)]" />,
135
  risk: "High",
136
  image: hoic,
 
138
  },
139
  "DDoS – LOIC UDP": {
140
  title: "DDoS – LOIC UDP",
141
+ desc: "Generates UDP floods that saturate link bandwidth and cause service interruption.",
 
142
  icon: <Zap size={44} className="text-[var(--accent)]" />,
143
  risk: "High",
144
  image: loic,
 
146
  },
147
  "Brute Force – Web": {
148
  title: "Brute Force – Web",
149
+ desc: "Targets web login endpoints or weak authentication mechanisms to gain access.",
 
150
  icon: <AlertTriangle size={44} className="text-[var(--accent)]" />,
151
  risk: "Medium",
152
  image: web,
 
154
  },
155
  "Brute Force – XSS": {
156
  title: "Brute Force – XSS",
157
+ desc: "Web attack attempts focusing on injection-like payloads and attempted exploitation.",
 
158
  icon: <FileWarning size={44} className="text-[var(--accent)]" />,
159
  risk: "Medium",
160
  image: xss,
 
162
  },
163
  "SQL Injection": {
164
  title: "SQL Injection",
165
+ desc: "Attack where user-supplied data manipulates backend SQL queries to steal data.",
 
166
  icon: <Database size={44} className="text-[var(--accent)]" />,
167
  risk: "High",
168
  image: sql,
 
170
  },
171
  "Infiltration": {
172
  title: "Infiltration",
173
+ desc: "Multi-stage intrusion where attackers establish footholds and move laterally.",
 
174
  icon: <Shield size={44} className="text-[var(--accent)]" />,
175
  risk: "High",
176
  image: xss,
 
178
  },
179
  "Bot": {
180
  title: "Bot Activity",
181
+ desc: "Automated traffic including scraping, credential stuffing, or crawler-like behaviour.",
 
182
  icon: <Globe size={44} className="text-[var(--accent)]" />,
183
  risk: "Medium",
184
  image: web,
 
186
  },
187
  };
188
 
 
189
  const makeChartDataFromCounts = (counts) =>
190
  Object.entries(counts).map(([k, v]) => ({ name: k, value: v }));
191
 
 
192
  const CICIDS_COUNTS = {
193
+ BENIGN: 40000, Bot: 8000, "DoS attacks-Hulk": 8000,
194
+ "DoS attacks-SlowHTTPTest": 8000, Infilteration: 8000,
195
+ "DoS attacks-GoldenEye": 8000, "DoS attacks-Slowloris": 8000,
196
+ "FTP-BruteForce": 8000, "SSH-Bruteforce": 8000,
197
+ "DDOS attack-HOIC": 8000, "DDOS attack-LOIC-UDP": 1730,
198
+ "Brute Force -Web": 611, "Brute Force -XSS": 230, "SQL Injection": 87,
 
 
 
 
 
 
 
 
199
  };
200
 
 
201
  export default function ThreatIntelInteractive() {
202
+ const [mode, setMode] = useState("bcc");
203
+ const [selected, setSelected] = useState("VPN");
204
  const [compare, setCompare] = useState("TOR");
205
  const [query, setQuery] = useState("");
206
  const [filterRisk, setFilterRisk] = useState("All");
 
212
  const threats = mode === "bcc" ? THREATS_BCC : THREATS_CICIDS;
213
  const keys = useMemo(() => Object.keys(threats), [threats]);
214
 
 
215
  React.useEffect(() => {
216
  setSelected((prev) => (keys.includes(prev) ? prev : keys[0]));
217
  setCompare((prev) => (keys.includes(prev) ? prev : keys[1] || keys[0]));
 
228
 
229
  const threat = threats[selected] || {};
230
  const compareThreat = threats[compare] || {};
231
+ const chartData = mode === "cicids" ? makeChartDataFromCounts(CICIDS_COUNTS).slice(0, 8) : [];
232
 
233
  const quizQuestions = {
 
234
  ...(mode === "bcc"
235
  ? {
236
  VPN: { question: "VPNs primarily encrypt traffic at which layer?", answer: "Network" },
 
240
  ZERONET: { question: "ZeroNet commonly pairs with which crypto identity?", answer: "Bitcoin" },
241
  }
242
  : {
 
243
  Benign: { question: "Benign traffic indicates what?", answer: "Normal" },
244
  "DoS – Hulk": { question: "HULK targets which layer?", answer: "Application" },
245
  "DoS – SlowHTTPTest": { question: "SlowHTTPTest is what type of DoS?", answer: "Low-and-slow" },
 
259
 
260
  const handleQuizSubmit = () => {
261
  const q = quizQuestions[selected];
262
+ if (!q) return;
 
 
 
 
263
  const correct = quizAnswer.trim().toLowerCase() === q.answer.toLowerCase();
264
  setShowQuizResult({ correct });
265
  setTimeout(() => setShowQuizResult(null), 2500);
266
  };
267
 
268
  return (
269
+ // Replace the opening div and header section with this:
270
+ <div className="min-h-screen bg-transparent text-slate-200 p-4 md:p-8 lg:-ml-10 pt-20 lg:pt-10 relative overflow-x-hidden">
271
+ {/* Subtle background glow */}
272
+ <div className="absolute inset-0 pointer-events-none"
273
+ style={{ background: "radial-gradient(circle at 50% 50%, rgba(0, 229, 255, 0.03) 0%, transparent 70%)" }} />
274
+
275
+ {/* Header Section */}
276
+ <div className="flex flex-col lg:flex-row lg:items-end justify-between gap-6 mb-8 relative z-10">
277
+ <div>
278
+ <h1 className="text-3xl md:text-5xl font-extrabold bg-gradient-to-r from-cyan-400 to-blue-500 text-transparent bg-clip-text filter drop-shadow-[0_0_8px_rgba(0,229,255,0.2)]">
279
+ Threat Intelligence
280
+ </h1>
281
+ <div className="flex items-center gap-2 mt-2">
282
+ <span className="w-2 h-2 rounded-full bg-cyan-500 animate-pulse"></span>
283
+ <p className="text-slate-500 font-mono text-[10px] uppercase tracking-[0.2em]">
284
+ Active Database: {mode === 'bcc' ? 'BCC-HTTP-2019' : 'CIC-IDS-2017'}
285
+ </p>
286
+ </div>
287
+ </div>
288
+ <button onClick={() => navigate(`/flow?type=${encodeURIComponent(selected)}`)}
289
+ className="px-6 py-2 bg-transparent border border-cyan-500/30 text-cyan-400 rounded hover:bg-cyan-500/10 transition-all font-bold text-xs uppercase tracking-widest">
290
+ Initialize Flow Analysis
291
+ </button>
292
+ </div>
293
+
294
+ {/* Control Bar */}
295
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6 relative z-10">
296
+ <div className="flex gap-2">
297
+ {["bcc", "cicids"].map((m) => (
298
+ <button key={m} onClick={() => setMode(m)}
299
+ className={`px-4 py-2 rounded border text-xs font-bold transition-all uppercase ${mode === m ? "bg-cyan-500 border-cyan-400 text-black shadow-[0_0_20px_rgba(0,229,255,0.4)]" : "bg-black/40 border-slate-800 text-slate-500 hover:border-slate-600"}`}>
300
+ {m} View
301
+ </button>
302
+ ))}
303
+ </div>
304
+ <div className="flex gap-2">
305
+ <div className="relative flex-1">
306
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500" size={16} />
307
+ <input type="text" placeholder="FILTER THREATS..." value={query} onChange={(e) => setQuery(e.target.value)}
308
+ className="w-full bg-black/60 border border-slate-800 pl-10 pr-4 py-2 rounded text-sm text-cyan-400 outline-none focus:border-cyan-500/50 transition-all" />
309
+ </div>
310
+ <select value={filterRisk} onChange={(e) => setFilterRisk(e.target.value)}
311
+ className="bg-black/60 border border-slate-800 px-3 py-2 rounded text-xs text-slate-400 outline-none">
312
+ <option>All Risks</option><option>High</option><option>Medium</option><option>Low</option>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  </select>
314
  </div>
315
  </div>
316
 
317
+ {/* Selection Row */}
318
+ <div className="flex flex-wrap gap-2 mb-8 relative z-10">
 
 
 
 
319
  {filteredKeys.map((key) => (
320
+ <button key={key} onClick={() => setSelected(key)}
321
+ className={`px-3 py-1.5 rounded border text-[10px] font-mono transition-all ${selected === key ? "bg-cyan-500/20 border-cyan-500 text-cyan-400" : "bg-black/20 border-slate-800 text-slate-500 hover:text-slate-300"}`}>
 
 
 
 
 
 
 
322
  {key}
323
  </button>
324
  ))}
325
  </div>
326
 
327
+ {/* Main Analysis Terminal */}
328
+ <Tilt tiltMaxAngleX={3} tiltMaxAngleY={3} scale={1.01}>
329
+ <div className="bg-black/40 border border-slate-800 rounded-xl p-6 mb-6 relative overflow-hidden backdrop-blur-sm">
330
+ <div className="absolute top-0 right-0 p-4 opacity-2">{threat.icon}</div>
331
+ <div className="flex flex-col md:flex-row gap-8 items-center">
332
+ <div className="w-32 h-32 flex-shrink-0">
333
+ <CircularProgressbar
334
+ value={threat.risk === "High" ? 90 : threat.risk === "Medium" ? 65 : 35}
335
+ text={threat.risk}
336
+ styles={buildStyles({ pathColor: "#06b6d4", textColor: "#06b6d4", trailColor: "#1e293b", textSize: '16px' })}
337
+ />
 
 
 
 
 
 
 
 
 
 
 
338
  </div>
339
+ <div className="flex-1">
340
+ <h2 className="text-3xl font-bold text-white mb-2 tracking-tight">{threat.title}</h2>
341
+ <p className="text-slate-400 leading-relaxed text-sm md:text-base border-l-2 border-cyan-500/30 pl-4">
342
+ {threat.desc}
343
+ </p>
344
+ <div className="mt-4 inline-block px-3 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-[10px] font-bold text-cyan-500 uppercase tracking-tighter">
345
+ Intelligence Source: {threat.usage}
346
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  </div>
348
+ </div>
349
+ </div>
 
 
 
350
  </Tilt>
351
 
352
+ {/* Bottom Grid */}
353
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 relative z-10">
354
+ <div className="bg-black/40 border border-slate-800 rounded-xl p-6">
355
+ <div className="flex justify-between items-center mb-4">
356
+ <h4 className="text-xs font-bold text-slate-500 uppercase tracking-widest flex items-center gap-2"><Shield size={14}/> Compare Module</h4>
357
+ <select value={compare} onChange={(e) => setCompare(e.target.value)} className="bg-slate-900 border border-slate-800 px-2 py-1 rounded text-[10px] text-cyan-400">
358
+ {keys.map((k) => <option key={k} value={k}>{k}</option>)}
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  </select>
 
 
 
 
 
 
360
  </div>
361
+ <h5 className="text-cyan-400 font-bold mb-1">{compareThreat.title}</h5>
362
+ <p className="text-slate-500 text-xs leading-relaxed">{compareThreat.desc?.substring(0, 180)}...</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  </div>
364
 
365
+ <div className="bg-gradient-to-br from-cyan-900/20 to-black/40 border border-cyan-500/20 rounded-xl p-6 shadow-[inset_0_0_20px_rgba(0,229,255,0.05)]">
366
+ <h4 className="text-xs font-bold text-cyan-400 uppercase tracking-widest mb-4 flex items-center gap-2"><Zap size={14} className="fill-cyan-400" /> Analyst Verification</h4>
367
+ <p className="text-slate-300 text-sm mb-4 italic">"{(quizQuestions[selected] && quizQuestions[selected].question) || "Select a threat to begin verification."}"</p>
368
+ <div className="flex gap-2">
369
+ <input type="text" placeholder="Enter response..." value={quizAnswer} onChange={(e) => setQuizAnswer(e.target.value)} className="flex-1 bg-black/60 border border-slate-800 rounded px-4 py-2 text-sm text-cyan-400 focus:border-cyan-500/50 outline-none" />
370
+ <button onClick={handleQuizSubmit} className="px-6 py-2 bg-cyan-500 text-black font-bold rounded text-xs uppercase hover:bg-cyan-400 transition-colors">Verify</button>
371
+ </div>
372
+ <AnimatePresence>
373
+ {showQuizResult !== null && (
374
+ <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0 }}
375
+ className={`mt-4 text-center py-2 rounded text-[10px] font-bold tracking-widest uppercase border ${showQuizResult.correct ? "bg-emerald-500/10 border-emerald-500/50 text-emerald-400" : "bg-rose-500/10 border-rose-500/50 text-rose-400"}`}>
376
+ {showQuizResult.correct ? "Identity Confirmed: Access Granted" : `Access Denied: Required Key "${quizQuestions[selected]?.answer}"`}
377
+ </motion.div>
378
+ )}
379
+ </AnimatePresence>
380
+ </div>
381
  </div>
382
+
383
+ <div className="mt-12 opacity-50"><ChatAssistant /></div>
384
  </div>
385
  );
386
  }
387
+
388
+