Flight queue UI: dotted map line, left-pane Queue sub-section, e2e (ISS-043 part 2)
CI / build + unit + e2e (pull_request) Failing after 6m51s
CI / build + unit + e2e (pull_request) Failing after 6m51s
This commit is contained in:
+56
-1
@@ -107,6 +107,10 @@ export default function LeftPane({ state, loading, error, onRefresh, applySnapsh
|
||||
// a sensible default (first grounded plane with fuel below max).
|
||||
const [refuelPlaneId, setRefuelPlaneId] = useState<string | null>(null);
|
||||
|
||||
// ISS-043 (v0.26.0): flight-queue "add" destination — one shared pick across every on-board
|
||||
// block's queue-add select (the e2e fleet is a single plane; per-block state would be dead weight).
|
||||
const [queueAddDestIcao, setQueueAddDestIcao] = useState<string | null>(null);
|
||||
|
||||
// ISS-010 (v0.18.0): one-time /api/airports fetch per page life — destination options for the
|
||||
// Relocate section, sorted by name so e2e selection is stable. Same promise-ref pattern as Map.tsx;
|
||||
// on failure airportOptions stays null and the Relocate button simply remains disabled. Moved here
|
||||
@@ -200,7 +204,11 @@ export default function LeftPane({ state, loading, error, onRefresh, applySnapsh
|
||||
// cargo or is mid-flight gets a block — its loaded/expired packages with fly-to-destination +
|
||||
// abandon controls, and flying planes show their current leg.
|
||||
const clockMs = state?.simState.clockMs ?? 0;
|
||||
const onboard = state ? state.planes.filter((p) => p.status === 'flying' || slotsUsedFor(state, p.id) > 0) : [];
|
||||
// ISS-043 (v0.26.0): a plane with queued legs always shows its block too — the queue is the
|
||||
// reason it's here even when grounded with nothing on board.
|
||||
const onboard = state
|
||||
? state.planes.filter((p) => p.status === 'flying' || slotsUsedFor(state, p.id) > 0 || (p.queue?.length ?? 0) > 0)
|
||||
: [];
|
||||
|
||||
// ISS-023 (v0.21.0): Relocate — any GROUNDED plane can be repositioned to any airport via the
|
||||
// existing fly endpoint (pure repositioning, no package needed since v0.12.0). Moved here from
|
||||
@@ -455,6 +463,53 @@ export default function LeftPane({ state, loading, error, onRefresh, applySnapsh
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{/* ISS-043 (v0.26.0): flight queue — the not-yet-started legs with cancel, plus an
|
||||
add control reusing this pane's already-fetched airport options (no second fetch). */}
|
||||
<div className="queue-subsection">
|
||||
<span className="queue-heading">Queue</span>
|
||||
{plane.queue.map((icao, i) => (
|
||||
<div key={`${icao}-${i}`} data-testid={`queue-leg-${i}`} className="queue-row">
|
||||
<span className="contract-route">
|
||||
{airportOptions?.find((a) => a.icao === icao)?.name ?? icao} ({icao})
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
data-testid={`queue-cancel-${i}`}
|
||||
className="pane-btn"
|
||||
disabled={actionsBusy}
|
||||
onClick={() => void runAction(`/api/planes/${plane.id}/queue/cancel`, { index: i })}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<div className="market-row">
|
||||
<select
|
||||
data-testid="queue-add-dest"
|
||||
aria-label="Airport to add to the flight queue"
|
||||
value={queueAddDestIcao ?? ''}
|
||||
onChange={(e) => setQueueAddDestIcao(e.target.value || null)}
|
||||
>
|
||||
<option value="">Select an airport…</option>
|
||||
{airportOptions?.map((a) => (
|
||||
<option key={a.icao} value={a.icao}>
|
||||
{a.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
data-testid="queue-add"
|
||||
className="pane-btn"
|
||||
disabled={actionsBusy || queueAddDestIcao === null}
|
||||
onClick={() => {
|
||||
if (queueAddDestIcao) void runAction(`/api/planes/${plane.id}/queue`, { destIcao: queueAddDestIcao });
|
||||
}}
|
||||
>
|
||||
Add to queue
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user