larxius commited on
Commit
5f10ca5
·
verified ·
1 Parent(s): 079d29a

Update frontend/src/pages/Dashboard.jsx

Browse files
Files changed (1) hide show
  1. frontend/src/pages/Dashboard.jsx +27 -15
frontend/src/pages/Dashboard.jsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useRef, useCallback } from 'react';
2
  import { Link, useNavigate } from 'react-router-dom';
3
  import { useAuth } from '../components/AuthContext';
4
  import { LabelList, ComposedChart, RadialBarChart, RadialBar, RadarChart, Radar, PolarGrid, PolarAngleAxis, PolarRadiusAxis, AreaChart, Area, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip as RechartsTooltip, ResponsiveContainer, PieChart, Pie, Cell, Legend, BarChart, Bar } from 'recharts';
@@ -268,13 +268,23 @@ export const Dashboard = () => {
268
  const counts = summary?.vulnerabilities_count || { critical: 0, high: 0, medium: 0, low: 0, total: 0 };
269
 
270
  // Real-time dynamic security score calculation
271
- const score = summary?.average_security_score ?? 100;
272
- const dashOffset = 283 - (283 * score) / 100;
273
-
274
- let scoreLabel = 'Excellent';
275
- let scoreColorClass = 'text-primary';
276
- if (score < 50) { scoreLabel = 'Critical'; scoreColorClass = 'text-error'; }
277
- else if (score < 80) { scoreLabel = 'Warning'; scoreColorClass = 'text-tertiary'; }
 
 
 
 
 
 
 
 
 
 
278
 
279
  const getRatingGrade = (s) => {
280
  if (s === null || s === undefined) return '--';
@@ -625,7 +635,7 @@ export const Dashboard = () => {
625
  <circle
626
  className="transition-all duration-1000 ease-out"
627
  cx="50" cy="50" fill="none" r="45"
628
- stroke={score < 50 ? '#ba1a1a' : score < 80 ? '#bc4800' : '#004ac6'}
629
  strokeDasharray="283"
630
  strokeDashoffset={dashOffset}
631
  strokeLinecap="round"
@@ -633,12 +643,14 @@ export const Dashboard = () => {
633
  />
634
  </svg>
635
  <div className="text-center flex flex-col items-center z-10">
636
- <span className="font-display-lg text-display-lg text-primary tracking-tighter">{score}</span>
637
- <span className={`font-label-sm text-label-sm uppercase tracking-widest bg-primary/10 px-xs py-[2px] rounded-sm mt-xs ${scoreColorClass}`}>
 
 
638
  {scoreLabel}
639
  </span>
640
  <span className="font-label-sm text-label-sm text-on-surface-variant/70 mt-base">
641
- {score >= 80 ? 'System Protected' : 'Remediation Required'}
642
  </span>
643
  </div>
644
  </div>
@@ -646,12 +658,12 @@ export const Dashboard = () => {
646
  <div className="flex items-center justify-between text-body-sm font-body-sm border-t border-outline-variant pt-sm mt-sm">
647
  <span className="text-on-surface-variant">Live security posture</span>
648
  <span className={`font-medium flex items-center ${
649
- score >= 80 ? 'text-green-600' : score >= 50 ? 'text-orange-600' : 'text-error'
650
  }`}>
651
  <span className="material-symbols-outlined text-[16px] mr-[2px]">
652
- {score >= 80 ? 'trending_up' : score >= 50 ? 'trending_flat' : 'trending_down'}
653
  </span>
654
- {score >= 80 ? 'Stable' : score >= 50 ? 'Needs Attention' : 'Critical Risk'}
655
  </span>
656
  </div>
657
  </div>
 
1
+ import { useState, useEffect, useRef, useCallback } from 'react';
2
  import { Link, useNavigate } from 'react-router-dom';
3
  import { useAuth } from '../components/AuthContext';
4
  import { LabelList, ComposedChart, RadialBarChart, RadialBar, RadarChart, Radar, PolarGrid, PolarAngleAxis, PolarRadiusAxis, AreaChart, Area, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip as RechartsTooltip, ResponsiveContainer, PieChart, Pie, Cell, Legend, BarChart, Bar } from 'recharts';
 
268
  const counts = summary?.vulnerabilities_count || { critical: 0, high: 0, medium: 0, low: 0, total: 0 };
269
 
270
  // Real-time dynamic security score calculation
271
+ const rawScore = summary?.average_security_score;
272
+ const hasCompletedScans = (summary?.scans_count > 0 || recentScans.some(s => s.status === 'completed')) && rawScore !== null && rawScore !== undefined;
273
+
274
+ const score = hasCompletedScans ? Math.round(rawScore) : null;
275
+ const dashOffset = hasCompletedScans ? (283 - (283 * score) / 100) : 283;
276
+
277
+ let scoreDisplay = hasCompletedScans ? score : 'N/A';
278
+ let scoreLabel = hasCompletedScans ? 'Excellent' : 'Not Tested Yet';
279
+ let scoreColorClass = hasCompletedScans ? 'text-primary bg-primary/10' : 'text-slate-400 bg-slate-500/10 border border-slate-500/20';
280
+ let scoreSubtext = hasCompletedScans
281
+ ? (score >= 80 ? 'System Protected' : 'Remediation Required')
282
+ : 'No Scans Performed Yet';
283
+
284
+ if (hasCompletedScans) {
285
+ if (score < 50) { scoreLabel = 'Critical'; scoreColorClass = 'text-error bg-error/10'; }
286
+ else if (score < 80) { scoreLabel = 'Warning'; scoreColorClass = 'text-tertiary bg-tertiary/10'; }
287
+ }
288
 
289
  const getRatingGrade = (s) => {
290
  if (s === null || s === undefined) return '--';
 
635
  <circle
636
  className="transition-all duration-1000 ease-out"
637
  cx="50" cy="50" fill="none" r="45"
638
+ stroke={!hasCompletedScans ? '#94a3b8' : score < 50 ? '#ba1a1a' : score < 80 ? '#bc4800' : '#004ac6'}
639
  strokeDasharray="283"
640
  strokeDashoffset={dashOffset}
641
  strokeLinecap="round"
 
643
  />
644
  </svg>
645
  <div className="text-center flex flex-col items-center z-10">
646
+ <span className={`font-display-lg text-display-lg tracking-tighter ${hasCompletedScans ? 'text-primary' : 'text-slate-400'}`}>
647
+ {scoreDisplay}
648
+ </span>
649
+ <span className={`font-label-sm text-label-sm uppercase tracking-widest px-xs py-[2px] rounded-sm mt-xs ${scoreColorClass}`}>
650
  {scoreLabel}
651
  </span>
652
  <span className="font-label-sm text-label-sm text-on-surface-variant/70 mt-base">
653
+ {scoreSubtext}
654
  </span>
655
  </div>
656
  </div>
 
658
  <div className="flex items-center justify-between text-body-sm font-body-sm border-t border-outline-variant pt-sm mt-sm">
659
  <span className="text-on-surface-variant">Live security posture</span>
660
  <span className={`font-medium flex items-center ${
661
+ !hasCompletedScans ? 'text-slate-500' : score >= 80 ? 'text-green-600' : score >= 50 ? 'text-orange-600' : 'text-error'
662
  }`}>
663
  <span className="material-symbols-outlined text-[16px] mr-[2px]">
664
+ {!hasCompletedScans ? 'sensors_off' : score >= 80 ? 'trending_up' : score >= 50 ? 'trending_flat' : 'trending_down'}
665
  </span>
666
+ {!hasCompletedScans ? 'Pending Initial Scan' : score >= 80 ? 'Stable' : score >= 50 ? 'Needs Attention' : 'Critical Risk'}
667
  </span>
668
  </div>
669
  </div>