Files
Atomizer/atomizer-dashboard/frontend/src/components/StudyCard.tsx
Antoine 8cbdbcad78 feat: Add Protocol 13 adaptive optimization, Plotly charts, and dashboard improvements
## Protocol 13: Adaptive Multi-Objective Optimization
- Iterative FEA + Neural Network surrogate workflow
- Initial FEA sampling, NN training, NN-accelerated search
- FEA validation of top NN predictions, retraining loop
- adaptive_state.json tracks iteration history and best values
- M1 mirror study (V11) with 103 FEA, 3000 NN trials

## Dashboard Visualization Enhancements
- Added Plotly.js interactive charts (parallel coords, Pareto, convergence)
- Lazy loading with React.lazy() for performance
- Code splitting: plotly.js-basic-dist (~1MB vs 3.5MB)
- Chart library toggle (Recharts default, Plotly on-demand)
- ExpandableChart component for full-screen modal views
- ConsoleOutput component for real-time log viewing

## Documentation
- Protocol 13 detailed documentation
- Dashboard visualization guide
- Plotly components README
- Updated run-optimization skill with Mode 5 (adaptive)

## Bug Fixes
- Fixed TypeScript errors in dashboard components
- Fixed Card component to accept ReactNode title
- Removed unused imports across components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 07:41:54 -05:00

53 lines
1.5 KiB
TypeScript

import type { Study } from '../types';
import { Badge } from './Badge';
interface StudyCardProps {
study: Study;
isActive: boolean;
onClick: () => void;
}
export function StudyCard({ study, isActive, onClick }: StudyCardProps) {
const percentage = study.progress.total > 0
? (study.progress.current / study.progress.total) * 100
: 0;
const statusVariant = study.status === 'completed'
? 'success'
: study.status === 'running'
? 'info'
: 'warning';
return (
<div
className={`p-4 rounded-lg cursor-pointer transition-all duration-200 ${
isActive
? 'bg-primary-900 border-l-4 border-primary-400'
: 'bg-dark-500 hover:bg-dark-400'
}`}
onClick={onClick}
>
<div className="flex items-start justify-between mb-2">
<h3 className="font-semibold text-dark-50 text-sm">{study.name}</h3>
<Badge variant={statusVariant}>
{study.status}
</Badge>
</div>
<div className="text-xs text-dark-200 mb-2">
{study.progress.current} / {study.progress.total} trials
{study.best_value !== null && (
<span className="ml-2"> Best: {study.best_value.toFixed(4)}</span>
)}
</div>
<div className="w-full h-2 bg-dark-700 rounded-full overflow-hidden">
<div
className="h-full bg-gradient-to-r from-primary-600 to-primary-400 transition-all duration-300"
style={{ width: `${percentage}%` }}
/>
</div>
</div>
);
}