import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { useUserStore } from '@/store/userStore'; import { useLiveStore } from '@/store/liveStore'; import apiService from '@/services/api'; import OverviewTab from '@/components/simulator/OverviewTab'; import ScenarioBuilderTab from '@/components/simulator/ScenarioBuilderTab'; import ForecastTab from '@/components/simulator/ForecastTab'; import AIInsightsTab from '@/components/simulator/AIInsightsTab'; import VariableImportanceTab from '@/components/simulator/VariableImportanceTab'; import AISuggestedScenariosTab from '@/components/simulator/AISuggestedScenariosTab'; import ComparisonTab from '@/components/simulator/ComparisonTab'; import OptimizationTab from '@/components/simulator/OptimizationTab'; import HistoryTab from '@/components/simulator/HistoryTab'; import ReportsTab from '@/components/simulator/ReportsTab'; import { Sliders, Play, Save, Share2, Sparkles, LayoutDashboard, TrendingUp, Lightbulb, BarChart2, Brain, GitCompare, Zap, History, FileText, Rocket, RefreshCcw, Database, AlertTriangle, Upload } from 'lucide-react'; const tabs = [ { id: 'overview', label: 'Overview', icon: LayoutDashboard }, { id: 'builder', label: 'Scenario Builder', icon: Sliders }, { id: 'forecast', label: 'Forecast', icon: TrendingUp }, { id: 'ai-insights', label: 'AI Insights', icon: Lightbulb }, { id: 'importance', label: 'Variable Importance', icon: BarChart2 }, { id: 'ai-suggested', label: 'AI Suggested', icon: Brain }, { id: 'comparison', label: 'Comparison', icon: GitCompare }, { id: 'optimization', label: 'Optimization', icon: Zap }, { id: 'history', label: 'History', icon: History }, { id: 'reports', label: 'Reports', icon: FileText }, ]; const ScenarioSimulator: React.FC = () => { const navigate = useNavigate(); const { isDark } = useUserStore(); const { clearSimulatorCache } = useLiveStore(); const [activeTab, setActiveTab] = useState('overview'); const [refreshKey, setRefreshKey] = useState(0); const [hasData, setHasData] = useState(null); // null = loading const [simRunning, setSimRunning] = useState(false); const [simResult, setSimResult] = useState(null); const [saveModalOpen, setSaveModalOpen] = useState(false); const [saveName, setSaveName] = useState(''); const [saveDesc, setSaveDesc] = useState(''); const [saving, setSaving] = useState(false); const [saveSuccess, setSaveSuccess] = useState(false); const textPrimary = isDark ? '#f8fafc' : '#0f172a'; const textMuted = isDark ? '#94a3b8' : '#64748b'; const borderSubtle = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'; const handleManualRefresh = () => { clearSimulatorCache(); setRefreshKey(prev => prev + 1); checkDataAvailability(); }; // Check if user has data to simulate const checkDataAvailability = async () => { try { const res = await apiService.getSimulatorVariables(); setHasData(res.data && Array.isArray(res.data) && res.data.length > 0); } catch { setHasData(false); } }; useEffect(() => { checkDataAvailability(); }, []); // Auto refresh when returning to this page if a new model was trained useEffect(() => { const handleStorage = (e: StorageEvent) => { if (e.key === 'last_trained_timestamp' || e.key === 'hasMLResults') { clearSimulatorCache(); setRefreshKey(prev => prev + 1); checkDataAvailability(); } }; window.addEventListener('storage', handleStorage); return () => window.removeEventListener('storage', handleStorage); }, []); // Run actual simulation const handleRunSimulation = async () => { setSimRunning(true); try { const varsRes = await apiService.getSimulatorVariables(); if (varsRes.data && varsRes.data.length > 0) { const values: Record = {}; varsRes.data.forEach((v: any) => { values[v.name || v.display_name] = v.current_value; }); const runRes = await apiService.runSimulation(values); setSimResult(runRes.data); setActiveTab('builder'); } } catch (err) { console.error('Simulation failed:', err); } finally { setSimRunning(false); } }; // Save current scenario const handleSaveScenario = async () => { if (!saveName.trim()) return; setSaving(true); try { const varsRes = await apiService.getSimulatorVariables(); const values: Record = {}; if (varsRes.data) { varsRes.data.forEach((v: any) => { values[v.name || v.display_name] = v.current_value; }); } await apiService.saveScenario({ name: saveName, description: saveDesc, variables: values, prediction: simResult?.prediction, confidence: simResult?.confidence, metrics: simResult?.metrics, }); setSaveSuccess(true); setTimeout(() => { setSaveModalOpen(false); setSaveSuccess(false); setSaveName(''); setSaveDesc(''); }, 1500); } catch (err) { console.error('Save failed:', err); } finally { setSaving(false); } }; // No data state if (hasData === false) { return (

No Dataset Available

The Scenario Simulator requires a dataset with a trained model to work. Upload data in the Data Hub and train a model in AutoML first.

); } // Loading state if (hasData === null) { return (
Loading simulator data...
); } return (
{/* Top Bar Header */}

Scenario Simulator

Enterprise v3.0

Real-time ML scenario simulation, multi-variable forecasting, AI insights, and trade-off optimization.

{/* Action Buttons */}
{/* Tab Navigation Bar */}
{tabs.map((tab) => { const Icon = tab.icon; const active = activeTab === tab.id; return ( ); })}
{/* Tab Content Display */} {activeTab === 'overview' && } {activeTab === 'builder' && } {activeTab === 'forecast' && } {activeTab === 'ai-insights' && } {activeTab === 'importance' && } {activeTab === 'ai-suggested' && } {activeTab === 'comparison' && } {activeTab === 'optimization' && } {activeTab === 'history' && } {activeTab === 'reports' && } {/* Save Scenario Modal */} {saveModalOpen && ( setSaveModalOpen(false)} > e.stopPropagation()} className={`w-full max-w-md p-6 rounded-2xl border shadow-2xl ${ isDark ? 'bg-[#12131a] border-white/10' : 'bg-white border-slate-200' }`} > {saveSuccess ? (

Scenario Saved!

) : ( <>

Save Current Scenario

setSaveName(e.target.value)} placeholder="e.g., Best-case Revenue Q3" className={`w-full px-3 py-2 rounded-xl text-sm border focus:outline-none focus:border-indigo-500 transition-all ${ isDark ? 'bg-white/5 border-white/10 text-white placeholder:text-slate-600' : 'bg-slate-50 border-slate-200 text-slate-900' }`} />