import type { Contract, PlayerState } from "@deadhead/schema"; import { useQuery } from "@tanstack/react-query"; import { useSearchParams } from "react-router"; import { useApi } from "../api/context"; import { useClock } from "../clock/clock"; import { Countdown } from "../components/Countdown"; import { cargoName, formatCredits, formatMillionKm, locationName, skillName } from "../format"; import { distanceAt } from "../game"; import { useLoadedPlayer } from "../state/actions"; export const locationBoardKey = (locationId: string) => ["board", "location", locationId] as const; /** Skills a contract needs, e.g. "Heavy Cargo 2, Long Haul 1", or null. */ export function requirementsText(contract: Contract): string | null { const parts = [ contract.requiredSkill ? `${skillName(contract.requiredSkill.skillId)} ${contract.requiredSkill.level}` : null, contract.requiredLongHaulLevel > 0 ? `Long Haul ${contract.requiredLongHaulLevel}` : null, ].filter((p): p is string => p !== null); return parts.length > 0 ? parts.join(", ") : null; } /** * The location the Contracts screen opens on: where the most recently arrived * idle ship is, otherwise Earth (CR-002). */ export function defaultBoardLocation(state: PlayerState): string { const idle = state.ships.filter((s) => s.status === "idle" && s.locationId); idle.sort((a, b) => b.lastArrivalAt - a.lastArrivalAt); return idle[0]?.locationId ?? "earth"; } /** Freight markets of every discovered location, no bay needed (Steps 9.4, 10B.7). */ export function LocationBoards({ onSelect }: { onSelect?: (contract: Contract) => void }) { const state = useLoadedPlayer(); // `?location=moon` (from the map or Fleet) selects that location. const [params, setParams] = useSearchParams(); const discovered = state.locations.filter((l) => l.discovered).map((l) => l.id); const requested = params.get("location"); const locationId = requested && discovered.includes(requested) ? requested : defaultBoardLocation(state); const idleAt = (id: string) => state.ships.filter((s) => s.status === "idle" && s.locationId === id).length; return (
No idle ships here. Deadhead one in from the Fleet screen to take these jobs.
)}Loading contracts…
; if (board.isError) { return (No contracts left this period. Check back soon.
); } return (