Spaces:
Running
Running
File size: 7,373 Bytes
b8b3edf 24c58d8 b8b3edf | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
import React, { useState } from 'react';
import { Play, Sparkles, AlertCircle, CheckCircle2, ChevronRight, Loader2 } from 'lucide-react';
// fix: removed .ts extension from imports to follow project pattern and resolved missing member error
import { runSimulationForecast } from '../services/geminiService';
import { SimulationResult } from '../types/index';
const ScenarioButton = ({ label, description, onClick }: any) => (
<button
onClick={() => onClick(label)}
className="text-left p-5 rounded-2xl bg-zinc-900 border border-zinc-800 hover:border-blue-500/50 hover:bg-zinc-800/50 transition-all group"
>
<h4 className="text-white font-bold mb-1 group-hover:text-blue-400 transition-colors">{label}</h4>
<p className="text-zinc-500 text-xs leading-relaxed">{description}</p>
</button>
);
const Simulation: React.FC = () => {
const [prompt, setPrompt] = useState('');
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<SimulationResult | null>(null);
const handleRun = async (overridePrompt?: string) => {
const finalPrompt = overridePrompt || prompt;
if (!finalPrompt) return;
setLoading(true);
const data = await runSimulationForecast(finalPrompt);
setResult(data);
setLoading(false);
};
return (
<div className="max-w-5xl mx-auto space-y-8 animate-in slide-in-from-bottom-4 duration-500">
<div className="bg-gradient-to-br from-indigo-900/20 via-zinc-900 to-zinc-900 border border-zinc-800 rounded-3xl p-10 overflow-hidden relative">
<div className="absolute top-0 right-0 -mt-10 -mr-10 w-64 h-64 bg-indigo-600/10 blur-[80px] rounded-full"></div>
<div className="relative z-10">
<div className="flex items-center space-x-3 mb-4">
<div className="p-2 rounded-lg bg-indigo-500/20 text-indigo-400">
<Sparkles size={24} />
</div>
<h2 className="text-3xl font-bold text-white tracking-tight">Gemini Oracle Simulation</h2>
</div>
<p className="text-zinc-400 text-lg mb-8 max-w-2xl">
Simulate complex market shifts, regulatory shocks, or internal expenditure reallocations using neural financial forecasting.
</p>
<div className="flex flex-col space-y-4">
<div className="relative">
<textarea
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
placeholder="e.g., 'Simulate a 5% inflation spike over 12 months with a focus on cloud compute costs'"
className="w-full bg-black border-2 border-zinc-800 focus:border-indigo-500/50 rounded-2xl p-6 text-white text-lg min-h-[160px] outline-none transition-all resize-none placeholder:text-zinc-700"
></textarea>
<button
onClick={() => handleRun()}
disabled={loading || !prompt}
className="absolute bottom-4 right-4 px-8 py-3 bg-indigo-600 hover:bg-indigo-500 disabled:bg-zinc-800 disabled:text-zinc-500 text-white rounded-xl font-bold flex items-center space-x-2 transition-all shadow-lg shadow-indigo-900/20"
>
{loading ? <Loader2 className="animate-spin" size={20} /> : <Play size={20} fill="currentColor" />}
<span>{loading ? 'Thinking...' : 'Run Simulation'}</span>
</button>
</div>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<ScenarioButton
label="Market Crash"
description="Simulate 2008-style housing collapse on commercial real estate portfolio."
onClick={handleRun}
/>
<ScenarioButton
label="Hyperinflation"
description="Model assets against 15%+ annual CPI growth over a 3-year horizon."
onClick={handleRun}
/>
<ScenarioButton
label="AI Expansion"
description="Forecast ROI on $2M compute spend increase vs reduced dev headcount."
onClick={handleRun}
/>
</div>
{result && (
<div className="bg-zinc-900 border border-zinc-800 rounded-3xl p-8 animate-in zoom-in-95 duration-300">
<div className="flex justify-between items-start mb-8 pb-8 border-b border-zinc-800">
<div className="flex items-center space-x-4">
<div className="w-12 h-12 rounded-2xl bg-emerald-500/10 text-emerald-500 flex items-center justify-center">
<CheckCircle2 size={28} />
</div>
<div>
<h3 className="text-xl font-bold text-white">Simulation Results</h3>
<p className="text-zinc-500 text-sm mono">REF: {result.simulationId}</p>
</div>
</div>
<div className="text-right">
<p className="text-[10px] uppercase tracking-widest text-zinc-500 font-bold mb-1">Confidence Score</p>
<div className="flex items-center space-x-2">
<div className="h-2 w-32 bg-zinc-800 rounded-full overflow-hidden">
<div className="h-full bg-emerald-500" style={{ width: `${result.confidenceScore * 100}%` }}></div>
</div>
<span className="text-sm font-bold text-zinc-300">{Math.round(result.confidenceScore * 100)}%</span>
</div>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
<div>
<h4 className="text-zinc-400 font-bold uppercase text-[10px] tracking-widest mb-4">Neural Narrative</h4>
<p className="text-zinc-200 leading-relaxed italic border-l-2 border-blue-500/30 pl-6 py-2">
"{result.outcomeNarrative}"
</p>
</div>
<div className="bg-black/40 rounded-2xl p-8 border border-zinc-800">
<div className="space-y-6">
<div>
<p className="text-zinc-500 text-xs mb-1">Projected Portfolio Value (12M)</p>
<p className="text-4xl font-bold text-white mono tracking-tighter">
${result.projectedValue?.toLocaleString()}
</p>
</div>
<div className="flex space-x-4">
<div className="flex-1 p-4 rounded-xl bg-zinc-800/50 border border-zinc-700">
<p className="text-zinc-500 text-[10px] font-bold uppercase mb-1">Risk Exposure</p>
<div className="flex items-center space-x-2 text-rose-500">
<AlertCircle size={16} />
<span className="font-bold">Elevated</span>
</div>
</div>
<div className="flex-1 p-4 rounded-xl bg-zinc-800/50 border border-zinc-700">
<p className="text-zinc-500 text-[10px] font-bold uppercase mb-1">Resilience Rating</p>
<div className="flex items-center space-x-2 text-blue-400">
<ChevronRight size={16} />
<span className="font-bold">AA-</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default Simulation;
|