diff --git a/frontend/src/components/Dashboard.tsx b/frontend/src/components/Dashboard.tsx index 0ba062de0..7b3c7dfd7 100644 --- a/frontend/src/components/Dashboard.tsx +++ b/frontend/src/components/Dashboard.tsx @@ -28,7 +28,10 @@ import { MenuItem, Accordion, AccordionSummary, - AccordionDetails + AccordionDetails, + FormControlLabel, + Switch, + Divider } from '@mui/material'; import { TrendingUp, @@ -38,7 +41,8 @@ import { ExpandMore, Upload, Person, - AccountBalance + AccountBalance, + Settings as SettingsIcon } from '@mui/icons-material'; interface DashboardStats { @@ -69,7 +73,7 @@ const Dashboard: React.FC = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [testResult, setTestResult] = useState(null); - + // New state for enhanced features const [customDialogOpen, setCustomDialogOpen] = useState(false); const [bulkDialogOpen, setBulkDialogOpen] = useState(false); @@ -79,6 +83,10 @@ const Dashboard: React.FC = () => { const [bulkTransactions, setBulkTransactions] = useState([]); const [bulkResults, setBulkResults] = useState([]); + // Settings state + const [isDarkMode, setIsDarkMode] = useState(false); + const [isHighContrast, setIsHighContrast] = useState(false); + // Updated API URL to match our working backend const API_BASE = 'http://localhost:8000'; @@ -88,19 +96,73 @@ const Dashboard: React.FC = () => { return () => clearInterval(interval); }, []); + // Load settings from localStorage + useEffect(() => { + const savedDarkMode = localStorage.getItem('darkMode'); + const savedHighContrast = localStorage.getItem('highContrast'); + + if (savedDarkMode !== null) { + setIsDarkMode(JSON.parse(savedDarkMode)); + } + + if (savedHighContrast !== null) { + setIsHighContrast(JSON.parse(savedHighContrast)); + } + }, []); + + // Apply dark mode theme + useEffect(() => { + if (isDarkMode) { + document.documentElement.classList.add('dark'); + document.body.style.backgroundColor = '#121212'; + document.body.style.color = '#ffffff'; + } else { + document.documentElement.classList.remove('dark'); + document.body.style.backgroundColor = '#ffffff'; + document.body.style.color = '#000000'; + } + }, [isDarkMode]); + + // Apply high contrast + useEffect(() => { + if (isHighContrast) { + document.documentElement.classList.add('high-contrast'); + document.body.style.filter = 'contrast(150%)'; + } else { + document.documentElement.classList.remove('high-contrast'); + document.body.style.filter = 'none'; + } + }, [isHighContrast]); + + // Handle Dark Mode toggle + const handleDarkModeToggle = (event: React.ChangeEvent) => { + const newValue = event.target.checked; + setIsDarkMode(newValue); + localStorage.setItem('darkMode', JSON.stringify(newValue)); + console.log(`Dark Mode ${newValue ? 'enabled' : 'disabled'}`); + }; + + // Handle High Contrast toggle + const handleHighContrastToggle = (event: React.ChangeEvent) => { + const newValue = event.target.checked; + setIsHighContrast(newValue); + localStorage.setItem('highContrast', JSON.stringify(newValue)); + console.log(`High Contrast ${newValue ? 'enabled' : 'disabled'}`); + }; + const fetchDashboardData = async () => { try { // Fetch dashboard stats const statsResponse = await fetch(`${API_BASE}/api/stats`); const statsData = await statsResponse.json(); - + // Add missing fields with defaults const enhancedStats = { ...statsData, pending_alerts: statsData.recent_alerts || 0, fraud_rate: statsData.fraud_rate || 0 }; - + setStats(enhancedStats); setLoading(false); } catch (err) { @@ -124,15 +186,15 @@ const Dashboard: React.FC = () => { const response = await fetch(`${API_BASE}/api/predict`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ + body: JSON.stringify({ amount: amount, merchant: merchant, card_type: 'credit' }) }); - + const result = await response.json(); - + // Convert result to Transaction interface const transaction: Transaction = { id: result.transaction_id || Date.now(), @@ -145,7 +207,7 @@ const Dashboard: React.FC = () => { timestamp: new Date().toISOString(), transaction_type: 'credit_card' }; - + setTestResult(transaction); } catch (err) { setError(`Failed to test fraud detection: ${err}`); @@ -163,15 +225,15 @@ const Dashboard: React.FC = () => { const response = await fetch(`${API_BASE}/api/predict`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ + body: JSON.stringify({ amount: parseFloat(customAmount), merchant: customMerchant, transaction_type: customTransactionType }) }); - + const result = await response.json(); - + const transaction: Transaction = { id: Date.now(), transaction_id: result.transaction_id, @@ -183,7 +245,7 @@ const Dashboard: React.FC = () => { timestamp: new Date().toISOString(), transaction_type: customTransactionType }; - + setTestResult(transaction); setCustomDialogOpen(false); setCustomAmount(''); @@ -208,7 +270,7 @@ const Dashboard: React.FC = () => { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(transaction) }); - + const result = await response.json(); results.push({ ...transaction, @@ -224,7 +286,7 @@ const Dashboard: React.FC = () => { }); } } - + setBulkResults(results); }; @@ -278,15 +340,15 @@ const Dashboard: React.FC = () => { - - - - - -