QuantumShield / frontend /app /page.tsx
SantoshKumar1310's picture
Upload folder using huggingface_hub
49e53ae verified
'use client';
import { useState, useEffect, useCallback } from 'react';
import {
RefreshCw, Shield, AlertTriangle, CheckCircle, TrendingUp,
Activity, Zap
} from 'lucide-react';
import Sidebar from '@/components/Sidebar';
import SimulationEngine from '@/components/SimulationEngine';
import ChatPanel from '@/components/ChatPanel';
// Use environment variable or relative URL for production
const API_URL = process.env.NEXT_PUBLIC_API_URL || '';
interface Transaction {
id: number;
amount: number;
merchant: string;
category: string;
is_fraud: number;
prediction: string;
final_score: number;
classical_score: number;
quantum_score: number;
quantum_details: {
vqc: number;
qaoa: number;
qnn: number;
};
}
interface Metrics {
total: number;
flagged: number;
actual_fraud: number;
accuracy: number;
precision: number;
recall: number;
f1: number;
tp: number;
fp: number;
tn: number;
fn: number;
}
export default function Home() {
const [mounted, setMounted] = useState(false);
const [activeTab, setActiveTab] = useState('dashboard');
const [isRunning, setIsRunning] = useState(false);
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [metrics, setMetrics] = useState<Metrics>({
total: 0, flagged: 0, actual_fraud: 0, accuracy: 0, precision: 0, recall: 0, f1: 0, tp: 0, fp: 0, tn: 0, fn: 0
});
const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
// Hydration fix
useEffect(() => {
setMounted(true);
setLastUpdated(new Date());
}, []);
// Stable callbacks for SimulationEngine
const handleTransactionUpdate = useCallback((transaction: Transaction, newMetrics: Metrics) => {
setTransactions(prev => [transaction, ...prev].slice(0, 50));
setMetrics(newMetrics);
setLastUpdated(new Date());
}, []);
const handleRunningChange = useCallback((running: boolean) => {
setIsRunning(running);
}, []);
// Manual refresh
const processOneTransaction = useCallback(async () => {
try {
const response = await fetch(`${API_URL}/api/process-random`);
if (response.ok) {
const data = await response.json();
handleTransactionUpdate(data.transaction, data.metrics);
}
} catch (error) {
console.error('Failed to process transaction:', error);
}
}, [handleTransactionUpdate]);
const getRiskColor = (score: number) => {
if (score >= 0.7) return 'text-red-700 bg-red-100';
if (score >= 0.4) return 'text-amber-700 bg-amber-100';
return 'text-green-700 bg-green-100';
};
const getRiskLevel = (score: number) => {
if (score >= 0.7) return { label: 'HIGH', color: 'text-red-600 bg-red-50 border-red-200' };
if (score >= 0.4) return { label: 'MEDIUM', color: 'text-amber-600 bg-amber-50 border-amber-200' };
return { label: 'LOW', color: 'text-green-600 bg-green-50 border-green-200' };
};
// Page titles and descriptions
const pageInfo: Record<string, { title: string; subtitle: string }> = {
dashboard: { title: 'Dashboard', subtitle: 'Live Transaction Monitoring' },
models: { title: 'Model Performance', subtitle: 'Quantum & Classical Model Analysis' },
settings: { title: 'Settings', subtitle: 'System Configuration' },
};
const currentPage = pageInfo[activeTab] || pageInfo.dashboard;
return (
<div className="min-h-screen bg-gray-50 flex">
<Sidebar activeTab={activeTab} onTabChange={setActiveTab} />
<div className="flex-1 ml-16">
{/* Header */}
<header className="sticky top-0 z-40 backdrop-blur-xl bg-white/90 border-b border-gray-200 px-4 py-3 shadow-sm">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold text-gray-900">{currentPage.title}</h1>
<p className="text-xs text-gray-500">{currentPage.subtitle}</p>
</div>
<div className="flex items-center gap-3">
{/* System Status */}
<div className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm ${isRunning ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-500'}`}>
<div className={`w-2 h-2 rounded-full ${isRunning ? 'bg-green-500 animate-pulse' : 'bg-gray-400'}`} />
{isRunning ? 'Processing' : 'Idle'}
</div>
{/* Model Status */}
<div className="hidden md:flex items-center gap-1.5 bg-amber-100 text-amber-700 rounded-lg px-3 py-1.5 text-sm">
<Zap className="w-3.5 h-3.5 text-amber-500" />
<span>Quantum Ready</span>
</div>
{/* Transaction Count */}
<div className="hidden lg:flex items-center gap-1.5 bg-gray-100 text-gray-600 rounded-lg px-3 py-1.5 text-sm">
<Activity className="w-3.5 h-3.5" />
<span>{metrics.total} txns</span>
</div>
{/* Refresh */}
<button onClick={processOneTransaction} className="p-2 hover:bg-gray-100 rounded-lg transition-colors" title="Process one transaction">
<RefreshCw className="w-4 h-4 text-gray-500" />
</button>
</div>
</div>
<p className="text-[10px] text-gray-400 mt-1" suppressHydrationWarning>
Last updated: {mounted && lastUpdated ? lastUpdated.toLocaleTimeString() : '--:--:--'}
</p>
</header>
<main className="p-4">
{/* Dashboard View */}
{activeTab === 'dashboard' && (
<>
{/* Simulation Engine - Isolated Component */}
<SimulationEngine
onTransactionUpdate={handleTransactionUpdate}
onRunningChange={handleRunningChange}
/>
{/* Stats Row */}
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-3 mb-4">
<StatCard icon={<Activity className="w-4 h-4" />} label="Transactions" value={metrics.total} color="white" />
<StatCard icon={<AlertTriangle className="w-4 h-4" />} label="Flagged" value={metrics.flagged} color="yellow" />
<StatCard icon={<Shield className="w-4 h-4" />} label="Actual Fraud" value={metrics.actual_fraud} color="red" />
<StatCard icon={<CheckCircle className="w-4 h-4" />} label="Accuracy" value={`${(metrics.accuracy * 100).toFixed(1)}%`} color="green" />
<StatCard icon={<TrendingUp className="w-4 h-4" />} label="Precision" value={`${(metrics.precision * 100).toFixed(1)}%`} color="green" />
<StatCard icon={<Zap className="w-4 h-4" />} label="F1 Score" value={`${(metrics.f1 * 100).toFixed(1)}%`} color="yellow" />
</div>
{/* Main Grid */}
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4">
{/* Transaction Table */}
<div className="xl:col-span-2 bg-white rounded-xl border border-gray-200 overflow-hidden shadow-sm">
<div className="px-4 py-3 border-b border-gray-200 flex items-center justify-between">
<h3 className="text-gray-900 font-bold text-sm uppercase tracking-wide">Live Transactions</h3>
<span className="text-xs text-gray-500">{transactions.length} records</span>
</div>
<div className="overflow-x-auto max-h-[400px] overflow-y-auto">
<table className="w-full text-sm">
<thead className="bg-gray-50 sticky top-0">
<tr className="text-gray-600 text-xs">
<th className="px-3 py-2 text-left">ID</th>
<th className="px-3 py-2 text-left">Amount</th>
<th className="px-3 py-2 text-left">Category</th>
<th className="px-3 py-2 text-left">
<div className="flex items-center gap-1">
<span className="text-blue-600">C</span>/<span className="text-purple-600">Q</span>
</div>
</th>
<th className="px-3 py-2 text-left">Final</th>
<th className="px-3 py-2 text-left">Risk</th>
<th className="px-3 py-2 text-left">Prediction</th>
<th className="px-3 py-2 text-left">Actual</th>
</tr>
</thead>
<tbody>
{transactions.length === 0 ? (
<tr><td colSpan={8} className="px-3 py-8 text-center text-gray-400 text-sm">Click &quot;Start&quot; to begin processing transactions</td></tr>
) : (
transactions.map((tx, idx) => {
const risk = getRiskLevel(tx.final_score);
return (
<tr key={tx.id} className={`border-b border-gray-100 hover:bg-gray-50 transition-colors ${idx === 0 ? 'bg-blue-50 animate-pulse' : ''}`}>
<td className="px-3 py-2 text-gray-500 font-mono text-xs">#{tx.id}</td>
<td className="px-3 py-2 text-gray-900 font-medium">${tx.amount.toFixed(2)}</td>
<td className="px-3 py-2 text-gray-500 text-xs">{tx.category}</td>
<td className="px-3 py-2">
<div className="flex items-center gap-1">
<span className="text-xs text-blue-600 font-medium">{((tx.classical_score || tx.final_score * 0.8) * 100).toFixed(0)}%</span>
<span className="text-gray-400">/</span>
<span className="text-xs text-purple-600 font-medium">{((tx.quantum_score || tx.final_score * 0.2) * 100).toFixed(0)}%</span>
</div>
</td>
<td className="px-3 py-2">
<span className={`px-2 py-0.5 rounded text-xs font-medium ${getRiskColor(tx.final_score)}`}>
{(tx.final_score * 100).toFixed(0)}%
</span>
</td>
<td className="px-3 py-2">
<span className={`px-2 py-0.5 rounded text-xs font-semibold border ${risk.color}`}>
{risk.label}
</span>
</td>
<td className="px-3 py-2">
<span className={`px-2 py-0.5 rounded text-xs ${tx.prediction === 'Fraud' ? 'bg-red-100 text-red-700' : 'bg-green-100 text-green-700'}`}>
{tx.prediction}
</span>
</td>
<td className="px-3 py-2">
<span className={`px-2 py-0.5 rounded text-xs ${tx.is_fraud ? 'bg-red-100 text-red-700' : 'bg-green-100 text-green-700'}`}>
{tx.is_fraud ? 'Fraud' : 'Legit'}
</span>
</td>
</tr>
);
})
)}
</tbody>
</table>
</div>
</div>
{/* Chat Panel - Isolated Component */}
<ChatPanel
transactions={transactions}
metrics={{ total: metrics.total, flagged: metrics.flagged, accuracy: metrics.accuracy }}
/>
</div>
{/* Bottom Row - Model Performance & Confusion Matrix */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 mt-4">
{/* Live Quantum Analysis */}
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<h3 className="text-gray-900 font-bold text-sm mb-3 flex items-center gap-2 uppercase tracking-wide">
<Zap className="w-4 h-4 text-amber-500" /> Live Quantum Analysis
</h3>
{transactions.length > 0 ? (
<>
<div className="space-y-3">
{/* Latest Transaction Quantum Breakdown */}
<div className="bg-gradient-to-r from-indigo-50 to-purple-50 rounded-lg p-3 border border-indigo-100">
<div className="flex items-center justify-between mb-2">
<span className="text-xs text-gray-500">Transaction #{transactions[0].id}</span>
<span className={`text-xs px-2 py-0.5 rounded ${transactions[0].prediction === 'Fraud' ? 'bg-red-100 text-red-700' : 'bg-green-100 text-green-700'}`}>
{transactions[0].prediction}
</span>
</div>
<div className="grid grid-cols-2 gap-2 text-center">
<div className="bg-white/60 rounded p-2">
<p className="text-blue-600 font-bold font-data text-lg">{((transactions[0].classical_score || 0) * 100).toFixed(1)}%</p>
<p className="text-[10px] text-gray-500">Classical</p>
</div>
<div className="bg-white/60 rounded p-2">
<p className="text-purple-600 font-bold font-data text-lg">{((transactions[0].quantum_score || 0) * 100).toFixed(1)}%</p>
<p className="text-[10px] text-gray-500">Quantum</p>
</div>
</div>
</div>
{/* Quantum Model Scores */}
<div className="space-y-2">
{[
{ name: 'VQC', value: transactions[0].quantum_details?.vqc || 0, color: 'bg-indigo-500', desc: 'Variational Quantum Classifier' },
{ name: 'QAOA', value: transactions[0].quantum_details?.qaoa || 0, color: 'bg-purple-500', desc: 'Quantum Optimization' },
{ name: 'QNN', value: transactions[0].quantum_details?.qnn || 0, color: 'bg-violet-500', desc: 'Quantum Neural Network' }
].map((model) => (
<div key={model.name} className="flex items-center gap-2">
<span className="text-gray-600 text-xs w-10 font-medium">{model.name}</span>
<div className="flex-1 h-2 bg-gray-200 rounded-full overflow-hidden">
<div className={`h-full ${model.color} rounded-full transition-all duration-500`} style={{ width: `${model.value * 100}%` }} />
</div>
<span className="text-gray-700 text-xs font-medium w-10 text-right">{(model.value * 100).toFixed(0)}%</span>
</div>
))}
</div>
</div>
<div className="mt-3 pt-3 border-t border-gray-200 flex justify-between text-xs">
<span className="text-gray-500">Final Score</span>
<span className={`font-bold ${transactions[0].final_score >= 0.5 ? 'text-red-600' : 'text-green-600'}`}>
{(transactions[0].final_score * 100).toFixed(1)}%
</span>
</div>
</>
) : (
<div className="text-center text-gray-400 py-6 text-sm">
Start simulation to see live quantum analysis
</div>
)}
</div>
{/* Confusion Matrix */}
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<h3 className="text-gray-900 font-bold text-sm mb-3 uppercase tracking-wide">Confusion Matrix</h3>
<div className="grid grid-cols-2 gap-2">
<div className="bg-green-100 rounded-lg p-3 text-center">
<p className="text-green-700 text-xl font-bold">{metrics.tp}</p>
<p className="text-[10px] text-gray-500">True Positive</p>
</div>
<div className="bg-red-100 rounded-lg p-3 text-center">
<p className="text-red-700 text-xl font-bold">{metrics.fp}</p>
<p className="text-[10px] text-gray-500">False Positive</p>
</div>
<div className="bg-amber-100 rounded-lg p-3 text-center">
<p className="text-amber-700 text-xl font-bold">{metrics.fn}</p>
<p className="text-[10px] text-gray-500">False Negative</p>
</div>
<div className="bg-gray-100 rounded-lg p-3 text-center">
<p className="text-gray-700 text-xl font-bold">{metrics.tn}</p>
<p className="text-[10px] text-gray-500">True Negative</p>
</div>
</div>
</div>
{/* Model Weights */}
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<h3 className="text-gray-900 font-bold text-sm mb-3 uppercase tracking-wide">Model Weights</h3>
<div className="space-y-2">
<div className="flex items-center justify-between bg-gray-50 rounded-lg px-3 py-2">
<span className="text-gray-600 text-xs">Classical Model</span>
<span className="text-gray-900 font-bold font-data">80%</span>
</div>
<div className="flex items-center justify-between bg-gray-50 rounded-lg px-3 py-2">
<span className="text-gray-600 text-xs">Quantum Ensemble</span>
<span className="text-gray-900 font-bold font-data">20%</span>
</div>
<div className="flex items-center justify-between bg-green-50 rounded-lg px-3 py-2 mt-3">
<span className="text-gray-600 text-xs">Ensemble Accuracy</span>
<span className="text-green-600 font-bold font-data">{(metrics.accuracy * 100).toFixed(1) || '0.0'}%</span>
</div>
<div className="flex items-center justify-between bg-green-50 rounded-lg px-3 py-2">
<span className="text-gray-600 text-xs">System Status</span>
<span className="text-green-600 font-bold">Online</span>
</div>
</div>
</div>
</div>
</>
)}
{/* Models View */}
{activeTab === 'models' && (
<div className="space-y-4">
{/* Model Architecture Overview */}
<div className="bg-white rounded-xl p-6 border border-gray-200 shadow-sm">
<h2 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-2 uppercase tracking-wide">
<Zap className="w-5 h-5 text-amber-500" /> Hybrid Model Architecture
</h2>
<p className="text-gray-600 text-sm mb-6">
Our fraud detection system uses a hybrid ensemble combining classical machine learning with quantum computing for enhanced pattern recognition.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* Classical Model */}
<div className="bg-gray-50 rounded-lg p-4 border border-gray-200">
<div className="flex items-center justify-between mb-3">
<h3 className="text-gray-900 font-bold uppercase tracking-wide">Classical Model</h3>
<span className="text-2xl font-bold text-gray-900 font-data">80%</span>
</div>
<p className="text-gray-500 text-xs mb-3">XGBoost Gradient Boosting</p>
<div className="w-full h-3 bg-gray-200 rounded-full overflow-hidden">
<div className="h-full bg-gray-700 rounded-full" style={{ width: '80%' }} />
</div>
<ul className="mt-3 space-y-1 text-xs text-gray-600">
<li>• High accuracy on structured data</li>
<li>• Fast inference time</li>
<li>• Handles missing values</li>
</ul>
</div>
{/* Quantum Ensemble */}
<div className="bg-gradient-to-br from-indigo-50 to-purple-50 rounded-lg p-4 border border-indigo-200">
<div className="flex items-center justify-between mb-3">
<h3 className="text-gray-900 font-bold uppercase tracking-wide">Quantum Ensemble</h3>
<span className="text-2xl font-bold text-indigo-600 font-data">20%</span>
</div>
<p className="text-gray-500 text-xs mb-3">VQC + QAOA + QNN</p>
<div className="w-full h-3 bg-indigo-200 rounded-full overflow-hidden">
<div className="h-full bg-indigo-500 rounded-full" style={{ width: '20%' }} />
</div>
<ul className="mt-3 space-y-1 text-xs text-gray-600">
<li>• Detects quantum patterns</li>
<li>• Finds subtle correlations</li>
<li>• Improves edge cases</li>
</ul>
</div>
</div>
</div>
{/* Quantum Models Detail */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 rounded-lg bg-indigo-100 flex items-center justify-center">
<span className="text-indigo-700 font-bold text-sm">VQC</span>
</div>
<div>
<h3 className="text-gray-900 font-semibold text-sm">Variational Quantum Classifier</h3>
<p className="text-gray-400 text-xs">40% of quantum weight</p>
</div>
</div>
<p className="text-gray-600 text-xs">
Uses parameterized quantum circuits for classification. Learns optimal rotations for feature encoding.
</p>
<div className="mt-3 pt-3 border-t border-gray-200">
<div className="flex justify-between text-xs">
<span className="text-gray-400">Qubits</span>
<span className="text-gray-900">4</span>
</div>
</div>
</div>
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center">
<span className="text-purple-700 font-bold text-sm">QAOA</span>
</div>
<div>
<h3 className="text-gray-900 font-semibold text-sm">Quantum Approximate Optimization</h3>
<p className="text-gray-400 text-xs">30% of quantum weight</p>
</div>
</div>
<p className="text-gray-600 text-xs">
Finds optimal solutions for combinatorial problems. Used for feature subset selection.
</p>
<div className="mt-3 pt-3 border-t border-gray-200">
<div className="flex justify-between text-xs">
<span className="text-gray-400">Layers</span>
<span className="text-gray-900">2</span>
</div>
</div>
</div>
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 rounded-lg bg-violet-100 flex items-center justify-center">
<span className="text-violet-700 font-bold text-sm">QNN</span>
</div>
<div>
<h3 className="text-gray-900 font-semibold text-sm">Quantum Neural Network</h3>
<p className="text-gray-400 text-xs">30% of quantum weight</p>
</div>
</div>
<p className="text-gray-600 text-xs">
Deep quantum circuits with entanglement layers. Captures complex non-linear patterns.
</p>
<div className="mt-3 pt-3 border-t border-gray-200">
<div className="flex justify-between text-xs">
<span className="text-gray-400">Depth</span>
<span className="text-gray-900">3</span>
</div>
</div>
</div>
</div>
{/* Performance Metrics */}
<div className="bg-white rounded-xl p-4 border border-gray-200 shadow-sm">
<h3 className="text-gray-900 font-semibold text-sm mb-4">Current Session Performance</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center">
<p className="text-3xl font-bold text-green-600">{(metrics.accuracy * 100).toFixed(1)}%</p>
<p className="text-gray-500 text-xs">Accuracy</p>
</div>
<div className="text-center">
<p className="text-3xl font-bold text-green-600">{(metrics.precision * 100).toFixed(1)}%</p>
<p className="text-gray-500 text-xs">Precision</p>
</div>
<div className="text-center">
<p className="text-3xl font-bold text-amber-500">{(metrics.recall * 100).toFixed(1)}%</p>
<p className="text-gray-500 text-xs">Recall</p>
</div>
<div className="text-center">
<p className="text-3xl font-bold text-amber-500">{(metrics.f1 * 100).toFixed(1)}%</p>
<p className="text-gray-500 text-xs">F1 Score</p>
</div>
</div>
</div>
</div>
)}
{/* Settings View */}
{activeTab === 'settings' && (
<div className="space-y-4 max-w-2xl">
<div className="bg-white rounded-xl p-6 border border-gray-200 shadow-sm">
<h2 className="text-xl font-bold text-gray-900 mb-4">System Settings</h2>
<div className="space-y-4">
<div className="flex items-center justify-between py-3 border-b border-gray-200">
<div>
<h3 className="text-gray-900 font-medium text-sm">API Endpoint</h3>
<p className="text-gray-500 text-xs">Backend server URL</p>
</div>
<code className="bg-gray-100 px-3 py-1.5 rounded text-gray-700 text-xs font-mono">{API_URL}</code>
</div>
<div className="flex items-center justify-between py-3 border-b border-gray-200">
<div>
<h3 className="text-gray-900 font-medium text-sm">Classical Weight</h3>
<p className="text-gray-500 text-xs">XGBoost contribution</p>
</div>
<span className="text-gray-900 font-bold">80%</span>
</div>
<div className="flex items-center justify-between py-3 border-b border-gray-200">
<div>
<h3 className="text-gray-900 font-medium text-sm">Quantum Weight</h3>
<p className="text-gray-500 text-xs">Ensemble contribution</p>
</div>
<span className="text-indigo-600 font-bold">20%</span>
</div>
<div className="flex items-center justify-between py-3 border-b border-gray-200">
<div>
<h3 className="text-gray-900 font-medium text-sm">Fraud Threshold</h3>
<p className="text-gray-500 text-xs">Score cutoff for flagging</p>
</div>
<span className="text-gray-900 font-bold">0.5</span>
</div>
<div className="flex items-center justify-between py-3">
<div>
<h3 className="text-gray-900 font-medium text-sm">Transaction Buffer</h3>
<p className="text-gray-500 text-xs">Max transactions in view</p>
</div>
<span className="text-gray-900 font-bold">50</span>
</div>
</div>
</div>
{/* HuggingFace Cloud Integration */}
<div className="bg-gradient-to-br from-amber-50 to-orange-50 rounded-xl p-6 border border-amber-200 shadow-sm">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🤗</span>
<h2 className="text-lg font-bold text-gray-900">HuggingFace Cloud Integration</h2>
</div>
<p className="text-gray-600 text-sm mb-4">
Offload heavy ML computations to HuggingFace Inference API to reduce local system burden.
</p>
<div className="space-y-3">
<div className="flex items-center justify-between bg-white/60 rounded-lg px-4 py-3">
<div>
<h3 className="text-gray-900 font-medium text-sm">Status</h3>
<p className="text-gray-500 text-xs">Cloud inference availability</p>
</div>
<span className="px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-600">
Check Backend
</span>
</div>
<div className="bg-white/60 rounded-lg px-4 py-3">
<h3 className="text-gray-900 font-medium text-sm mb-2">Setup Instructions</h3>
<ol className="text-xs text-gray-600 space-y-1 list-decimal list-inside">
<li>Get free API key from <a href="https://huggingface.co/settings/tokens" target="_blank" rel="noopener noreferrer" className="text-amber-600 hover:underline">huggingface.co/settings/tokens</a></li>
<li>Create a <code className="bg-gray-100 px-1 rounded">.env</code> file in project root</li>
<li>Add: <code className="bg-gray-100 px-1 rounded">HUGGINGFACE_API_KEY=your_key_here</code></li>
<li>Restart the backend server</li>
</ol>
</div>
<div className="text-xs text-amber-700 bg-amber-100 rounded-lg px-4 py-2">
💡 Free tier includes ~30K requests/month - perfect for development and testing!
</div>
</div>
</div>
<div className="bg-white rounded-xl p-6 border border-gray-200 shadow-sm">
<h2 className="text-lg font-bold text-gray-900 mb-3">About</h2>
<p className="text-gray-600 text-sm">
QuantumShield is a hybrid quantum-classical fraud detection system. It combines the power of XGBoost for handling structured transaction data with quantum computing circuits (VQC, QAOA, QNN) for enhanced pattern recognition.
</p>
<div className="mt-4 pt-4 border-t border-gray-200 flex gap-4 text-xs text-gray-400">
<span>Built with PennyLane</span>
<span></span>
<span>Next.js Frontend</span>
<span></span>
<span>FastAPI Backend</span>
<span></span>
<span>🤗 HuggingFace</span>
</div>
</div>
</div>
)}
</main>
</div>
</div>
);
}
function StatCard({ icon, label, value, color }: { icon: React.ReactNode; label: string; value: string | number; color: string }) {
const colors: Record<string, string> = {
white: 'bg-white border-gray-200',
yellow: 'bg-amber-50 border-amber-200',
red: 'bg-red-50 border-red-200',
green: 'bg-green-50 border-green-200',
};
const textColors: Record<string, string> = {
white: 'text-gray-900',
yellow: 'text-amber-600',
red: 'text-red-600',
green: 'text-green-600',
};
const iconColors: Record<string, string> = {
white: 'text-gray-500',
yellow: 'text-amber-500',
red: 'text-red-500',
green: 'text-green-500',
};
return (
<div className={`${colors[color]} rounded-xl p-3 border shadow-sm`}>
<div className="flex items-center gap-2 mb-1">
<span className={iconColors[color]}>{icon}</span>
<span className="text-gray-500 text-[10px] uppercase font-bold tracking-wider">{label}</span>
</div>
<p className={`text-xl font-bold font-data tracking-tight ${textColors[color]}`}>{value}</p>
</div>
);
}