larxius commited on
Commit
b73e5e2
·
verified ·
1 Parent(s): 9005748

Update frontend/src/pages/LogsAndThreats.jsx

Browse files
Files changed (1) hide show
  1. frontend/src/pages/LogsAndThreats.jsx +185 -149
frontend/src/pages/LogsAndThreats.jsx CHANGED
@@ -199,16 +199,25 @@ const LogsAndThreats = () => {
199
  const getThreatDetail = (t) => {
200
  if (!t) return null;
201
  const titleKey = typeof t === 'string' ? t : (t.title || '');
202
- const kb = THREAT_KNOWLEDGE_BASE[titleKey] || {};
 
 
 
 
 
 
 
 
 
203
  return {
204
- title: titleKey,
205
  count: t.count || 1,
206
  severity: t.severity || kb.severity || 'Medium',
207
  category: t.category || kb.category || 'Security Headers',
208
- cvss: t.cvss_score || kb.cvss || 5.3,
209
- owasp: t.owasp_category || kb.owasp || 'A05:2021 - Security Misconfiguration',
210
  cwe: t.cwe_ids && t.cwe_ids.length ? t.cwe_ids : (kb.cwe || ['CWE-693']),
211
- description: t.description && t.description.length > 30 ? t.description : (kb.description || `Security intelligence scan detected "${titleKey}" across active system endpoints.`),
212
  impact: t.impact || kb.impact || 'Unpatched or missing security settings increase risk of exploitation, unauthorized data access, or service disruption.',
213
  remediation: t.remediation && t.remediation.length > 20 ? t.remediation : (kb.remediation || 'add_header Cross-Origin-Embedder-Policy "require-corp" always;'),
214
  affected_targets: t.affected_targets && t.affected_targets.length ? t.affected_targets : (kb.affected_targets || ['https://app.larshield.io'])
@@ -224,8 +233,35 @@ const LogsAndThreats = () => {
224
  return 'bg-blue-500/15 text-blue-600 dark:text-blue-400 border-blue-500/30';
225
  };
226
 
227
- // Threat Details Calculations
228
- const allThreatDetails = trends.map(t => getThreatDetail(t)).filter(Boolean);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
230
  // Stats Counters
231
  const criticalCount = allThreatDetails.filter(t => t.severity.toLowerCase() === 'critical').length;
@@ -426,6 +462,142 @@ const LogsAndThreats = () => {
426
  );
427
  }
428
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
  // Full Page Threat Intelligence View Mode
430
  if (isFullThreatsView) {
431
  return (
@@ -655,8 +827,7 @@ const LogsAndThreats = () => {
655
  return (
656
  <tr
657
  key={i}
658
- onClick={() => setSelectedThreat(detail)}
659
- className="hover:bg-surface-container-high/60 transition-colors cursor-pointer group"
660
  >
661
  <td className="p-3.5 text-center font-extrabold text-[12px] text-error">
662
  {rowIdx}
@@ -773,10 +944,10 @@ const LogsAndThreats = () => {
773
  </>
774
  )}
775
  </div>
 
776
  </div>
777
  );
778
  }
779
-
780
  // Full Page Audit Logs Mode
781
  if (isFullLogsView) {
782
  return (
@@ -991,6 +1162,7 @@ const LogsAndThreats = () => {
991
  </>
992
  )}
993
  </div>
 
994
  </div>
995
  );
996
  }
@@ -1041,12 +1213,7 @@ const LogsAndThreats = () => {
1041
  return (
1042
  <li
1043
  key={i}
1044
- onClick={(e) => {
1045
- e.preventDefault();
1046
- setSelectedThreat(detail);
1047
- }}
1048
- className="py-3 px-3 rounded-xl flex flex-col sm:flex-row sm:items-center justify-between gap-3 hover:bg-surface-container-high/70 cursor-pointer transition-all group border border-transparent hover:border-primary/30 my-1"
1049
- title="Click to view full threat details & remediation guide"
1050
  >
1051
  <div className="flex items-start gap-3 pr-2">
1052
  <span className="w-7 h-7 rounded-full bg-error/10 text-error flex items-center justify-center text-[12px] font-extrabold shrink-0 mt-0.5 border border-error/20">
@@ -1191,139 +1358,8 @@ const LogsAndThreats = () => {
1191
  </div>
1192
  </div>
1193
 
1194
- {/* Global Threat Detail Modal - High Tech Premium Design (z-[9999] so top layout header never clips it) */}
1195
- {selectedThreat && (
1196
- <div className="fixed inset-0 bg-black/80 backdrop-blur-md flex items-center justify-center p-4 pt-20 z-[9999] animate-fade-in overflow-y-auto">
1197
- <div className="bg-surface border border-outline-variant rounded-2xl max-w-2xl w-full shadow-2xl relative my-auto overflow-hidden flex flex-col max-h-[85vh]">
1198
-
1199
- {/* Header Banner with Gradient */}
1200
- <div className="bg-gradient-to-r from-surface-container-highest via-surface-container to-surface-container-low p-6 border-b border-outline-variant relative">
1201
- <button
1202
- onClick={() => setSelectedThreat(null)}
1203
- className="absolute top-4 right-4 text-on-surface-variant hover:text-on-surface bg-surface-container-high p-2 rounded-full transition-colors cursor-pointer border border-outline-variant/60"
1204
- >
1205
- <X className="w-5 h-5" />
1206
- </button>
1207
-
1208
- <div className="flex items-center gap-2 flex-wrap mb-3 pr-10">
1209
- <span className={`px-3 py-1 rounded-full text-[11px] font-black uppercase tracking-wider border shadow-2xs ${getSeverityBadgeClass(selectedThreat.severity)}`}>
1210
- {selectedThreat.severity} SEVERITY
1211
- </span>
1212
- <span className="bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black px-3 py-1 rounded-full border border-cyan-500/30">
1213
- CVSS {selectedThreat.cvss}
1214
- </span>
1215
- <span className="bg-red-500/10 text-red-600 dark:text-red-400 text-[11px] font-black px-3 py-1 rounded-full border border-red-500/30 flex items-center gap-1">
1216
- <ShieldAlert className="w-3.5 h-3.5" />
1217
- {selectedThreat.count} Detections Recorded
1218
- </span>
1219
- </div>
1220
-
1221
- <h2 className="text-[21px] font-extrabold text-on-surface tracking-tight leading-snug">
1222
- {selectedThreat.title}
1223
- </h2>
1224
- </div>
1225
-
1226
- {/* Modal Body Scroll Container */}
1227
- <div className="p-6 space-y-5 overflow-y-auto text-[13.5px]">
1228
-
1229
- {/* Category & OWASP Specifications Cards */}
1230
- <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
1231
- <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
1232
- <span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
1233
- <Layers className="w-3.5 h-3.5 text-primary" /> Vulnerability Category
1234
- </span>
1235
- <span className="font-extrabold text-on-surface text-[14px]">{selectedThreat.category}</span>
1236
- </div>
1237
- <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
1238
- <span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
1239
- <Shield className="w-3.5 h-3.5 text-primary" /> OWASP Standard
1240
- </span>
1241
- <span className="font-extrabold text-primary text-[14px]">{selectedThreat.owasp}</span>
1242
- </div>
1243
- </div>
1244
-
1245
- {/* Threat Overview Card */}
1246
- <div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-primary border border-outline-variant/60 shadow-2xs">
1247
- <h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2">
1248
- <Shield className="w-4 h-4 text-primary" /> Threat Overview
1249
- </h3>
1250
- <p className="text-on-surface-variant leading-relaxed">
1251
- {selectedThreat.description}
1252
- </p>
1253
- </div>
1254
-
1255
- {/* Security Impact Card */}
1256
- <div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-amber-500 border border-outline-variant/60 shadow-2xs">
1257
- <h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2 text-amber-600 dark:text-amber-400">
1258
- <AlertTriangle className="w-4 h-4" /> Exploitation & Impact Risk
1259
- </h3>
1260
- <p className="text-on-surface-variant leading-relaxed">
1261
- {selectedThreat.impact}
1262
- </p>
1263
- </div>
1264
-
1265
- {/* Code Remediation Terminal Box */}
1266
- <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
1267
- <div className="flex items-center justify-between mb-2">
1268
- <h3 className="font-bold text-on-surface text-[14px] flex items-center gap-2 text-green-600 dark:text-green-400">
1269
- <Terminal className="w-4 h-4" /> Recommended Remediation Command
1270
- </h3>
1271
- <button
1272
- onClick={() => copyToClipboard(selectedThreat.remediation)}
1273
- className="flex items-center gap-1 px-2.5 py-1 bg-surface-container hover:bg-surface-container-high text-on-surface rounded-lg text-[11.5px] font-bold border border-outline-variant cursor-pointer transition-all"
1274
- >
1275
- {copiedCode ? <Check className="w-3.5 h-3.5 text-green-500" /> : <Copy className="w-3.5 h-3.5" />}
1276
- {copiedCode ? 'Copied!' : 'Copy Code'}
1277
- </button>
1278
- </div>
1279
-
1280
- <div className="bg-[#0b132a] text-[#38bdf8] font-mono text-[12.5px] p-4 rounded-xl border border-slate-800 leading-relaxed overflow-x-auto shadow-inner">
1281
- {selectedThreat.remediation}
1282
- </div>
1283
- </div>
1284
-
1285
- {/* Affected Target Endpoints */}
1286
- {selectedThreat.affected_targets && selectedThreat.affected_targets.length > 0 && (
1287
- <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
1288
- <h3 className="font-bold text-on-surface text-[14px] mb-2.5 flex items-center gap-2">
1289
- <ExternalLink className="w-4 h-4 text-primary" /> Affected Target Endpoints ({selectedThreat.affected_targets.length})
1290
- </h3>
1291
- <div className="flex flex-wrap gap-2">
1292
- {selectedThreat.affected_targets.map((url, idx) => (
1293
- <span key={idx} className="bg-surface-container border border-outline-variant/80 text-on-surface font-mono text-[12px] px-3 py-1.5 rounded-lg flex items-center gap-2 font-medium">
1294
- <span className="w-2 h-2 rounded-full bg-red-500 animate-pulse"></span>
1295
- {url}
1296
- </span>
1297
- ))}
1298
- </div>
1299
- </div>
1300
- )}
1301
- </div>
1302
-
1303
- {/* Modal Actions Footer */}
1304
- <div className="p-4 bg-surface-container-lowest border-t border-outline-variant flex items-center justify-between flex-wrap gap-3">
1305
- <button
1306
- onClick={() => {
1307
- const query = selectedThreat.title;
1308
- setSelectedThreat(null);
1309
- openFullLogsView(query);
1310
- }}
1311
- className="px-4 py-2.5 bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-xl font-bold text-[13px] flex items-center gap-2 cursor-pointer transition-colors"
1312
- >
1313
- <Search className="w-4 h-4" />
1314
- Filter Audit Logs for this Threat
1315
- </button>
1316
-
1317
- <button
1318
- onClick={() => setSelectedThreat(null)}
1319
- className="px-6 py-2.5 bg-primary text-white hover:brightness-110 rounded-xl font-bold text-[13px] cursor-pointer border-0 shadow-md shadow-primary/20 transition-all"
1320
- >
1321
- Close Window
1322
- </button>
1323
- </div>
1324
- </div>
1325
- </div>
1326
- )}
1327
  </div>
1328
  );
1329
  };
 
199
  const getThreatDetail = (t) => {
200
  if (!t) return null;
201
  const titleKey = typeof t === 'string' ? t : (t.title || '');
202
+
203
+ // Intelligent fuzzy matching for Knowledge Base lookup
204
+ const kbKey = Object.keys(THREAT_KNOWLEDGE_BASE).find(k =>
205
+ k.toLowerCase() === titleKey.toLowerCase() ||
206
+ titleKey.toLowerCase().includes(k.toLowerCase()) ||
207
+ k.toLowerCase().includes(titleKey.toLowerCase()) ||
208
+ (titleKey.toLowerCase().includes('cve') && k.toLowerCase().includes('cve'))
209
+ );
210
+ const kb = (kbKey ? THREAT_KNOWLEDGE_BASE[kbKey] : null) || {};
211
+
212
  return {
213
+ title: titleKey || kbKey || 'Security Vulnerability',
214
  count: t.count || 1,
215
  severity: t.severity || kb.severity || 'Medium',
216
  category: t.category || kb.category || 'Security Headers',
217
+ cvss: t.cvss_score || t.cvss || kb.cvss || 5.3,
218
+ owasp: t.owasp_category || t.owasp || kb.owasp || 'A05:2021 - Security Misconfiguration',
219
  cwe: t.cwe_ids && t.cwe_ids.length ? t.cwe_ids : (kb.cwe || ['CWE-693']),
220
+ description: t.description && t.description.length > 20 ? t.description : (kb.description || `Security intelligence scan detected "${titleKey}" across active system endpoints.`),
221
  impact: t.impact || kb.impact || 'Unpatched or missing security settings increase risk of exploitation, unauthorized data access, or service disruption.',
222
  remediation: t.remediation && t.remediation.length > 20 ? t.remediation : (kb.remediation || 'add_header Cross-Origin-Embedder-Policy "require-corp" always;'),
223
  affected_targets: t.affected_targets && t.affected_targets.length ? t.affected_targets : (kb.affected_targets || ['https://app.larshield.io'])
 
233
  return 'bg-blue-500/15 text-blue-600 dark:text-blue-400 border-blue-500/30';
234
  };
235
 
236
+ // Threat Details Calculations (Merge KB + Live API Trends)
237
+ const mergedThreatsMap = new Map();
238
+ Object.keys(THREAT_KNOWLEDGE_BASE).forEach(key => {
239
+ mergedThreatsMap.set(key, getThreatDetail({ title: key, count: 1 }));
240
+ });
241
+
242
+ if (Array.isArray(trends) && trends.length > 0) {
243
+ trends.forEach(t => {
244
+ const detail = getThreatDetail(t);
245
+ if (detail && detail.title) {
246
+ const existingKey = Array.from(mergedThreatsMap.keys()).find(k =>
247
+ k.toLowerCase() === detail.title.toLowerCase() ||
248
+ k.toLowerCase().includes(detail.title.toLowerCase()) ||
249
+ detail.title.toLowerCase().includes(k.toLowerCase())
250
+ );
251
+ if (existingKey) {
252
+ mergedThreatsMap.set(existingKey, {
253
+ ...mergedThreatsMap.get(existingKey),
254
+ ...detail,
255
+ count: detail.count || mergedThreatsMap.get(existingKey).count || 1
256
+ });
257
+ } else {
258
+ mergedThreatsMap.set(detail.title, detail);
259
+ }
260
+ }
261
+ });
262
+ }
263
+
264
+ const allThreatDetails = Array.from(mergedThreatsMap.values());
265
 
266
  // Stats Counters
267
  const criticalCount = allThreatDetails.filter(t => t.severity.toLowerCase() === 'critical').length;
 
462
  );
463
  }
464
 
465
+ const renderThreatModal = () => {
466
+ if (!selectedThreat) return null;
467
+ return (
468
+ <div className="fixed inset-0 bg-black/80 backdrop-blur-md flex items-center justify-center p-4 pt-20 z-[9999] animate-fade-in overflow-y-auto">
469
+ <div className="bg-surface border border-outline-variant rounded-2xl max-w-2xl w-full shadow-2xl relative my-auto overflow-hidden flex flex-col max-h-[85vh]">
470
+
471
+ {/* Header Banner with Gradient */}
472
+ <div className="bg-gradient-to-r from-surface-container-highest via-surface-container to-surface-container-low p-6 border-b border-outline-variant relative">
473
+ <button
474
+ onClick={() => setSelectedThreat(null)}
475
+ className="absolute top-4 right-4 text-on-surface-variant hover:text-on-surface bg-surface-container-high p-2 rounded-full transition-colors cursor-pointer border border-outline-variant/60"
476
+ >
477
+ <X className="w-5 h-5" />
478
+ </button>
479
+
480
+ <div className="flex items-center gap-2 flex-wrap mb-3 pr-10">
481
+ <span className={`px-3 py-1 rounded-full text-[11px] font-black uppercase tracking-wider border shadow-2xs ${getSeverityBadgeClass(selectedThreat.severity)}`}>
482
+ {selectedThreat.severity} SEVERITY
483
+ </span>
484
+ <span className="bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black px-3 py-1 rounded-full border border-cyan-500/30">
485
+ CVSS {selectedThreat.cvss}
486
+ </span>
487
+ <span className="bg-red-500/10 text-red-600 dark:text-red-400 text-[11px] font-black px-3 py-1 rounded-full border border-red-500/30 flex items-center gap-1">
488
+ <ShieldAlert className="w-3.5 h-3.5" />
489
+ {selectedThreat.count} Detections Recorded
490
+ </span>
491
+ </div>
492
+
493
+ <h2 className="text-[21px] font-extrabold text-on-surface tracking-tight leading-snug">
494
+ {selectedThreat.title}
495
+ </h2>
496
+ </div>
497
+
498
+ {/* Modal Body Scroll Container */}
499
+ <div className="p-6 space-y-5 overflow-y-auto text-[13.5px]">
500
+
501
+ {/* Category & OWASP Specifications Cards */}
502
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
503
+ <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
504
+ <span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
505
+ <Layers className="w-3.5 h-3.5 text-primary" /> Vulnerability Category
506
+ </span>
507
+ <span className="font-extrabold text-on-surface text-[14px]">{selectedThreat.category}</span>
508
+ </div>
509
+ <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
510
+ <span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
511
+ <Shield className="w-3.5 h-3.5 text-primary" /> OWASP Standard
512
+ </span>
513
+ <span className="font-extrabold text-primary text-[14px]">{selectedThreat.owasp}</span>
514
+ </div>
515
+ </div>
516
+
517
+ {/* Threat Overview Card */}
518
+ <div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-primary border border-outline-variant/60 shadow-2xs">
519
+ <h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2">
520
+ <Shield className="w-4 h-4 text-primary" /> Threat Overview
521
+ </h3>
522
+ <p className="text-on-surface-variant leading-relaxed">
523
+ {selectedThreat.description}
524
+ </p>
525
+ </div>
526
+
527
+ {/* Security Impact Card */}
528
+ <div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-amber-500 border border-outline-variant/60 shadow-2xs">
529
+ <h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2 text-amber-600 dark:text-amber-400">
530
+ <AlertTriangle className="w-4 h-4" /> Exploitation & Impact Risk
531
+ </h3>
532
+ <p className="text-on-surface-variant leading-relaxed">
533
+ {selectedThreat.impact}
534
+ </p>
535
+ </div>
536
+
537
+ {/* Code Remediation Terminal Box */}
538
+ <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
539
+ <div className="flex items-center justify-between mb-2">
540
+ <h3 className="font-bold text-on-surface text-[14px] flex items-center gap-2 text-green-600 dark:text-green-400">
541
+ <Terminal className="w-4 h-4" /> Recommended Remediation Command
542
+ </h3>
543
+ <button
544
+ onClick={() => copyToClipboard(selectedThreat.remediation)}
545
+ className="flex items-center gap-1 px-2.5 py-1 bg-surface-container hover:bg-surface-container-high text-on-surface rounded-lg text-[11.5px] font-bold border border-outline-variant cursor-pointer transition-all"
546
+ >
547
+ {copiedCode ? <Check className="w-3.5 h-3.5 text-green-500" /> : <Copy className="w-3.5 h-3.5" />}
548
+ {copiedCode ? 'Copied!' : 'Copy Code'}
549
+ </button>
550
+ </div>
551
+
552
+ <div className="bg-[#0b132a] text-[#38bdf8] font-mono text-[12.5px] p-4 rounded-xl border border-slate-800 leading-relaxed overflow-x-auto shadow-inner whitespace-pre-wrap">
553
+ {selectedThreat.remediation}
554
+ </div>
555
+ </div>
556
+
557
+ {/* Affected Target Endpoints */}
558
+ {selectedThreat.affected_targets && selectedThreat.affected_targets.length > 0 && (
559
+ <div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
560
+ <h3 className="font-bold text-on-surface text-[14px] mb-2.5 flex items-center gap-2">
561
+ <ExternalLink className="w-4 h-4 text-primary" /> Affected Target Endpoints ({selectedThreat.affected_targets.length})
562
+ </h3>
563
+ <div className="flex flex-wrap gap-2">
564
+ {selectedThreat.affected_targets.map((url, idx) => (
565
+ <span key={idx} className="bg-surface-container border border-outline-variant/80 text-on-surface font-mono text-[12px] px-3 py-1.5 rounded-lg flex items-center gap-2 font-medium">
566
+ <span className="w-2 h-2 rounded-full bg-red-500 animate-pulse"></span>
567
+ {url}
568
+ </span>
569
+ ))}
570
+ </div>
571
+ </div>
572
+ )}
573
+ </div>
574
+
575
+ {/* Modal Actions Footer */}
576
+ <div className="p-4 bg-surface-container-lowest border-t border-outline-variant flex items-center justify-between flex-wrap gap-3">
577
+ <button
578
+ onClick={() => {
579
+ const query = selectedThreat.title;
580
+ setSelectedThreat(null);
581
+ openFullLogsView(query);
582
+ }}
583
+ className="px-4 py-2.5 bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-xl font-bold text-[13px] flex items-center gap-2 cursor-pointer transition-colors"
584
+ >
585
+ <Search className="w-4 h-4" />
586
+ Filter Audit Logs for this Threat
587
+ </button>
588
+
589
+ <button
590
+ onClick={() => setSelectedThreat(null)}
591
+ className="px-6 py-2.5 bg-primary text-white hover:brightness-110 rounded-xl font-bold text-[13px] cursor-pointer border-0 shadow-md shadow-primary/20 transition-all"
592
+ >
593
+ Close Window
594
+ </button>
595
+ </div>
596
+ </div>
597
+ </div>
598
+ );
599
+ };
600
+
601
  // Full Page Threat Intelligence View Mode
602
  if (isFullThreatsView) {
603
  return (
 
827
  return (
828
  <tr
829
  key={i}
830
+ className="hover:bg-surface-container-high/60 transition-colors group"
 
831
  >
832
  <td className="p-3.5 text-center font-extrabold text-[12px] text-error">
833
  {rowIdx}
 
944
  </>
945
  )}
946
  </div>
947
+ {selectedThreat && renderThreatModal()}
948
  </div>
949
  );
950
  }
 
951
  // Full Page Audit Logs Mode
952
  if (isFullLogsView) {
953
  return (
 
1162
  </>
1163
  )}
1164
  </div>
1165
+ {selectedThreat && renderThreatModal()}
1166
  </div>
1167
  );
1168
  }
 
1213
  return (
1214
  <li
1215
  key={i}
1216
+ className="py-3 px-3 rounded-xl flex flex-col sm:flex-row sm:items-center justify-between gap-3 hover:bg-surface-container-high/40 transition-all group my-1"
 
 
 
 
 
1217
  >
1218
  <div className="flex items-start gap-3 pr-2">
1219
  <span className="w-7 h-7 rounded-full bg-error/10 text-error flex items-center justify-center text-[12px] font-extrabold shrink-0 mt-0.5 border border-error/20">
 
1358
  </div>
1359
  </div>
1360
 
1361
+ {/* Global Threat Detail Modal */}
1362
+ {selectedThreat && renderThreatModal()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1363
  </div>
1364
  );
1365
  };