c1cc70eeb9
Full rebrand: UI display text, package scope (@ai-tycoon/* -> @token-empire/*), localStorage keys, Docker/CI image paths, database names, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
142 lines
6.3 KiB
TypeScript
142 lines
6.3 KiB
TypeScript
import { useState } from 'react';
|
|
import { useGameStore } from '@/store';
|
|
import { formatMoney } from '@token-empire/shared';
|
|
|
|
function DevButton({ onClick, children, variant = 'default' }: {
|
|
onClick: () => void;
|
|
children: React.ReactNode;
|
|
variant?: 'default' | 'success';
|
|
}) {
|
|
const cls = variant === 'success'
|
|
? 'bg-emerald-500/20 hover:bg-emerald-500/30 border-emerald-500/50 text-emerald-400'
|
|
: 'bg-surface-800 hover:bg-surface-700 border-surface-600 text-surface-300';
|
|
return (
|
|
<button onClick={onClick} className={`px-2 py-1 rounded text-xs border ${cls}`}>
|
|
{children}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
function DevInput({ value, onChange, placeholder, className = '' }: {
|
|
value: string;
|
|
onChange: (v: string) => void;
|
|
placeholder?: string;
|
|
className?: string;
|
|
}) {
|
|
return (
|
|
<input
|
|
type="number"
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
placeholder={placeholder}
|
|
className={`bg-surface-800 border border-surface-600 rounded px-2 py-1 text-xs text-surface-100 w-24 ${className}`}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function ResourcesTab() {
|
|
const money = useGameStore((s) => s.economy.money);
|
|
const reputation = useGameStore((s) => s.reputation);
|
|
const researchPoints = useGameStore((s) => s.research.researchPoints);
|
|
const totalTrainingTokens = useGameStore((s) => s.data.totalTrainingTokens);
|
|
|
|
const [customMoney, setCustomMoney] = useState('');
|
|
const [customTokens, setCustomTokens] = useState('');
|
|
const [customRP, setCustomRP] = useState('');
|
|
|
|
const addMoney = (amount: number) => {
|
|
useGameStore.setState((s) => ({ economy: { ...s.economy, money: s.economy.money + amount } }));
|
|
};
|
|
|
|
const setMoney = (amount: number) => {
|
|
useGameStore.setState((s) => ({ economy: { ...s.economy, money: amount } }));
|
|
};
|
|
|
|
const setRepField = (field: 'safetyRecord' | 'publicPerception' | 'employeeSatisfaction' | 'regulatoryStanding', value: number) => {
|
|
const clamped = Math.max(0, Math.min(100, value));
|
|
useGameStore.setState((s) => ({ reputation: { ...s.reputation, [field]: clamped } }));
|
|
};
|
|
|
|
const addResearchPoints = (amount: number) => {
|
|
useGameStore.setState((s) => ({ research: { ...s.research, researchPoints: s.research.researchPoints + amount } }));
|
|
};
|
|
|
|
const addTokens = (amount: number) => {
|
|
useGameStore.setState((s) => ({ data: { ...s.data, totalTrainingTokens: s.data.totalTrainingTokens + amount } }));
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div>
|
|
<div className="text-[10px] uppercase tracking-wider text-surface-500 mb-1.5 font-semibold">
|
|
Money <span className="text-surface-400 normal-case">({formatMoney(money)})</span>
|
|
</div>
|
|
<div className="flex flex-wrap gap-1.5">
|
|
<DevButton onClick={() => addMoney(100_000)} variant="success">+100K</DevButton>
|
|
<DevButton onClick={() => addMoney(1_000_000)} variant="success">+1M</DevButton>
|
|
<DevButton onClick={() => addMoney(10_000_000)} variant="success">+10M</DevButton>
|
|
<DevButton onClick={() => addMoney(1_000_000_000)} variant="success">+1B</DevButton>
|
|
</div>
|
|
<div className="flex gap-1.5 mt-1.5">
|
|
<DevInput value={customMoney} onChange={setCustomMoney} placeholder="Amount" />
|
|
<DevButton onClick={() => { if (customMoney) setMoney(Number(customMoney)); }}>Set</DevButton>
|
|
<DevButton onClick={() => { if (customMoney) addMoney(Number(customMoney)); }} variant="success">Add</DevButton>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="text-[10px] uppercase tracking-wider text-surface-500 mb-1.5 font-semibold">
|
|
Reputation <span className="text-surface-400 normal-case">(score: {reputation.score})</span>
|
|
</div>
|
|
<div className="space-y-1">
|
|
{([
|
|
['safetyRecord', 'Safety Record', reputation.safetyRecord],
|
|
['publicPerception', 'Public Perception', reputation.publicPerception],
|
|
['employeeSatisfaction', 'Employee Satisfaction', reputation.employeeSatisfaction],
|
|
['regulatoryStanding', 'Regulatory Standing', reputation.regulatoryStanding],
|
|
] as const).map(([field, label, val]) => (
|
|
<div key={field} className="flex items-center gap-2">
|
|
<span className="text-xs text-surface-400 w-32">{label}</span>
|
|
<input
|
|
type="range"
|
|
min={0}
|
|
max={100}
|
|
value={Math.round(val)}
|
|
onChange={(e) => setRepField(field, Number(e.target.value))}
|
|
className="flex-1 h-1 accent-accent"
|
|
/>
|
|
<span className="text-xs font-mono text-surface-100 w-8 text-right">{Math.round(val)}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="text-[10px] uppercase tracking-wider text-surface-500 mb-1.5 font-semibold">
|
|
Research Points <span className="text-surface-400 normal-case">({researchPoints.toFixed(1)})</span>
|
|
</div>
|
|
<div className="flex gap-1.5">
|
|
<DevButton onClick={() => addResearchPoints(5)} variant="success">+5</DevButton>
|
|
<DevButton onClick={() => addResearchPoints(25)} variant="success">+25</DevButton>
|
|
<DevButton onClick={() => addResearchPoints(100)} variant="success">+100</DevButton>
|
|
<DevInput value={customRP} onChange={setCustomRP} placeholder="Amount" />
|
|
<DevButton onClick={() => { if (customRP) addResearchPoints(Number(customRP)); }} variant="success">Add</DevButton>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="text-[10px] uppercase tracking-wider text-surface-500 mb-1.5 font-semibold">
|
|
Training Tokens <span className="text-surface-400 normal-case">({(totalTrainingTokens / 1e9).toFixed(1)}B)</span>
|
|
</div>
|
|
<div className="flex gap-1.5">
|
|
<DevButton onClick={() => addTokens(1_000_000_000)} variant="success">+1B</DevButton>
|
|
<DevButton onClick={() => addTokens(10_000_000_000)} variant="success">+10B</DevButton>
|
|
<DevButton onClick={() => addTokens(100_000_000_000)} variant="success">+100B</DevButton>
|
|
<DevInput value={customTokens} onChange={setCustomTokens} placeholder="Amount" />
|
|
<DevButton onClick={() => { if (customTokens) addTokens(Number(customTokens)); }} variant="success">Add</DevButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|