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

85 lines
2.5 KiB
TypeScript

import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useApi } from "../api/context";
import { serverNow, syncClock } from "../clock/clock";
import { errorMessage, useLoadedPlayer } from "../state/actions";
import { PLAYER_STATE_KEY } from "../state/player";
import { Button } from "../ui";
const MINUTE = 60_000;
/**
* Settings → Developer (non-production builds only, CR-011): fast-forward the
* server clock, add credits, or land every flight now.
*/
export function DevTools() {
const api = useApi();
const queryClient = useQueryClient();
const state = useLoadedPlayer();
const refresh = async () => {
await syncClock(api);
await queryClient.invalidateQueries({ queryKey: PLAYER_STATE_KEY });
await queryClient.invalidateQueries({ queryKey: ["board"] });
};
const advance = useMutation({
mutationFn: (advanceMs: number) => api.call("devAdvanceClock", { advanceMs }),
onSuccess: refresh,
});
const credits = useMutation({
mutationFn: () => api.call("devAddCredits", { amount: 10_000 }),
onSuccess: refresh,
});
const lastArrival = Math.max(0, ...state.activeDispatches.map((d) => d.arrivalAt));
const busy = advance.isPending || credits.isPending;
const error = advance.error ?? credits.error;
return (
<div className="space-y-2">
<div className="flex flex-wrap gap-2">
<Button
needsServer
variant="secondary"
size="sm"
disabled={busy}
onClick={() => advance.mutate(10 * MINUTE)}
>
Advance 10 minutes
</Button>
<Button
needsServer
variant="secondary"
size="sm"
disabled={busy}
onClick={() => advance.mutate(60 * MINUTE)}
>
Advance 1 hour
</Button>
<Button
needsServer
variant="secondary"
size="sm"
disabled={busy}
onClick={() => credits.mutate()}
>
Add 10,000 credits
</Button>
<Button
needsServer
variant="secondary"
size="sm"
disabled={busy || lastArrival <= serverNow()}
onClick={() =>
advance.mutate(Math.max(1000, Math.ceil(lastArrival - serverNow()) + 1000))
}
>
Finish all flights
</Button>
</div>
{error && (
<p role="alert" className="text-sm text-rose-300">
{errorMessage(error)}
</p>
)}
</div>
);
}