feat(ui): active-tasks strip bottom-left — active first, pending dimmed (#44)
This commit is contained in:
@@ -16,6 +16,7 @@ import { MissionPanel } from '@/components/missions'
|
|||||||
import { NextTurnButton } from '@/components/next-turn-button'
|
import { NextTurnButton } from '@/components/next-turn-button'
|
||||||
import { ShipSystemsPanel } from '@/components/ship-systems'
|
import { ShipSystemsPanel } from '@/components/ship-systems'
|
||||||
import { SkillTreePanel } from '@/components/skill-tree'
|
import { SkillTreePanel } from '@/components/skill-tree'
|
||||||
|
import { TaskStrip } from '@/components/task-strip'
|
||||||
import { WorldMapPanel } from '@/components/world-map'
|
import { WorldMapPanel } from '@/components/world-map'
|
||||||
import { CREW_CAPACITY } from '@/lib/game/ship-costs'
|
import { CREW_CAPACITY } from '@/lib/game/ship-costs'
|
||||||
import type { CrewState, SystemState } from '@/lib/game/save'
|
import type { CrewState, SystemState } from '@/lib/game/save'
|
||||||
@@ -562,6 +563,12 @@ export function MissionControl() {
|
|||||||
stays visible on every tab (Radix unmounts inactive tabs — the button only refreshes
|
stays visible on every tab (Radix unmounts inactive tabs — the button only refreshes
|
||||||
the snapshots this shell owns) */}
|
the snapshots this shell owns) */}
|
||||||
<NextTurnButton turn={ship?.turn ?? null} onTicked={refreshAll} />
|
<NextTurnButton turn={ship?.turn ?? null} onTicked={refreshAll} />
|
||||||
|
|
||||||
|
{/* #44 — the active-tasks strip: fixed bottom-left (same mount convention as the button —
|
||||||
|
outside the tab grid so it stays visible on every tab). Data: the shell's system
|
||||||
|
snapshot (JC-15) — refreshAll re-runs /api/system on every turn, so it updates on
|
||||||
|
every shell refresh with no fetch of its own. */}
|
||||||
|
<TaskStrip tasks={system?.tasks ?? []} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import type { QueueDto } from '@/lib/game/save'
|
||||||
|
|
||||||
|
// TASK STRIP — the save's task queue, fixed bottom-left next to the NEXT TURN button (#44).
|
||||||
|
// The array arrives pre-ordered from the snapshot builder (Task 6: ACTIVE block, then PENDING
|
||||||
|
// block, each by (queuedAtTurn, id)) — the strip renders it as-is, dimming the PENDING rows,
|
||||||
|
// and never fetches or re-sorts. Empty queue → null, no box at all. The shell re-renders it on
|
||||||
|
// every refreshAll (Task 7) — a pure display of the array it is handed.
|
||||||
|
|
||||||
|
export function TaskStrip({ tasks }: { tasks: QueueDto[] }) {
|
||||||
|
if (tasks.length === 0) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
left: '1rem',
|
||||||
|
bottom: '1rem',
|
||||||
|
zIndex: 60, // above the header/footer's 50
|
||||||
|
background: 'var(--surface)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
padding: '0.5rem 0.75rem',
|
||||||
|
maxWidth: '26rem',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ display: 'block', fontSize: '0.6rem', color: 'var(--text-muted)', letterSpacing: '0.12em', marginBottom: '0.3rem' }}>
|
||||||
|
ACTIVE TASKS
|
||||||
|
</span>
|
||||||
|
{tasks.map((t) => (
|
||||||
|
<div
|
||||||
|
key={t.id}
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
gap: '0.75rem',
|
||||||
|
padding: '0.2rem 0',
|
||||||
|
opacity: t.status === 'PENDING' ? 0.45 : 1, // dim, don't reorder — the array is the order
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ fontSize: '0.62rem', color: 'var(--text-secondary)', letterSpacing: '0.06em' }}>
|
||||||
|
{t.type} // {t.targetLabel}
|
||||||
|
</span>
|
||||||
|
<span style={{ fontSize: '0.62rem', color: 'var(--text-muted)', letterSpacing: '0.04em', whiteSpace: 'nowrap' }}>
|
||||||
|
{t.leadName}
|
||||||
|
{t.helperNames.length > 0 ? ` +${t.helperNames.join(' +')}` : ''}
|
||||||
|
{' — '}
|
||||||
|
{t.status === 'ACTIVE' ? `${t.remaining} turn(s) left` : 'queued'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user