feat(ui): team builder — lead + helpers with live duration preview, wired into the action panels (#44)

This commit is contained in:
2026-10-02 20:34:14 +00:00
parent 07c1508999
commit a199b64348
9 changed files with 374 additions and 62 deletions
+11 -3
View File
@@ -26,7 +26,10 @@ export interface WorldSystemDto {
// One row of the snapshot task queue — what the GET builders expose of the tasks table
// (distinct from the tick's TickResult, which reports every row including DONE): the display
// fields the UI needs, names resolved, no raw payload.
// fields the UI needs, names resolved, no raw payload — plus the raw row state (JC-11):
// `status` (the array's ACTIVE-block-first order isn't readable back from it) and the crew
// ids, which the team builder needs for exact member↔row matching (name matching breaks on
// the `unknown` fallback).
export interface QueueDto {
id: number
type: TaskType
@@ -34,6 +37,9 @@ export interface QueueDto {
leadName: string
helperNames: string[]
remaining: number
status: TaskStatus // ACTIVE block first in the array, then PENDING
leadCrewId: number // crew.id of the team lead
helperCrewIds: number[] // crew.id of the supporting crew (degrades to [] on a corrupted blob, like helperNames)
}
export interface WorldState {
@@ -251,12 +257,14 @@ async function taskQueue(db: GameDb): Promise<QueueDto[]> {
helperNames: parseHelpers(t.helpers).map(crewName),
remaining: t.remaining,
status: t.status as TaskStatus,
leadCrewId: t.leadCrewId,
helperCrewIds: parseHelpers(t.helpers),
queuedAtTurn: t.queuedAtTurn,
}))
const byQueueOrder = (rows: typeof queue) => rows.sort((a, b) => a.queuedAtTurn - b.queuedAtTurn || a.id - b.id)
const ordered = [...byQueueOrder(queue.filter((t) => t.status === 'ACTIVE')), ...byQueueOrder(queue.filter((t) => t.status === 'PENDING'))]
// The sort keys are only for ordering — the exposed shape is exactly QueueDto.
return ordered.map(({ status, queuedAtTurn, ...dto }) => dto)
// queuedAtTurn is only for ordering — the exposed shape is exactly QueueDto (status stays: JC-11).
return ordered.map(({ queuedAtTurn, ...dto }) => dto)
}
export async function getWorldState(db: GameDb): Promise<WorldState> {