'use client' import { useState } from 'react' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' import { BUILD_PART_COST, MAX_CAPACITY, MAX_LEVEL, expandCost, totalQty, upgradeCost } from '@/lib/game/ship-costs' import type { ShipState, ShipSystemDto } from '@/lib/game/ship' // SHIP SYSTEMS tab — live data. The parent (MissionControl) owns the ship state so the left // column mirrors actions immediately; this panel applies each action's response directly via // onChanged (no polling). Buttons are disabled when unaffordable or capped, using the same // cost constants the API enforces (lib/game/ship-costs.ts). interface ShipSystemsPanelProps { ship: ShipState | null narrow?: boolean onChanged: (next: ShipState) => void } export function ShipSystemsPanel({ ship, narrow, onChanged }: ShipSystemsPanelProps) { const [error, setError] = useState(null) const [busy, setBusy] = useState(false) // one action at a time — turn-based game if (!ship) { return (
LOADING SHIP SYSTEMS…
) } const resources = totalQty(ship.inventory, 'resource') const parts = totalQty(ship.inventory, 'part') async function act(url: string, body: unknown) { setBusy(true) setError(null) try { const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) const data = (await res.json()) as ShipState & { error?: string } if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`) onChanged(data) // response is the fresh ship state — apply directly } catch (err: unknown) { setError(err instanceof Error ? err.message : String(err)) } finally { setBusy(false) } } return (
{error && (
{error.toUpperCase()}
)}
{ship.systems.map((system) => ( ))}
) } function SystemCard({ system, resources, parts, busy, onAct, }: { system: ShipSystemDto resources: number parts: number busy: boolean onAct: (url: string, body: unknown) => void }) { const upgradeDisabled = busy || !system.built || system.level >= MAX_LEVEL || resources < upgradeCost(system.level) const expandDisabled = busy || !system.built || system.capacity >= MAX_CAPACITY || resources < expandCost(system.capacity) const buildDisabled = busy || system.built || parts < BUILD_PART_COST return (
{system.type} {system.built ? `LV ${system.level}` : 'OFFLINE'}

{system.built ? `LEVEL ${system.level} · CAPACITY ${system.capacity}` : 'NOT INSTALLED'}

{system.built ? `UPGRADE ${upgradeCost(system.level)}× RES · EXPAND ${expandCost(system.capacity)}× RES` : `BUILD ${BUILD_PART_COST}× PARTS`}

{system.built ? ( <> ) : ( )}
) }