Add Week 3 polish and late-game features
VC funding system (seed through IPO with requirements gating), 15 achievements with engine checker, model tuning presets and unlockable sliders, overload policy controls, open-source mechanic with reputation boost, enhanced Recharts analytics (subscriber/reputation/revenue vs expenses charts), M&A acquisition system, sidebar NEW badges on era transitions, tutorial hints, and wired-up settings toggles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,8 @@ import {
|
||||
DollarSign, Server, Brain, Users, TrendingUp,
|
||||
TrendingDown, Minus, Cpu, Zap, Shield,
|
||||
} from 'lucide-react';
|
||||
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, Area, AreaChart } from 'recharts';
|
||||
import { XAxis, YAxis, Tooltip, ResponsiveContainer, Area, AreaChart } from 'recharts';
|
||||
import { TutorialHint } from '@/components/game/TutorialHint';
|
||||
|
||||
export function DashboardPage() {
|
||||
const money = useGameStore((s) => s.economy.money);
|
||||
@@ -26,6 +27,24 @@ export function DashboardPage() {
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-2xl font-bold">Dashboard</h2>
|
||||
|
||||
{dataCenters.length === 0 && (
|
||||
<TutorialHint id="welcome">
|
||||
Welcome to AI Tycoon! Start by building a data center in the Infrastructure tab, then buy GPUs to begin training your first AI model.
|
||||
</TutorialHint>
|
||||
)}
|
||||
|
||||
{dataCenters.length > 0 && trainedModels.length === 0 && !activeTraining && (
|
||||
<TutorialHint id="train-first-model">
|
||||
You have compute available! Head to the Models tab to allocate compute for training and start your first model.
|
||||
</TutorialHint>
|
||||
)}
|
||||
|
||||
{trainedModels.length > 0 && !trainedModels.some(m => m.isDeployed) && (
|
||||
<TutorialHint id="deploy-model">
|
||||
Your model is trained! Deploy it from the Models tab to start serving customers and earning revenue.
|
||||
</TutorialHint>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<StatCard
|
||||
icon={DollarSign}
|
||||
@@ -115,6 +134,62 @@ export function DashboardPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="bg-surface-900 border border-surface-700 rounded-xl p-4">
|
||||
<h3 className="text-sm font-medium text-surface-400 mb-4">Subscribers Over Time</h3>
|
||||
{(useGameStore.getState().market.subscriberHistory?.length ?? 0) > 1 ? (
|
||||
<ResponsiveContainer width="100%" height={180}>
|
||||
<AreaChart data={useGameStore.getState().market.subscriberHistory}>
|
||||
<defs>
|
||||
<linearGradient id="subsGrad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stopColor="#f97316" stopOpacity={0.3} />
|
||||
<stop offset="100%" stopColor="#f97316" stopOpacity={0} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<XAxis dataKey="tick" hide />
|
||||
<YAxis hide />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1e293b', border: '1px solid #334155', borderRadius: '8px' }}
|
||||
formatter={(value: number) => [formatNumber(value), 'Subscribers']}
|
||||
/>
|
||||
<Area type="monotone" dataKey="subscribers" stroke="#f97316" fill="url(#subsGrad)" />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<div className="h-[180px] flex items-center justify-center text-surface-500 text-sm">
|
||||
No subscriber data yet
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="bg-surface-900 border border-surface-700 rounded-xl p-4">
|
||||
<h3 className="text-sm font-medium text-surface-400 mb-4">Reputation Over Time</h3>
|
||||
{(useGameStore.getState().reputation.reputationHistory?.length ?? 0) > 1 ? (
|
||||
<ResponsiveContainer width="100%" height={180}>
|
||||
<AreaChart data={useGameStore.getState().reputation.reputationHistory}>
|
||||
<defs>
|
||||
<linearGradient id="repGrad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stopColor="#a855f7" stopOpacity={0.3} />
|
||||
<stop offset="100%" stopColor="#a855f7" stopOpacity={0} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<XAxis dataKey="tick" hide />
|
||||
<YAxis hide domain={[0, 100]} />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1e293b', border: '1px solid #334155', borderRadius: '8px' }}
|
||||
formatter={(value: number) => [`${value}/100`, 'Reputation']}
|
||||
/>
|
||||
<Area type="monotone" dataKey="score" stroke="#a855f7" fill="url(#repGrad)" />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<div className="h-[180px] flex items-center justify-center text-surface-500 text-sm">
|
||||
No reputation data yet
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{dataCenters.length === 0 && (
|
||||
<div className="bg-surface-900 border border-accent/30 rounded-xl p-6 text-center">
|
||||
<h3 className="text-lg font-semibold mb-2">Get Started</h3>
|
||||
|
||||
Reference in New Issue
Block a user