Polish Week 1: tooltips, save import, game balance tuning
Add reusable Tooltip component and rich tooltips on all TopBar KPIs (cash breakdown, compute utilization, reputation context). Add save import button to Settings page. Fix game balance: reduce GPU maintenance 100x, increase organic API demand 200x, accelerate subscription revenue timescale, boost early subscriber seeding, use sqrt scaling for model compute factor, simplify deploy to activate all product lines at once. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { useRef } from 'react';
|
||||
import { useGameStore } from '@/store';
|
||||
|
||||
export function SettingsPage() {
|
||||
const settings = useGameStore((s) => s.meta.settings);
|
||||
const companyName = useGameStore((s) => s.meta.companyName);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleReset = () => {
|
||||
if (confirm('Are you sure you want to reset all progress? This cannot be undone.')) {
|
||||
@@ -23,6 +25,31 @@ export function SettingsPage() {
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
const handleImport = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.target?.result as string);
|
||||
if (!data.meta?.companyName) {
|
||||
alert('Invalid save file: missing company data.');
|
||||
return;
|
||||
}
|
||||
if (!confirm(`Import save for "${data.meta.companyName}"? This will replace your current game.`)) {
|
||||
return;
|
||||
}
|
||||
localStorage.setItem('ai-tycoon-save', JSON.stringify({ state: data }));
|
||||
window.location.reload();
|
||||
} catch {
|
||||
alert('Failed to read save file. Make sure it is a valid AI Tycoon export.');
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
if (fileInputRef.current) fileInputRef.current.value = '';
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6 max-w-2xl">
|
||||
<h2 className="text-2xl font-bold">Settings</h2>
|
||||
@@ -56,6 +83,19 @@ export function SettingsPage() {
|
||||
>
|
||||
Export Save
|
||||
</button>
|
||||
<button
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
className="px-4 py-2 rounded bg-surface-800 hover:bg-surface-700 border border-surface-600 text-sm"
|
||||
>
|
||||
Import Save
|
||||
</button>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept=".json"
|
||||
onChange={handleImport}
|
||||
className="hidden"
|
||||
/>
|
||||
<button
|
||||
onClick={handleReset}
|
||||
className="px-4 py-2 rounded bg-danger/20 hover:bg-danger/30 border border-danger/50 text-danger text-sm"
|
||||
|
||||
Reference in New Issue
Block a user