updated tsconfig changed reactor status
This commit is contained in:
parent
4cecf71d04
commit
ece54771b7
|
|
@ -1,90 +1,110 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { Activity, Power, Atom, Coffee, TrendingUp, Wallet } from 'lucide-react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Activity, Power, Atom, TrendingUp, Users } from 'lucide-react';
|
||||
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
|
||||
import type { ReactorStatusProps, TooltipProps, PriceStat } from './types';
|
||||
import { getEthereumData, formatPrice, getHighLowPrices, formatVolume } from '../../utils/api';
|
||||
import type { ReactorStatusProps } from './types';
|
||||
|
||||
const statusMessages = [
|
||||
'Mining blocks... literally',
|
||||
'Consensus achieved',
|
||||
'Smart contracts cooling',
|
||||
'Tokens well-contained',
|
||||
'DAOs running smoothly',
|
||||
'Radiation levels nominal',
|
||||
'Governance protocols stable',
|
||||
'Core temperature optimal',
|
||||
'NFTs properly shielded',
|
||||
'Blockchain fully operational'
|
||||
'Consensus protocols maintaining criticality',
|
||||
'Smart contracts properly shielded',
|
||||
'DAOs operating at optimal temperature',
|
||||
'Governance tokens well-contained',
|
||||
'Web3 radiation levels nominal',
|
||||
'Blockchain fully operational',
|
||||
'Decentralized cooling systems engaged',
|
||||
'Token emissions within parameters',
|
||||
'NFT containment field stable',
|
||||
'Reactor governance optimized'
|
||||
];
|
||||
|
||||
const CustomTooltip = ({ active, payload, label }: TooltipProps) => {
|
||||
if (active && payload && payload.length && label) {
|
||||
// Simulated data for the career timeline
|
||||
// Generate simulated stability data
|
||||
const generateStabilityData = () => {
|
||||
const points = 20;
|
||||
const data = [];
|
||||
for (let i = 0; i < points; i++) {
|
||||
data.push({
|
||||
time: i,
|
||||
value: 50 + Math.sin(i / 2) * 20 + (Math.random() * 10 - 5)
|
||||
});
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
// Generate simulated neutron flux data
|
||||
const generateFluxData = () => {
|
||||
const points = 20;
|
||||
const data = [];
|
||||
for (let i = 0; i < points; i++) {
|
||||
data.push({
|
||||
time: i,
|
||||
value: 70 + Math.cos(i / 3) * 15 + (Math.random() * 8 - 4)
|
||||
});
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
const generateTimelineData = () => {
|
||||
const data = [];
|
||||
const startYear = 2003;
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
for (let year = startYear; year <= currentYear; year++) {
|
||||
let value = 30; // Base value
|
||||
|
||||
// Add significant career events
|
||||
if (year === 2003) value += 20; // Started as Boilermaker
|
||||
if (year === 2005) value += 15; // Red Seal certification
|
||||
if (year === 2016) value += 25; // Radiation Protection certification
|
||||
if (year === 2019) value += 20; // EPRI certification
|
||||
if (year === 2022) value += 30; // Entered Web3 space
|
||||
|
||||
data.push({
|
||||
year: year.toString(),
|
||||
value: value + Math.random() * 10
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
const CustomTooltip = ({ active, payload, label }: any) => {
|
||||
if (active && payload && payload.length) {
|
||||
const careerEvents: { [key: string]: string } = {
|
||||
'2003': 'Started as Boilermaker',
|
||||
'2005': 'Achieved Red Seal certification',
|
||||
'2016': 'Obtained Radiation Protection certification',
|
||||
'2019': 'Earned EPRI certification',
|
||||
'2022': 'Entered Web3 space and founded DAO Masons'
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-gray-800 p-2 rounded border border-gray-700">
|
||||
<p className="text-blue-400">{formatPrice(payload[0].value)}</p>
|
||||
<p className="text-gray-400 text-sm">
|
||||
{new Date(parseInt(label)).toLocaleTimeString()}
|
||||
</p>
|
||||
<div className="bg-gray-800 p-3 rounded-lg border border-gray-700">
|
||||
<p className="text-white font-medium">{label}</p>
|
||||
<p className="text-blue-400">{careerEvents[label] || 'Career progression'}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const ReactorStatus = ({ className = '' }: ReactorStatusProps) => {
|
||||
const [power, setPower] = useState(0);
|
||||
const [status, setStatus] = useState('Initializing...');
|
||||
export const ReactorStatus: React.FC<ReactorStatusProps> = ({
|
||||
}) => {
|
||||
const [power, setPower] = useState(85);
|
||||
const [coreTemp, setCoreTemp] = useState(1350);
|
||||
const [blockHeight, setBlockHeight] = useState(18_500_000);
|
||||
const [radLevel, setRadLevel] = useState(5.5e7);
|
||||
const [status, setStatus] = useState('Initializing systems...');
|
||||
const [isAnimating, setIsAnimating] = useState(false);
|
||||
const [currentTime, setCurrentTime] = useState(new Date());
|
||||
const [priceData, setPriceData] = useState<Array<{ time: number; price: number }>>([]);
|
||||
const [priceStats, setPriceStats] = useState<PriceStat[]>([
|
||||
{ label: '24h High', value: '...' },
|
||||
{ label: '24h Low', value: '...' },
|
||||
{ label: '24h Volume', value: '...' }
|
||||
]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [timelineData] = useState(generateTimelineData());
|
||||
|
||||
const careerStats = [
|
||||
{ label: 'Years Experience', value: '20+' },
|
||||
{ label: 'Major Projects', value: '50+' },
|
||||
{ label: 'Grants Secured', value: '$197K' }
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const data = await getEthereumData();
|
||||
console.log('Received ETH data:', data);
|
||||
|
||||
if (!data?.prices?.length) {
|
||||
throw new Error('Invalid price data received');
|
||||
}
|
||||
|
||||
const formattedPrices = data.prices.map(([timestamp, price]) => ({
|
||||
time: timestamp,
|
||||
price
|
||||
}));
|
||||
|
||||
const { high, low } = getHighLowPrices(data.prices);
|
||||
const volume = data.total_volumes[data.total_volumes.length - 1][1];
|
||||
|
||||
console.log('Formatted prices:', formattedPrices);
|
||||
setPriceData(formattedPrices);
|
||||
setPriceStats([
|
||||
{ label: '24h High', value: formatPrice(high) },
|
||||
{ label: '24h Low', value: formatPrice(low) },
|
||||
{ label: '24h Volume', value: formatVolume(volume) }
|
||||
]);
|
||||
} catch (err) {
|
||||
console.error('Error fetching ETH data:', err);
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch price data');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Initial fetch
|
||||
fetchData();
|
||||
|
||||
// Set up intervals
|
||||
const intervals = [
|
||||
setInterval(() => setCurrentTime(new Date()), 1000),
|
||||
setInterval(() => {
|
||||
|
|
@ -93,158 +113,181 @@ export const ReactorStatus = ({ className = '' }: ReactorStatusProps) => {
|
|||
return Math.min(Math.max(prev + fluctuation, 60), 100);
|
||||
});
|
||||
}, 3000),
|
||||
setInterval(() => {
|
||||
setCoreTemp(() => {
|
||||
const fluctuation = Math.random() * 20 - 10;
|
||||
return 1300 + (fluctuation % 100);
|
||||
});
|
||||
}, 2000),
|
||||
setInterval(() => {
|
||||
setBlockHeight(prev => prev + Math.floor(Math.random() * 3));
|
||||
}, 5000),
|
||||
setInterval(() => {
|
||||
setRadLevel(() => {
|
||||
const base = 5e7;
|
||||
const fluctuation = Math.random() * 5e7;
|
||||
return base + fluctuation;
|
||||
});
|
||||
}, 4000),
|
||||
setInterval(() => {
|
||||
const randomStatus = statusMessages[Math.floor(Math.random() * statusMessages.length)];
|
||||
setStatus(randomStatus);
|
||||
setIsAnimating(true);
|
||||
setTimeout(() => setIsAnimating(false), 500);
|
||||
}, 5000),
|
||||
setInterval(fetchData, 300000) // Fetch new data every 5 minutes
|
||||
}, 5000)
|
||||
];
|
||||
|
||||
// Cleanup
|
||||
return () => intervals.forEach(clearInterval);
|
||||
}, []);
|
||||
|
||||
const statusIndicators = [
|
||||
{ label: 'Core Temp', value: '37.2°C' },
|
||||
{ label: 'Block Height', value: '#18M' },
|
||||
{ label: 'Rad Level', value: '0.12 μSv' }
|
||||
];
|
||||
const formatRadLevel = (level: number) => {
|
||||
return `${(level / 1e7).toFixed(2)}E7 Gy/hr`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 gap-6 ${className}`}>
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<Atom size={32} className="text-blue-500" />
|
||||
<h2 className="text-3xl font-bold bg-gradient-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent">
|
||||
System Status
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* Reactor Status Panel */}
|
||||
<div className="bg-gray-900 rounded-lg p-6">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Atom className="text-blue-500 animate-spin" />
|
||||
<h3 className="text-lg font-bold text-white">Reactor Status</h3>
|
||||
<Activity className="text-blue-500" />
|
||||
<span className="text-sm text-gray-400 font-mono">
|
||||
{currentTime.toLocaleTimeString()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Activity className="text-green-500" />
|
||||
<span className="text-sm text-gray-400">
|
||||
{currentTime.toLocaleTimeString()}
|
||||
<Power className="text-green-500" />
|
||||
<span className="text-sm text-gray-400 font-mono">
|
||||
{power.toFixed(1)}% Capacity
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Power Level */}
|
||||
<div className="bg-gray-800 rounded-lg p-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-gray-400">Power Level</span>
|
||||
<Power className="text-blue-500" />
|
||||
{/* Status Message */}
|
||||
<div className="bg-gray-800/50 rounded-lg p-4 mb-6">
|
||||
<div className={`text-lg font-mono text-blue-400 ${isAnimating ? 'animate-pulse' : ''}`}>
|
||||
{status}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Reactor Metrics */}
|
||||
<div className="grid grid-cols-3 gap-4 mb-6">
|
||||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||||
<div className="text-sm text-gray-400 mb-2">Core Temp</div>
|
||||
<div className="text-blue-400 font-mono font-medium">
|
||||
{coreTemp.toFixed(1)}°C
|
||||
</div>
|
||||
<div className="relative h-4 bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="absolute h-full bg-blue-500 transition-all duration-1000"
|
||||
style={{ width: `${power}%` }}
|
||||
/>
|
||||
</div>
|
||||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||||
<div className="text-sm text-gray-400 mb-2">Block Height</div>
|
||||
<div className="text-blue-400 font-mono font-medium">
|
||||
#{blockHeight.toLocaleString()}
|
||||
</div>
|
||||
<div className="mt-2 text-right text-sm text-gray-400">
|
||||
{power.toFixed(1)}% Capacity
|
||||
</div>
|
||||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||||
<div className="text-sm text-gray-400 mb-2">Rad Level</div>
|
||||
<div className="text-blue-400 font-mono font-medium">
|
||||
{formatRadLevel(radLevel)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Systems Monitor */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="bg-gray-800/50 rounded-lg p-4">
|
||||
<div className="text-sm text-gray-400 mb-2">Core Stability</div>
|
||||
<div className="h-[100px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={generateStabilityData()}>
|
||||
<Line
|
||||
type="natural"
|
||||
dataKey="value"
|
||||
stroke="#3B82F6"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
isAnimationActive={true}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Status Message */}
|
||||
<div className="bg-gray-800 rounded-lg p-4">
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span className="text-gray-400">Current Status</span>
|
||||
<Coffee className="text-green-500" />
|
||||
<div className="bg-gray-800/50 rounded-lg p-4">
|
||||
<div className="text-sm text-gray-400 mb-2">Neutron Flux</div>
|
||||
<div className="h-[100px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={generateFluxData()}>
|
||||
<Line
|
||||
type="natural"
|
||||
dataKey="value"
|
||||
stroke="#8B5CF6"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
isAnimationActive={true}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
<div className={`text-lg font-medium text-blue-400 ${isAnimating ? 'animate-pulse' : ''}`}>
|
||||
{status}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Activity Indicators */}
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{statusIndicators.map((item, index) => (
|
||||
<div key={index} className="bg-gray-800 rounded-lg p-3 text-center">
|
||||
<div className="text-sm text-gray-400">{item.label}</div>
|
||||
<div className="text-white font-medium">{item.value}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ETH Price Monitor */}
|
||||
{/* Career Timeline Panel */}
|
||||
<div className="bg-gray-900 rounded-lg p-6">
|
||||
<div className="space-y-4 mb-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<TrendingUp className="text-blue-500" />
|
||||
<h3 className="text-lg font-bold text-white">ETH Price Monitor</h3>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Wallet className="text-green-500" />
|
||||
<span className="text-sm text-gray-400">Live Feed</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<TrendingUp className="text-purple-500" />
|
||||
<h3 className="text-lg font-bold text-white">Career Timeline</h3>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Users className="text-purple-500" />
|
||||
<span className="text-sm text-gray-400">Career Progression</span>
|
||||
</div>
|
||||
{priceData.length > 0 && (
|
||||
<div className="bg-gray-800 rounded-lg p-4">
|
||||
<div className="text-sm text-gray-400 mb-1">Current Price</div>
|
||||
<div className="text-2xl font-bold text-blue-400">
|
||||
{formatPrice(priceData[priceData.length - 1].price)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Price Chart */}
|
||||
<div className="bg-gray-800 rounded-lg p-4 h-[300px]">
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-blue-500 flex items-center gap-2">
|
||||
<Atom className="animate-spin" size={20} />
|
||||
<span>Loading price data...</span>
|
||||
</div>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-red-500">{error}</div>
|
||||
</div>
|
||||
) : (
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={priceData}>
|
||||
<XAxis
|
||||
dataKey="time"
|
||||
stroke="#4B5563"
|
||||
tick={{ fill: '#9CA3AF', fontSize: 12 }}
|
||||
tickFormatter={(timestamp) => new Date(timestamp).toLocaleTimeString()}
|
||||
/>
|
||||
<YAxis
|
||||
stroke="#4B5563"
|
||||
tick={{ fill: '#9CA3AF', fontSize: 12 }}
|
||||
domain={['auto', 'auto']}
|
||||
tickFormatter={(value) => formatPrice(value)}
|
||||
/>
|
||||
<Tooltip content={<CustomTooltip />} />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="price"
|
||||
stroke="#3B82F6"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
)}
|
||||
</div>
|
||||
{/* Career Stats */}
|
||||
<div className="grid grid-cols-3 gap-4 mb-6">
|
||||
{careerStats.map((stat, index) => (
|
||||
<div key={index} className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||||
<div className="text-sm text-gray-400">{stat.label}</div>
|
||||
<div className="text-purple-400 font-medium mt-1">{stat.value}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Price Stats */}
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{priceStats.map((item, index) => (
|
||||
<div key={index} className="bg-gray-800 rounded-lg p-3 text-center">
|
||||
<div className="text-sm text-gray-400">{item.label}</div>
|
||||
<div className="text-white font-medium">{item.value}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{/* Timeline Chart */}
|
||||
<div className="bg-gray-800/50 rounded-lg p-4 h-[200px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={timelineData}>
|
||||
<XAxis
|
||||
dataKey="year"
|
||||
stroke="#4B5563"
|
||||
tick={{ fill: '#9CA3AF', fontSize: 12 }}
|
||||
/>
|
||||
<YAxis
|
||||
stroke="#4B5563"
|
||||
tick={{ fill: '#9CA3AF', fontSize: 12 }}
|
||||
domain={['auto', 'auto']}
|
||||
hide
|
||||
/>
|
||||
<Tooltip content={<CustomTooltip />} />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke="#8B5CF6"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
|
|
@ -14,13 +14,11 @@
|
|||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue