/** * ModelSelector Component * Dropdown/tabs interface to switch between ML prediction models * OQI-006: Senales ML */ import React, { useMemo } from 'react'; import { Brain, ChevronDown, Check, Cpu, LineChart, Network, Layers, Sparkles, TrendingUp, AlertCircle, } from 'lucide-react'; export interface MLModel { id: string; name: string; type: 'lstm' | 'xgboost' | 'random_forest' | 'svm' | 'ensemble' | 'transformer'; accuracy: number; lastUpdated: string; status: 'active' | 'training' | 'inactive' | 'deprecated'; description?: string; features?: string[]; } export interface ModelSelectorProps { models: MLModel[]; selectedModelId: string; onModelChange: (modelId: string) => void; variant?: 'dropdown' | 'tabs' | 'cards'; showMetrics?: boolean; disabled?: boolean; loading?: boolean; } const ModelSelector: React.FC = ({ models, selectedModelId, onModelChange, variant = 'dropdown', showMetrics = true, disabled = false, loading = false, }) => { const [isOpen, setIsOpen] = React.useState(false); const dropdownRef = React.useRef(null); const selectedModel = useMemo( () => models.find((m) => m.id === selectedModelId), [models, selectedModelId] ); // Close dropdown on outside click React.useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const getModelIcon = (type: MLModel['type']) => { switch (type) { case 'lstm': return ; case 'xgboost': return ; case 'random_forest': return ; case 'svm': return ; case 'ensemble': return ; case 'transformer': return ; default: return ; } }; const getStatusColor = (status: MLModel['status']) => { switch (status) { case 'active': return 'text-green-400 bg-green-500/20'; case 'training': return 'text-yellow-400 bg-yellow-500/20'; case 'inactive': return 'text-gray-400 bg-gray-500/20'; case 'deprecated': return 'text-red-400 bg-red-500/20'; default: return 'text-gray-400 bg-gray-500/20'; } }; const getAccuracyColor = (accuracy: number) => { if (accuracy >= 70) return 'text-green-400'; if (accuracy >= 50) return 'text-yellow-400'; return 'text-red-400'; }; // Dropdown variant if (variant === 'dropdown') { return (
{isOpen && (
{models.map((model) => ( ))}
)}
); } // Tabs variant if (variant === 'tabs') { return (
{models.map((model) => ( ))}
); } // Cards variant return (
{models.map((model) => ( ))}
); }; export default ModelSelector;