Spaces:
Sleeping
Sleeping
| import React, { useState, useEffect, useCallback } from 'react'; | |
| import { apiService } from './services/api'; | |
| import { formatNumber, getRiskLevel, formatTime, getDeviceInfo, getProgressBarStyle } from './utils/formatters'; | |
| import HelpModal from './components/HelpModal'; | |
| import RiskCard from './components/RiskCard'; | |
| import EvidenceCard from './components/EvidenceCard'; | |
| import DeviceTrustCard from './components/DeviceTrustCard'; | |
| import HeuristicsCard from './components/HeuristicsCard'; | |
| import MlModelCard from './components/MlModelCard'; | |
| import MachinesCard from './components/MachinesCard'; | |
| import RiskHistoryCard from './components/RiskHistoryCard'; | |
| import Controls from './components/Controls'; | |
| function App() { | |
| const [data, setData] = useState({ | |
| riskAssessment: null, | |
| riskHistory: [], | |
| modelMeta: null, | |
| trustedDevices: [], | |
| machines: [], | |
| }); | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState(null); | |
| const [showHelp, setShowHelp] = useState(false); | |
| const [lastUpdate, setLastUpdate] = useState(null); | |
| // Fetch all data | |
| const fetchAllData = useCallback(async () => { | |
| try { | |
| setError(null); | |
| const [riskAssessment, riskHistory, modelMeta, trustedDevices, machines] = await Promise.all([ | |
| apiService.getRiskAssessment('demo-machine').catch(() => null), | |
| apiService.getRiskHistory('demo-machine', 20).catch(() => []), | |
| apiService.getModelMeta().catch(() => null), | |
| apiService.getTrustedDevices().catch(() => []), | |
| apiService.getMachines().catch(() => []), | |
| ]); | |
| setData({ | |
| riskAssessment, | |
| riskHistory, | |
| modelMeta, | |
| trustedDevices, | |
| machines, | |
| }); | |
| setLastUpdate(new Date()); | |
| } catch (err) { | |
| setError(err.message); | |
| console.error('Failed to fetch data:', err); | |
| } | |
| }, []); | |
| // Auto-refresh every 2 seconds | |
| useEffect(() => { | |
| fetchAllData(); | |
| const interval = setInterval(fetchAllData, 2000); | |
| return () => clearInterval(interval); | |
| }, [fetchAllData]); | |
| // Handle demo actions | |
| const handleSeedDemo = async () => { | |
| setLoading(true); | |
| try { | |
| await apiService.seedDemo(); | |
| await fetchAllData(); // Refresh data after seeding | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleClearDemo = async () => { | |
| setLoading(true); | |
| try { | |
| await apiService.clearDemo(); | |
| await fetchAllData(); // Refresh data after clearing | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleEvictStale = async () => { | |
| setLoading(true); | |
| try { | |
| await apiService.evictStale(); | |
| await fetchAllData(); // Refresh data after evicting | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleRefreshModel = async () => { | |
| setLoading(true); | |
| try { | |
| await fetchAllData(); // Refresh all data including model info | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| if (error) { | |
| return ( | |
| <div className="dashboard"> | |
| <div className="card" style={{ gridColumn: '1 / -1', textAlign: 'center' }}> | |
| <h3>⚠️ Error</h3> | |
| <p style={{ color: '#dc2626', marginBottom: '16px' }}>{error}</p> | |
| <button className="btn" onClick={fetchAllData}> | |
| Retry | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className="dashboard"> | |
| <RiskCard | |
| riskAssessment={data.riskAssessment} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| <EvidenceCard | |
| riskAssessment={data.riskAssessment} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| <DeviceTrustCard | |
| trustedDevices={data.trustedDevices} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| <HeuristicsCard | |
| riskAssessment={data.riskAssessment} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| <MlModelCard | |
| riskAssessment={data.riskAssessment} | |
| modelMeta={data.modelMeta} | |
| onRefresh={handleRefreshModel} | |
| onShowHelp={() => setShowHelp(true)} | |
| loading={loading} | |
| /> | |
| <MachinesCard | |
| machines={data.machines} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| <RiskHistoryCard | |
| riskHistory={data.riskHistory} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| <Controls | |
| onSeedDemo={handleSeedDemo} | |
| onClearDemo={handleClearDemo} | |
| onEvictStale={handleEvictStale} | |
| loading={loading} | |
| onShowHelp={() => setShowHelp(true)} | |
| /> | |
| {lastUpdate && ( | |
| <div style={{ | |
| gridColumn: '1 / -1', | |
| textAlign: 'center', | |
| fontSize: '12px', | |
| color: '#64748b', | |
| marginTop: '16px' | |
| }}> | |
| Last updated: {formatTime(lastUpdate)} | |
| </div> | |
| )} | |
| <HelpModal | |
| isOpen={showHelp} | |
| onClose={() => setShowHelp(false)} | |
| /> | |
| </div> | |
| ); | |
| } | |
| export default App; | |