Files
SpaceWanderer/components/next-turn-button.tsx

56 lines
2.3 KiB
TypeScript

'use client'
import { useState } from 'react'
import { Button } from '@/components/ui/button'
// NEXT TURN — the manual tick control (5b): a normal-flow block in the right pane (#52) carrying
// the current turn from the ship snapshot the shell holds. One click = POST /api/turn (no body);
// on success the shell re-fetches its snapshots. Review Focus 4: the button is NEVER disabled by
// game state — an empty queue is a FREE SKIP (the route always returns 200) — and the only
// transient is an in-flight request, which the handler ignores. `disabled` is never set, so the
// cva disabled:opacity-40 styling never applies either.
// #52 — the fixed bottom-right overlay became the right pane's last flex child (mission-control):
// full width, size MD, pinned to the pane bottom when the content is short (marginTop:auto) and
// scrolling with the pane when the cargo list is long. No position/zIndex any more — so the
// active-tasks strip can no longer paint over it.
export function NextTurnButton({ turn, onTicked }: { turn: number | null; onTicked: () => void }) {
const [inFlight, setInFlight] = useState(false)
const [error, setError] = useState<string | null>(null)
const tick = () => {
if (inFlight) return // the only guard — a transient, never a game-state disable
setInFlight(true)
setError(null)
fetch('/api/turn', { method: 'POST' })
.then(async (res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`)
onTicked() // the same app-wide snapshot refresh the shell uses after every other action
})
.catch((err: unknown) => setError(err instanceof Error ? err.message : String(err)))
.finally(() => setInFlight(false))
}
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
width: '100%',
marginTop: 'auto',
}}
>
{error && (
<span style={{ fontSize: '0.62rem', color: 'var(--color-red)', letterSpacing: '0.08em' }}>{error.toUpperCase()}</span>
)}
<span style={{ fontSize: '0.62rem', color: 'var(--text-muted)', letterSpacing: '0.12em' }}>
TURN {turn ?? '—'}
</span>
<Button variant="EXEC" size="MD" className="w-full" onClick={tick}>
NEXT TURN
</Button>
</div>
)
}