ui/phase-20: ship-group inspector actions
Eight ship-group operations land on the inspector behind a single inline-form panel: split, send, load, unload, modernize, dismantle, transfer, join fleet. Each action either appends a typed command to the local order draft or surfaces a tooltip explaining the disabled state. Partial-ship operations emit an implicit breakShipGroup command before the targeted action so the engine sees a clean (Break, Action) pair on the wire. `pkg/calc.BlockUpgradeCost` migrates from `game/internal/controller/ship_group_upgrade.go` so the calc bridge can wrap a pure pkg/calc formula; the controller now imports it. The bridge surfaces the function as `core.blockUpgradeCost`, which the inspector calls once per ship block to render the modernize cost preview. `GameReport.otherRaces` is decoded from the report's player block (non-extinct, ≠ self) and feeds the transfer-to-race picker. The planet inspector's stationed-ship rows become clickable for own groups so the actions panel is reachable from the standard click flow (the renderer continues to hide on-planet groups). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -89,12 +89,23 @@ from the Phase 10 stub.
|
||||
const localPlayerDrive = $derived(
|
||||
renderedReport?.report?.localPlayerDrive ?? 0,
|
||||
);
|
||||
const localPlayerWeapons = $derived(
|
||||
renderedReport?.report?.localPlayerWeapons ?? 0,
|
||||
);
|
||||
const localPlayerShields = $derived(
|
||||
renderedReport?.report?.localPlayerShields ?? 0,
|
||||
);
|
||||
const localPlayerCargo = $derived(
|
||||
renderedReport?.report?.localPlayerCargo ?? 0,
|
||||
);
|
||||
const localShipGroups = $derived(
|
||||
renderedReport?.report?.localShipGroups ?? [],
|
||||
);
|
||||
const otherShipGroups = $derived(
|
||||
renderedReport?.report?.otherShipGroups ?? [],
|
||||
);
|
||||
const localFleets = $derived(renderedReport?.report?.localFleets ?? []);
|
||||
const otherRaces = $derived(renderedReport?.report?.otherRaces ?? []);
|
||||
const localRace = $derived(renderedReport?.report?.race ?? "");
|
||||
</script>
|
||||
|
||||
@@ -113,7 +124,19 @@ from the Phase 10 stub.
|
||||
{localRace}
|
||||
/>
|
||||
{:else if selectedShipGroup !== null}
|
||||
<ShipGroup selection={selectedShipGroup} planets={allPlanets} />
|
||||
<ShipGroup
|
||||
selection={selectedShipGroup}
|
||||
planets={allPlanets}
|
||||
{localShipClass}
|
||||
{localFleets}
|
||||
{otherRaces}
|
||||
{mapWidth}
|
||||
{mapHeight}
|
||||
{localPlayerDrive}
|
||||
{localPlayerWeapons}
|
||||
{localPlayerShields}
|
||||
{localPlayerCargo}
|
||||
/>
|
||||
{:else}
|
||||
<h3>{i18n.t("game.sidebar.tab.inspector")}</h3>
|
||||
<p>{i18n.t("game.sidebar.empty.inspector")}</p>
|
||||
|
||||
@@ -77,9 +77,57 @@ Tests exercise the tab through `__galaxyDebug.seedOrderDraft`
|
||||
return i18n.t("game.sidebar.order.label.ship_class_remove", {
|
||||
name: cmd.name,
|
||||
});
|
||||
case "breakShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_break", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
quantity: String(cmd.quantity),
|
||||
});
|
||||
case "sendShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_send", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
destination: String(cmd.destinationPlanetNumber),
|
||||
});
|
||||
case "loadShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_load", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
cargo: cmd.cargo,
|
||||
quantity: String(cmd.quantity),
|
||||
});
|
||||
case "unloadShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_unload", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
quantity: String(cmd.quantity),
|
||||
});
|
||||
case "upgradeShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_upgrade", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
tech: cmd.tech,
|
||||
level: String(cmd.level),
|
||||
});
|
||||
case "dismantleShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_dismantle", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
});
|
||||
case "transferShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_transfer", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
acceptor: cmd.acceptor,
|
||||
});
|
||||
case "joinFleetShipGroup":
|
||||
return i18n.t("game.sidebar.order.label.ship_group_join_fleet", {
|
||||
group: shortGroupId(cmd.groupId),
|
||||
fleet: cmd.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Short identifier for the order-tab so the human-readable label
|
||||
// stays glanceable; the full UUID is still in the underlying
|
||||
// command and visible in the inspector overlay.
|
||||
function shortGroupId(uuid: string): string {
|
||||
return uuid.length > 8 ? uuid.slice(0, 8) : uuid;
|
||||
}
|
||||
|
||||
function statusOf(cmd: OrderCommand): CommandStatus {
|
||||
return draft?.statuses[cmd.id] ?? "draft";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user