DataVision CI/CD Bot
release: clean production build for HuggingFace Space
09801ca
Raw
History Blame Contribute Delete
5.12 kB
import React, { useState, useEffect } from 'react';
import { useUserStore } from '@/store/userStore';
import apiService from '@/services/api';
import { History, Search, RefreshCcw, RotateCcw, ArrowRight } from 'lucide-react';
const HistoryTab: React.FC = () => {
const { isDark } = useUserStore();
const [simulations, setSimulations] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const [search, setSearch] = useState('');
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const cardBg = isDark ? 'rgba(255,255,255,0.03)' : '#ffffff';
const cardBorder = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';
const textPrimary = isDark ? '#f8fafc' : '#0f172a';
const textMuted = isDark ? '#94a3b8' : '#64748b';
const fetchHistory = async () => {
setLoading(true);
try {
const res = await apiService.getSimulationHistory(page, 20, search);
setSimulations(res.data?.simulations || []);
setTotal(res.data?.total || 0);
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchHistory();
}, [page, search]);
return (
<div className="space-y-5">
{/* Search & Header */}
<div className="flex items-center justify-between flex-wrap gap-3">
<div className="flex-1 relative min-w-48">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4" style={{ color: textMuted }} />
<input
type="text"
placeholder="Search simulation history..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="w-full pl-9 pr-3 py-2 rounded-xl text-xs border outline-none focus:ring-2 focus:ring-indigo-500/30"
style={{ background: cardBg, borderColor: cardBorder, color: textPrimary }}
/>
</div>
<button onClick={fetchHistory} className="flex items-center gap-1.5 px-3 py-2 rounded-xl border text-xs font-medium hover:bg-white/5" style={{ borderColor: cardBorder, color: textMuted }}>
<RefreshCcw className="w-3.5 h-3.5" /> Refresh
</button>
</div>
{/* History Table */}
<div className="rounded-2xl border p-5 overflow-x-auto" style={{ background: cardBg, borderColor: cardBorder }}>
<table className="w-full text-left">
<thead>
<tr className="border-b" style={{ borderColor: cardBorder }}>
{['Simulation Name', 'Model', 'Target Metric', 'Impact', 'Confidence', 'Status', 'Date', 'Action'].map((h) => (
<th key={h} className="py-2.5 px-3 text-xs font-semibold" style={{ color: textMuted }}>{h}</th>
))}
</tr>
</thead>
<tbody>
{simulations.map((sim: any, i: number) => (
<tr key={i} className="border-b last:border-0 hover:bg-white/[0.02]" style={{ borderColor: cardBorder }}>
<td className="py-3 px-3 text-xs font-semibold" style={{ color: textPrimary }}>{sim.name}</td>
<td className="py-3 px-3 text-xs" style={{ color: textMuted }}>{sim.model_name || 'AutoML'}</td>
<td className="py-3 px-3 text-xs font-bold" style={{ color: textPrimary }}>
{typeof sim.prediction === 'number' ? sim.prediction.toLocaleString(undefined, { maximumFractionDigits: 2 }) : 'N/A'}
</td>
<td className="py-3 px-3">
<span className={`text-xs font-bold ${(sim.impact_percentage || 0) >= 0 ? 'text-emerald-500' : 'text-red-500'}`}>
{(sim.impact_percentage || 0) >= 0 ? '+' : ''}{(sim.impact_percentage || 0).toFixed(1)}%
</span>
</td>
<td className="py-3 px-3 text-xs font-bold text-indigo-500">
{(sim.confidence || 90).toFixed(1)}%
</td>
<td className="py-3 px-3">
<span className="text-[10px] font-bold px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-500">
{sim.status || 'Completed'}
</span>
</td>
<td className="py-3 px-3 text-xs" style={{ color: textMuted }}>
{sim.created_at ? new Date(sim.created_at).toLocaleDateString() : 'Just now'}
</td>
<td className="py-3 px-3">
<button className="flex items-center gap-1 text-xs font-semibold text-indigo-500 hover:text-indigo-400">
<RotateCcw className="w-3 h-3" /> Restore
</button>
</td>
</tr>
))}
</tbody>
</table>
{simulations.length === 0 && !loading && (
<div className="text-center py-12">
<History className="w-10 h-10 mx-auto mb-2 opacity-40" style={{ color: textMuted }} />
<p className="text-xs" style={{ color: textMuted }}>No past simulation records found.</p>
</div>
)}
</div>
</div>
);
};
export default HistoryTab;