deadhead-space-freight-tycoon/apps/web/src/screens/HQ.tsx

74 lines
2.8 KiB
TypeScript

import { content } from "@deadhead/content";
import { realToGame } from "@deadhead/sim";
import { useClock } from "../clock/clock";
import { formatGameTime } from "../clock/GameClock";
import { Countdown } from "../components/Countdown";
import { GoalsCard } from "../components/GoalsCard";
import { LoanCard } from "../components/LoanCard";
import { formatCredits, locationName } from "../format";
import { useLoadedPlayer } from "../state/actions";
export function HQ() {
const state = useLoadedPlayer();
const now = useClock((s) => s.now);
const idle = state.ships.filter((s) => s.status === "idle").length;
const flying = state.ships.filter((s) => s.status === "in-flight").length;
const runsBeforeDeal = content.config.tutorialRunsBeforeDeal;
const next = [...state.activeDispatches].sort((a, b) => a.arrivalAt - b.arrivalAt)[0];
return (
<section className="space-y-4 p-4">
<h1 className="text-xl font-semibold">HQ</h1>
<div className="grid grid-cols-2 gap-3">
<Stat label="Credits" value={formatCredits(state.company.credits)} />
<Stat label="Game date" value={formatGameTime(realToGame(now, content.config))} />
<Stat label="Ships idle" value={String(idle)} />
<Stat label="Ships in flight" value={String(flying)} />
</div>
<div className="rounded-lg border border-slate-800 p-3">
<h2 className="text-sm font-semibold text-slate-300">Next arrival</h2>
{next ? (
<p className="mt-1">
{locationName(next.originId)} → {locationName(next.destinationId)} in{" "}
<Countdown to={next.arrivalAt} />
</p>
) : (
<p className="mt-1 text-sm text-slate-400">Nothing in flight.</p>
)}
</div>
{!state.tutorial && state.ships.length === 0 && (
<p className="text-sm text-slate-400">No ships yet — buy one in the Market.</p>
)}
{state.tutorial && (
<div className="rounded-lg border border-amber-500/40 bg-amber-500/10 p-3">
<h2 className="font-semibold text-amber-300">Flying for Halvorsen Lunar Freight</h2>
<p aria-label="Company runs" className="mt-1 text-sm text-slate-300">
Company runs: {Math.min(state.tutorial.runsCompleted, runsBeforeDeal)} of{" "}
{runsBeforeDeal}
</p>
<p className="mt-1 text-xs text-slate-400">
Keep flying — the old man has an offer for you.
</p>
</div>
)}
{!state.tutorial && <GoalsCard />}
{!state.tutorial && state.company.loanBalance > 0 && <LoanCard />}
</section>
);
}
function Stat({ label, value }: { label: string; value: string }) {
return (
<div className="rounded-lg border border-slate-800 p-3">
<div className="text-xs text-slate-400">{label}</div>
<div className="mt-1 font-semibold tabular-nums">{value}</div>
</div>
);
}